3

On MSDN I noticed the following for the VerQueryValue function:

lplpBuffer [out]
LPVOID
When this method returns, contains the address of a pointer to the requested version information in the buffer pointed to by pBlock. The memory pointed to by lplpBuffer is freed when the associated pBlock memory is freed._

How does the system know when pBlock is freed since pBlock is allocated by the caller?

I'm using the following code:

UINT reqSize = ::GetSystemDirectoryW(nullptr, 1);

std::vector<wchar_t> winDirectory (reqSize, 0);

UINT retVal = ::GetSystemDirectoryW(&winDirectory[0], reqSize);

std::wstring filePath(winDirectory.begin(), winDirectory.end()-1);

filePath.append(L"\\kernel32.dll");

DWORD bufSize = ::GetFileVersionInfoSizeW(
    filePath.c_str(),
    nullptr);

std::vector<BYTE> fileInfo (bufSize, 0);

::GetFileVersionInfoW(
    filePath.c_str(),
    0,
    bufSize,
    &fileInfo[0]);

UINT size = 0;

VS_FIXEDFILEINFO * ptr = nullptr;

BOOL error = ::VerQueryValueW(
    &fileInfo[0],
    L"\\",
    reinterpret_cast<LPVOID*>(&ptr),
    &size);
links77
  • 779
  • 2
  • 7
  • 8

3 Answers3

4

VerQueryValue returns a pointer to somewhere inside the initial block of memory that you allocate (GetFileVersionInfoSize returns the size of a block that is large enough to contain the whole version resource + any space required for ansi to unicode conversion etc)

Anders
  • 97,548
  • 12
  • 110
  • 164
3

At least in some occasions, VerQueryValue performs conversion of the version data (e.g. Unicode to ASCII conversion when Unicode version of GetFileVersionInfo, but ASCII version of VerQueryValue are used). GetFileVersionInfoSize obviously computes the buffer size large enough to hold converted data.

SingerOfTheFall
  • 29,228
  • 8
  • 68
  • 105
Jaromír Adamec
  • 579
  • 4
  • 13
2

GetFileVersionInfo copies data into the supplied buffer. As the format of this data isn't readily available/documented, you need to use the helper functionVerQueryValue to retrieve pointers to specific entries within the buffer GetFileVersionInfo filled in.

The way MS documented that "The pointer returned by VerQueryValue isn't allocated from anywhere - it's just pointing to somewhere within another buffer" is somewhat confusing.

Erik
  • 88,732
  • 13
  • 198
  • 189
  • It sounds like they are saying the second pointer is pointing into the block of already allocated memory. So there is only one block of allocated memory to be freed. – Steve Wellens Apr 16 '11 at 17:44
  • @Steve Wellens: As (hopefully) all memory is allocated somehow, that's true. The description in MSDN doesn't really clarify that the "already allocated memory" actually is the buffer the user supplied to GetFileVersionInfo earlier – Erik Apr 16 '11 at 18:09
  • Well they can't do it in the destructor since it's straight C and not C++. Unless they have some other magic going on, I'm guessing/assuming/hypothesizing ;) that they are using realloc to stretch the original buffer and then making the member pointer point to the new space. So when the original memory is freed...it's all freed. – Steve Wellens Apr 16 '11 at 22:57
  • 2
    @Steve Wellens: `VerQueryValue` doesn't allocate - there's nothing to free. You pass a buffer which *you* manage to `GetFileVersionInfo`, `VerQueryValue` simply returns a pointer to somewhere inside this buffer. – Erik Apr 16 '11 at 23:03