Why does GetFileVersionInfo on kernel32.dll in Windows 10 return version 6.2? - c++

I am trying to retrieve kernel32.dll version in order to perform a Windows version check. Yet, for some reason, even though kernel32.dll's version (as seen in file properties) is 10.0.10586.0, the returned version is: 6.2.10586.0
how come?
DWORD dwDummy;
DWORD dwFVISize = GetFileVersionInfoSize(lpszFilePath, &dwDummy);
LPBYTE lpVersionInfo = new BYTE[dwFVISize];
if (GetFileVersionInfo(lpszFilePath, 0, dwFVISize, lpVersionInfo) == 0)
{
return FALSE;
}
UINT uLen;
VS_FIXEDFILEINFO *lpFfi;
BOOL bVer = VerQueryValue(lpVersionInfo, L"\\", (LPVOID *)&lpFfi, &uLen);
if (!bVer || uLen == 0)
{
return FALSE;
}
DWORD dwFileVersionMS = lpFfi->dwFileVersionMS;
DWORD dwFileVersionLS = lpFfi->dwFileVersionLS;
delete[] lpVersionInfo;
DWORD dwLeftMost = HIWORD(dwFileVersionMS);
DWORD dwSecondLeft = LOWORD(dwFileVersionMS);
DWORD dwSecondRight = HIWORD(dwFileVersionLS);
DWORD dwRightMost = LOWORD(dwFileVersionLS);
Kernel32.dll properties (same as in SysWow64):

You are reading the wrong fields from the version information for this task. Instead of dwFileVersionMS and dwFileVersionLS use dwProductVersionMS and dwProductVersionLS.
The file version fields are subject to supportedOS compatibility issues. That is their values depend on the supportedOS levels declared in your application manifest. On the other hand the product version fields do not depend on the manifest.

Applications not manifested for Windows 8.1 or Windows 10 will return
the Windows 8 OS version value (6.2).
this is from GetVersionEx function MSDN description. for GetFileVersionInfo no such note, but really this doing same. i look under debugger:
so 10.0 ( 0xA000) in dwFileVersionMS can be fixed to 6.2 or 6.3
but dwProductVersionMS - not changed (0xA000 ~ 10.0)
think need fix MSDN documentation for GetFileVersionInfo[Ex] :)

Related

Calling API from a x86 DLL loaded into a x64 application

This is an experiment to exploit the availability of a 32-bit "compatibility" mode selector in GDT in Windows x64 which has the value of 0x23.
I 've successfully loaded a x86 DLL into the address space of a x64 application. This is done by first taking all imports of the x86 dll and saving it into a XML, then using a modified MemoryModule to load the DLL from memory and patch the Import Address Table with those pointers.
Then, in the x64 host I jump to a compatibility code segment:
push 0x23
xor rcx,rcx
mov ecx,Start32
push rcx
retf
Start32 is a 32-bit entry point that would call a configured function:
USE32
push eax
push dword [WhatToPass]
mov eax, [WhatToCall]
call eax
pop eax
Then go back to 64-bit
USE64
db 0eah
ret_64:
dd 0
dw 0x33
nop
This works, as long as the configured exp1 function does practically nothing. The concept is fully discussed in my CodeProject article and the source is on GitHub.
It doesn't work when run in Visual Studio, but it does work when run in WinDbg; WinDbg shows a 'x86' running mode when switching.
Now the ambitious project is to call the API from the x86 module. This fails even with a simple MessageBeep(0);. I don't of course expect it at this point to go fully to the function but it doesn't even enter; I get an invalid execution instruction on the call. The address is valid.
What could be wrong? Yes this is too much perhaps but I'm still curious.
Patching the IAT works correctly. Sample code:
void PatchIAT(HINSTANCE h,std::vector<FANDP>* CustomLoading = 0)
{
PCHAR codeBase = (PCHAR)h;
XML3::XML x(xResult);
PIMAGE_NT_HEADERS32 ntheaders = (PIMAGE_NT_HEADERS32)(PCHAR(h) + PIMAGE_DOS_HEADER(h)->e_lfanew);
PIMAGE_SECTION_HEADER pSech = IMAGE_FIRST_SECTION(ntheaders);//Pointer to first section header
DWORD ulsize = 0;
PIMAGE_IMPORT_DESCRIPTOR importDesc = (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData(h, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &ulsize);
if (!importDesc)
return;
for (; importDesc && importDesc->Name; importDesc++) {
PSTR pszModName = (PSTR)((PBYTE)h + importDesc->Name);
if (!pszModName)
break;
XML3::XMLElement* module = ... ; // find the XML entry
if (!module)
continue;
DWORD* thunkRef;
DWORD* funcRef = 0;
if (importDesc->OriginalFirstThunk) {
thunkRef = (DWORD*)(codeBase + importDesc->OriginalFirstThunk);
funcRef = (DWORD*)(codeBase + importDesc->FirstThunk);
}
else {
// no hint table
thunkRef = (DWORD*)(codeBase + importDesc->FirstThunk);
funcRef = (DWORD *)(codeBase + importDesc->FirstThunk);
}
DWORD V = 0;
for (; *thunkRef; thunkRef++, funcRef++) {
DWORD* wr = (DWORD*)funcRef;
if (IMAGE_SNAP_BY_ORDINAL(*thunkRef)) {
// *funcRef = module->getProcAddress(handle, (LPCSTR)IMAGE_ORDINAL(*thunkRef), module->userdata);
const char* fe = (LPCSTR)IMAGE_ORDINAL(*thunkRef);
// find V from xml
...
}
else {
PIMAGE_IMPORT_BY_NAME thunkData = (PIMAGE_IMPORT_BY_NAME)(codeBase + (*thunkRef));
// *wr = module->getProcAddress(handle, (LPCSTR)&thunkData->Name, module->userdata);
... // Find V from XML
}
// Patch it now...
DWORD dwOldProtect = 0;
if (VirtualProtect((LPVOID)wr, 4, PAGE_READWRITE, &dwOldProtect))
{
memcpy((void*)wr, &V, 4);
VirtualProtect((LPVOID)wr, 4, dwOldProtect, &dwOldProtect);
}
VirtualProtect((LPVOID)V, 4, PAGE_EXECUTE_READWRITE, &dwOldProtect);
}
}
}

Reading network computer names using mfc in windows 10

I tried to read network computer names using WNetOpenEnum. I am getting only 'Microsoft Terminal Services', 'Microsoft Windows Network' and 'Web Client Network'. Not getting the other machine connected in network.
Is there any way to read the names/IP of computers connected to network?.
if(NO_ERROR == WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_ANY, 0, pnetrParent, &hEnum))
{
DWORD dwCount = 1;
char szBuffer[512];
char* psz = szBuffer;
DWORD dwBufferSize = sizeof(szBuffer);
while (NO_ERROR == WNetEnumResource(hEnum, &dwCount, &szBuffer, &dwBufferSize))
{
NETRESOURCE* pnetResource = (NETRESOURCE*)psz;
if (NULL != pnetResource->lpRemoteName && *pnetResource->lpRemoteName)
{
m_lstIPAddress.AddString(pnetResource->lpRemoteName);
}
dwBufferSize = sizeof(szBuffer);
}
DWORD retValue = WNetCloseEnum(hEnum);
}
Any help would be appreciated.
You need to call it recursively. Microsoft Windows Network has computers listed. So next call to WNetOpenEnum will have handle to Microsoft Windows Network you received as first parameter and so on.
I believe this would give you answer: https://learn.microsoft.com/en-us/windows/win32/wnet/enumerating-network-resources

SetupDiEnumDriverInfo returns different results on Windows 7 and Windows 8 / 10

I am debugging an application that should retrieve information about all smart card reader drivers installed on a Windows system.
The code below works on Windows 7 (64 bit):
QSet<QString> getSmartCardDriverModuleNames()
{
QSet<QString> moduleNames;
// the GUID for the smart card reader device setup class
wchar_t deviceClassGuidString[] = L"{50dd5230-ba8a-11d1-bf5d-0000f805f530}";
GUID deviceClass;
CLSIDFromString(deviceClassGuidString, &deviceClass);
HDEVINFO deviceInfoSet = SetupDiGetClassDevs(&deviceClass, NULL, NULL, 0);
if (deviceInfoSet == INVALID_HANDLE_VALUE)
{
return moduleNames;
}
SP_DEVINFO_DATA deviceInfoData;
deviceInfoData.cbSize = sizeof(deviceInfoData);
for (DWORD deviceIndex = 0;
SetupDiEnumDeviceInfo(deviceInfoSet, deviceIndex,
&deviceInfoData);
deviceIndex++)
{
if (SetupDiBuildDriverInfoList(deviceInfoSet, &deviceInfoData,
SPDIT_COMPATDRIVER))
{
SP_DRVINFO_DATA_W driverInfoData;
driverInfoData.cbSize = sizeof(driverInfoData);
for (DWORD driverIndex = 0;
SetupDiEnumDriverInfo(deviceInfoSet, &deviceInfoData,
SPDIT_COMPATDRIVER, driverIndex,
&driverInfoData);
driverIndex++)
{
// Omitted: get service name and add to moduleNames.
}
SetupDiDestroyDriverInfoList(deviceInfoSet, &deviceInfoData,
SPDIT_COMPATDRIVER);
}
}
SetupDiDestroyDeviceInfoList(deviceInfoSet);
return moduleNames;
}
This code correctly finds the installed drivers when run on Windows 7, but finds no driver at all on Windows 8 or Windows 10 (both 64 bit), even though some drivers are installed.
It turns out (by adding extra logging and debug code) that under Windows 8 and 10 the first call to SetupDiEnumDriverInfo fails. In this case, by adding a call to GetLastError() I get ERROR_NO_MORE_ITEMS, which is the normal behaviour expected when the end of the list is reached (see the documentation).
So, no errors are detected, but the result is empty.
In the documentation of the Windows API I have found no changes from Windows 7 to Windows 8, 10, so no adaptation to the above code should be needed.
Have I overlooked something? Do you have any hint as to what I should check next?

GetFIleVersionInfoSize() succeeds but returns incorrect size

I am trying to get the version of a file. I want to look at the version number of this file to determine which OS is installed on a non-booted drive (I'll actually be doing this from a Win PE environment and trying to determine if the main drive has Windows XP or Windows 7 installed). Anyway, I have the following
wchar_t *fileName;
fileName = new wchar_t[255];
lstrcpy(fileName, hdds[HardDriveIndexes::SystemDrive].driveLetter.c_str());
lstrcat(fileName, L"Windows\\System32\\winload.exe");
TCHAR *versionInfoBuffer;
DWORD versionDataSize;
if (versionDataSize = GetFileVersionInfoSize(fileName, NULL) != 0)
{
versionInfoBuffer = new TCHAR[versionDataSize];
BOOL versionInfoResult = FALSE;
versionInfoResult = GetFileVersionInfo(fileName, NULL, versionDataSize, versionInfoBuffer);
if (versionInfoResult == FALSE)
{
wprintf(L"The last error associated with getting version info is: %d\n", GetLastError());
}
}
else
{
wprintf(L"The last error associated with gettting version info size is: %d\n", GetLastError());
}
The problem is that GetFileVersionInfoSize() succeeds but always returns 1 as the size. This causes GetFileVersionInfo() to fail with error 122. So far I have only tested this on a Windows 7 system. There is another function GetFileVersionInfoSizeEx() that works as expected, but it is only supported from Vista onwards. I would like to keep XP support if possible (some of our old Win PE images are still based on XP).
Is GetFileVersionInfoSize() deprecated and I somehow can't find that information, am I using it incorrectly, etc.?
The problem isn't with the call, it's with your assignment; you need parens around it:
if ( ( versionDataSize = GetFileVersionInfoSize(fileName, NULL) ) != 0)
What you had written assigns the value of the expression size != 0, which is 1 for true.

How do I read from a version resource in Visual C++

I have a version resource in my resources in a C++ project which contains version number, copyright and build details. Is there an easy way to access this at run-time to populate my help/about dialog as I am currently maintaining seperate const values of this information. Ideally, the solution should work for Windows/CE mobile and earlier versions of Visual C++ (6.0 upwards).
This is an edited version of my original answer.
bool GetProductAndVersion(CStringA & strProductName, CStringA & strProductVersion)
{
// get the filename of the executable containing the version resource
TCHAR szFilename[MAX_PATH + 1] = {0};
if (GetModuleFileName(NULL, szFilename, MAX_PATH) == 0)
{
TRACE("GetModuleFileName failed with error %d\n", GetLastError());
return false;
}
// allocate a block of memory for the version info
DWORD dummy;
DWORD dwSize = GetFileVersionInfoSize(szFilename, &dummy);
if (dwSize == 0)
{
TRACE("GetFileVersionInfoSize failed with error %d\n", GetLastError());
return false;
}
std::vector<BYTE> data(dwSize);
// load the version info
if (!GetFileVersionInfo(szFilename, NULL, dwSize, &data[0]))
{
TRACE("GetFileVersionInfo failed with error %d\n", GetLastError());
return false;
}
// get the name and version strings
LPVOID pvProductName = NULL;
unsigned int iProductNameLen = 0;
LPVOID pvProductVersion = NULL;
unsigned int iProductVersionLen = 0;
// replace "040904e4" with the language ID of your resources
if (!VerQueryValue(&data[0], _T("\\StringFileInfo\\040904e4\\ProductName"), &pvProductName, &iProductNameLen) ||
!VerQueryValue(&data[0], _T("\\StringFileInfo\\040904e4\\ProductVersion"), &pvProductVersion, &iProductVersionLen))
{
TRACE("Can't obtain ProductName and ProductVersion from resources\n");
return false;
}
strProductName.SetString((LPCSTR)pvProductName, iProductNameLen);
strProductVersion.SetString((LPCSTR)pvProductVersion, iProductVersionLen);
return true;
}
To get a language independent result to Mark's answer change :
// replace "040904e4" with the language ID of your resources
!VerQueryValue(&data[0], _T("\\StringFileInfo\\040904e4\\ProductVersion"), &pvProductVersion, &iProductVersionLen))
{
TRACE("Can't obtain ProductName and ProductVersion from resources\n");
return false;
}
To
UINT uiVerLen = 0;
VS_FIXEDFILEINFO* pFixedInfo = 0; // pointer to fixed file info structure
// get the fixed file info (language-independent)
if(VerQueryValue(&data[0], TEXT("\\"), (void**)&pFixedInfo, (UINT *)&uiVerLen) == 0)
{
return false;
}
strProductVersion.Format("%u.%u.%u.%u",
HIWORD (pFixedInfo->dwProductVersionMS),
LOWORD (pFixedInfo->dwProductVersionMS),
HIWORD (pFixedInfo->dwProductVersionLS),
LOWORD (pFixedInfo->dwProductVersionLS));
Something like might get you started, perhaps:
TCHAR moduleName[MAX_PATH+1];
(void)GetModuleFileName(AfxGetInstanceHandle(), moduleName, MAX_PATH);
DWORD dummyZero;
DWORD versionSize = GetFileVersionInfoSize(moduleName, &dummyZero);
if(versionSize == 0)
{
return NULL;
}
void* pVersion = malloc(versionSize);
if(pVersion == NULL)
{
return NULL;
}
if(!GetFileVersionInfo(moduleName, NULL, versionSize, pVersion))
{
free(pVersion);
return NULL;
}
UINT length;
VS_FIXEDFILEINFO* pFixInfo;
VERIFY(VerQueryValue(pVersionInfo, const_cast<LPTSTR>("\\"), (LPVOID*)&pFixInfo, &length));
Something like this will give you raw access to the resource data and get you started:
HRSRC res = ::FindResource(NULL, MAKEINTRESOURCE(MY_VERSION_ID), RT_VERSION);
DWORD size = ::SizeofResource(NULL, res);
HGLOBAL mem = ::LoadResource(NULL, res);
LPVOID raw_data = ::LockResource(mem);
...
::FreeResource(mem);
Beware!
Using FindResource..LockResource is not correct. It will sometimes work (as it did in my small demo program) and sometimes cause access violations (example: the production code I was making the demo for).
The VerQueryValue() documentation states that you should call GetFileVersionInfoSize and GetFileVersionInfo instead.
Raymond Chen explains, see http://blogs.msdn.com/oldnewthing/archive/2006/12/26/1365215.aspx
Ok, a bit more googleing found the following on CodeGuru. Basically this approach uses the CFileVersionInfo object to get on any given file. It should be interesting to see if it works on the currently running .EXE file and on Windows CE.
Sometimes I receive Access Violation when use VerQueryValueA. But I never got this error when use VerQueryValueW. I think something wrong with VerQueryValueA in version.dll. Therefore I use VerQueryValueW instead of VerQueryValueA even in projects Multi-byte Character Encoding. Here is my code of ReadVersion function