File version of SqlOledB.dll
:
10.0.18362.1
6.2.18362.1
I am trying to get the file version of the Windows dll "C:\Program Files (x86)\Common Files\System\Ole DB\sqloledb.dll"
In Windows Explorer, I can see:
When I use Powershell:
> [System.Diagnostics.FileVersionInfo]::GetVersionInfo("C:\Program Files (x86)\Common Files\System\Ole DB\sqloledb.dll") | Format-List -property *
I can see the file version:
FileVersionRaw : 10.0.18362.1
ProductVersionRaw : 10.0.18362.1
Comments :
CompanyName : Microsoft Corporation
FileBuildPart : 18362
FileDescription : OLE DB Provider for SQL Server
FileMajorPart : 10
FileMinorPart : 0
FileName : C:\Program Files (x86)\Common Files\System\Ole DB\sqloledb.dll
FilePrivatePart : 1
FileVersion : 10.0.18362.1 (WinBuild.160101.0800)
InternalName : sqloledb.dll
IsDebug : False
IsPatched : False
IsPrivateBuild : False
IsPreRelease : False
IsSpecialBuild : False
Language : English (United States)
LegalCopyright : © Microsoft Corporation. All rights reserved.
LegalTrademarks :
OriginalFilename : sqloledb.dll
PrivateBuild :
ProductBuildPart : 18362
ProductMajorPart : 10
ProductMinorPart : 0
ProductName : Microsoft® Windows® Operating System
ProductPrivatePart : 1
ProductVersion : 10.0.18362.1
SpecialBuild :
When I look at the VersionInfo resource in the DLL, I see the file and product versions match:
1 VERSIONINFO
FILEVERSION 10,0,18362,1
PRODUCTVERSION 10,0,18362,1
FILEOS 0x40004
FILETYPE 0x2
{
BLOCK "StringFileInfo"
{
BLOCK "040904B0"
{
VALUE "CompanyName", "Microsoft Corporation"
VALUE "FileDescription", "OLE DB Provider for SQL Server"
VALUE "FileVersion", "10.0.18362.1 (WinBuild.160101.0800)"
VALUE "InternalName", "sqloledb.dll"
VALUE "LegalCopyright", "© Microsoft Corporation. All rights reserved."
VALUE "OriginalFilename", "sqloledb.dll"
VALUE "ProductName", "Microsoft® Windows® Operating System"
VALUE "ProductVersion", "10.0.18362.1"
}
}
BLOCK "VarFileInfo"
{
VALUE "Translation", 0x0409 0x04B0
}
}
When I use PEView to view the raw version resource, I see 000A0000 47BA0001
for both the file and product versions. I also see the file info string section that says:
And when I use Process Monitor, I can see my application querying the correct DLL:
But, when I query it from code, I get the wrong value!
When my 32-bit application calls:
GetFileVersionInfoSizeW()
GetFileVersionInfoW()
VerQueryValueW()
(querying for "\"
)and look at the contents of the returned VS_FIXEDFILEINFO
buffer, I see:
If you look at the fileVersion and productVersion values, and convert them to hex:
Field | Decimal | Hex |
---|---|---|
dwFileVersionMS | 393218 | 0x00060002 |
dwFileVersionLS | 1203372033 | 0x47BA0001 |
dwProductVersionMS | 655360 | 0x000A0000 |
dwProductVersionLS | 1203372033 | 0x47BA0001 |
Which gives you the versions in hex of:
0x0006
, 0x0002
, 0x47BA
, 0x0001
0x000A
, 0x0000
, 0x47BA
, 0x0001
We get the versions as decimal strings:
The product version is correct, but the file version is completely wrong.
Which begs the questions:
GetFileVersion()
API function possibly getting version 6.2.x.x
from; when everything about the DLL binary says 10.0.x.x
?SupportedOS
entries in my assembly manifest?Short Version: How is Windows returning a version value that does not exist anywhere in the binary?
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils, Windows;
function GetFileVersion(Filename: WideString): string;
var
dwHandle: Cardinal;
dwInfoLength: Cardinal;
pInfoData: Pointer;
lengthOfReturned: Cardinal;
value: Pointer;
fileInfo: PVSFixedFileInfo;
iMajor, iMinor, iBuild, iRelease: Integer;
begin
Result := '?.?.?.?';
// Get the number of bytes he have to allocate for the file information structure
dwHandle := 0;
dwInfoLength := GetFileVersionInfoSizeW(PWideChar(Filename), {var}dwHandle);
if dwInfoLength = 0 then
Exit;
// Allocate the memory needed to hold the file info
GetMem(pInfoData, dwInfoLength);
try
//Put the information into the buffer we just allocated
if not GetFileVersionInfoW(PWideChar(Filename), 0, dwInfoLength, pInfoData) then
Exit;
// Extract the desired data from pInfoData into the FileInformation structure
value := nil;
lengthOfReturned := 0;
if not VerQueryValueW(pInfoData, '\', {var}value, {var}lengthOfReturned) then
Exit;
fileInfo := PVSFixedFileInfo(value);
iMajor := fileInfo.dwFileVersionMS shr 16;
iMinor := fileInfo.dwFileVersionMS and $FFFF;
iRelease := fileInfo.dwFileVersionLS shr 16;
iBuild := fileInfo.dwFileVersionLS and $FFFF;
finally
FreeMem(pInfoData);
end;
Result := Format('%d.%d.%d.%d', [iMajor, iMinor, iRelease, iBuild]);
end;
procedure Main;
var
filename: string;
version: string;
begin
filename := 'C:\Program Files (x86)\Common Files\System\Ole DB\sqloledb.dll';
version := GetFileVersion(filename);
WriteLn('Filename: '+filename);
WriteLn('File version: '+version);
end;
begin
Main;
WriteLn('Press enter to close...');
ReadLn;
end.
I also tried using the ANSI versions (with ANSI strings), in case the legacy ANSI version had some app-compat feature that lies about version numbers.
Tried in Delphi 5 and Delphi XE6 - both 32-bit apps.
Yes, it is an app-compat shim kicking in - lying to me about the version of the .dll
i use.
Adding the Windows 10 entry
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
to my Assembly.manifest
fixes it.