Fix stub DllGetVersion implementation to read Dll version and put it in correct structure. Implement GetDllVersion by using DllGetVersion function and return version
-- v2: cabinet.dll: implement DllGetVersion & GetDllVersion
From: Tobias G��rgens tobi.goergens@gmail.com
--- dlls/cabinet/cabinet.rc | 22 +++++ dlls/cabinet/cabinet.spec | 31 ++++--- dlls/cabinet/cabinet_main.c | 157 ++++++++++++++++++++++++++++++--- dlls/cabinet/tests/Makefile.in | 3 +- dlls/cabinet/tests/version.c | 73 +++++++++++++++ include/shlwapi.h | 9 ++ 6 files changed, 266 insertions(+), 29 deletions(-) create mode 100644 dlls/cabinet/tests/version.c
diff --git a/dlls/cabinet/cabinet.rc b/dlls/cabinet/cabinet.rc index 8a022909d5c..bf045d53c28 100644 --- a/dlls/cabinet/cabinet.rc +++ b/dlls/cabinet/cabinet.rc @@ -26,3 +26,25 @@ #define WINE_PRODUCTVERSION_STR "5.0"
#include "wine/wine_common_ver.rc" + +100 VERSIONINFO +FILEVERSION WINE_FILEVERSION +PRODUCTVERSION WINE_PRODUCTVERSION +FILEOS VOS_NT +FILETYPE VFT_DLL +{ + BLOCK "StringFileInfo" + { + BLOCK "1200" + { + VALUE "FileDescription", WINE_FILEDESCRIPTION_STR + VALUE "FileVersion", WINE_FILEVERSION + VALUE "FileVersionStr", WINE_FILEVERSION_STR + VALUE "InternalName", WINE_FILENAME + VALUE "LegalCopyright", WINE_LEGALCOPYRIGHT + VALUE "OriginalFilename", WINE_FILENAME_STR + VALUE "ProductName", WINE_PRODUCTNAME_STR + VALUE "ProductVersion", WINE_PRODUCTVERSION_STR + } + } +} diff --git a/dlls/cabinet/cabinet.spec b/dlls/cabinet/cabinet.spec index 96127cfc429..4de06cf303b 100644 --- a/dlls/cabinet/cabinet.spec +++ b/dlls/cabinet/cabinet.spec @@ -1,14 +1,17 @@ -1 stub GetDllVersion -2 stdcall -private DllGetVersion (ptr) -3 stdcall Extract(ptr str) -4 stub DeleteExtractedFiles -10 cdecl FCICreate(ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr) -11 cdecl FCIAddFile(long ptr ptr long ptr ptr ptr long) -12 cdecl FCIFlushFolder(long ptr ptr) -13 cdecl FCIFlushCabinet(long long ptr ptr) -14 cdecl FCIDestroy(long) -20 cdecl FDICreate(ptr ptr ptr ptr ptr ptr ptr long ptr) -21 cdecl FDIIsCabinet(long long ptr) -22 cdecl FDICopy(long ptr ptr long ptr ptr ptr) -23 cdecl FDIDestroy(long) -24 cdecl FDITruncateCabinet(long ptr long) +@ stdcall -import GetFileVersionInfoA(str long long ptr) +@ stdcall -import GetFileVersionInfoSizeA(str ptr) +@ stdcall -import VerQueryValueA(ptr str ptr ptr) +@ stdcall GetDllVersion() +@ stdcall -private DllGetVersion (ptr) +@ stdcall Extract(ptr str) +@ stub DeleteExtractedFiles +@ cdecl FCICreate(ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr ptr) +@ cdecl FCIAddFile(long ptr ptr long ptr ptr ptr long) +@ cdecl FCIFlushFolder(long ptr ptr) +@ cdecl FCIFlushCabinet(long long ptr ptr) +@ cdecl FCIDestroy(long) +@ cdecl FDICreate(ptr ptr ptr ptr ptr ptr ptr long ptr) +@ cdecl FDIIsCabinet(long long ptr) +@ cdecl FDICopy(long ptr ptr long ptr ptr ptr) +@ cdecl FDIDestroy(long) +@ cdecl FDITruncateCabinet(long ptr long) diff --git a/dlls/cabinet/cabinet_main.c b/dlls/cabinet/cabinet_main.c index f95eca93c52..4de1d817a1a 100644 --- a/dlls/cabinet/cabinet_main.c +++ b/dlls/cabinet/cabinet_main.c @@ -36,34 +36,163 @@
WINE_DEFAULT_DEBUG_CHANNEL(cabinet);
- /*********************************************************************** * DllGetVersion (CABINET.2) * - * Retrieves version information of the 'CABINET.DLL' + * Retrieves version information of the 'CABINET.DLL' using the + * CABINETDLLVERSIONINFO structure * * PARAMS - * pdvi [O] pointer to version information structure. + * cabVerInfo [O] pointer to CABINETDLLVERSIONINFO structure. * * RETURNS - * Success: S_OK - * Failure: E_INVALIDARG + * This function has no return value * * NOTES - * Supposedly returns version from IE6SP1RP1 + * Success: cabVerInfo points to mutet CABINETDLLVERSIONINFO structure + * Failure: cabVerInfo points to unmutet CABINETDLLVERSIONINFO structure + * Use GetLastError() to find out more about why the function failed + * + */ + +VOID WINAPI DllGetVersion(PCABINETDLLVERSIONINFO cabVerInfo) +{ + + LPCSTR filename; + LPCSTR subBlock; + DWORD lenVersionInfo; + VOID *data; + VOID *buffer; + UINT lenRoot; + DWORD *handleVerInfo; + VS_FIXEDFILEINFO *versionInfo; + + filename = "Cabinet.dll"; + subBlock = "\"; + lenRoot = 0; + + if (cabVerInfo == NULL){ + SetLastError(ERROR_INVALID_PARAMETER); + TRACE("Bad Parameter: Error = %ld.\n", GetLastError()); + return; + } + + handleVerInfo = malloc(sizeof(DWORD)); + if (handleVerInfo == NULL){ + SetLastError(ERROR_OUTOFMEMORY); + TRACE("Cannot create handleVerInfo: Out of memory: Error = %ld.\n", GetLastError()); + return; + } + + lenVersionInfo = GetFileVersionInfoSizeA(filename, handleVerInfo); + if (lenVersionInfo == 0){ + TRACE("Cannot set lenVersionInfo: Couldn't parse File Version Info Size: Error = %ld.\n", GetLastError()); + return; + } + + data=HeapAlloc(GetProcessHeap(), 0, lenVersionInfo); + if (data == NULL) { + SetLastError(ERROR_OUTOFMEMORY); + TRACE("Cannot create data: Out of memory: Error = %ld.\n", GetLastError()); + return; + } + + + if (GetFileVersionInfoA(filename, 0, lenVersionInfo, data) == 0){ + TRACE("Cannot get FileVersionInfo: Couldn't parse File Version Info Ressource: Error = %ld.\n", GetLastError()); + return; + } + + if (VerQueryValueA(data, subBlock, &buffer, &lenRoot) == 0){ + TRACE("Cannot query version info: Couldn't parse File Version Info Value: Error = %ld.\n", GetLastError()); + return; + } + else + { + if (lenRoot != 0) + { + versionInfo = (VS_FIXEDFILEINFO *)buffer; + if (versionInfo->dwSignature == 0xfeef04bd) + { + cabVerInfo->cbStruct = sizeof(CABINETDLLVERSIONINFO); + cabVerInfo->dwFileVersionMS = versionInfo->dwFileVersionMS; + cabVerInfo->dwFileVersionLS = versionInfo->dwFileVersionLS; + } + else + { + TRACE("Cannot verify struct: Version information has wrong signature: Error = %ld.\n", GetLastError()); + return; + } + } + else + { + TRACE("Cannot access struct: The length of the buffer holding version information is 0: Error = %ld.\n", GetLastError()); + return; + } + } +} + +/*********************************************************************** + * GetDllVersion (CABINET.2) + * + * Returns the version of the Cabinet.dll + * + * PARAMS + * This function has to parameters + * + * RETURNS + * Success: cabDllVer: string of Cabinet.dll version + * Failure: empty string. + * Use GetLastError() to find out more about why the function failed + * */ -HRESULT WINAPI DllGetVersion (DLLVERSIONINFO *pdvi) + +LPCSTR WINAPI GetDllVersion(void) { - WARN("hmmm... not right version number "5.1.1106.1"?\n"); + PCABINETDLLVERSIONINFO cabVerInfo; + LPSTR cabDllVer; + int sizeVerInfo; + DWORD FileVersionMS; + DWORD FileVersionLS; + int majorV; + int minorV; + int buildV; + int revisV; + + cabVerInfo = malloc(sizeof(CABINETDLLVERSIONINFO)); + if(cabVerInfo == NULL) { + SetLastError(ERROR_OUTOFMEMORY); + TRACE("Cannot create cabVerInfo: Out of memory: Error = %ld.\n", GetLastError()); + return ""; + } + + DllGetVersion(cabVerInfo); + if (cabVerInfo->cbStruct==0) { + TRACE("Cannot access struct: The length of the version information structure is 0: Error = %ld.\n", GetLastError()); + return ""; + } + + FileVersionMS = cabVerInfo->dwFileVersionMS; + FileVersionLS = cabVerInfo->dwFileVersionLS; + + /*length of 4 DWORDs + buffer*/ + sizeVerInfo = 32; + + cabDllVer = malloc(sizeVerInfo); + if (cabDllVer == NULL) { + SetLastError(ERROR_OUTOFMEMORY); + TRACE("Cannot create cabDllVer: Out of memory: Error = %ld.\n", GetLastError()); + return ""; + }
- if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) return E_INVALIDARG; + majorV = (int)( FileVersionMS >> 16 ) & 0xffff; + minorV = (int)( FileVersionMS >> 0 ) & 0xffff; + buildV = (int)( FileVersionLS >> 16 ) & 0xffff; + revisV = (int)( FileVersionLS >> 0 ) & 0xffff;
- pdvi->dwMajorVersion = 5; - pdvi->dwMinorVersion = 1; - pdvi->dwBuildNumber = 1106; - pdvi->dwPlatformID = 1; + snprintf(cabDllVer, sizeVerInfo, "%d.%d.%d.%d\n",majorV,minorV,buildV,revisV);
- return S_OK; + return cabDllVer; }
/* FDI callback functions */ diff --git a/dlls/cabinet/tests/Makefile.in b/dlls/cabinet/tests/Makefile.in index f301617473d..fc9fff75c7b 100644 --- a/dlls/cabinet/tests/Makefile.in +++ b/dlls/cabinet/tests/Makefile.in @@ -3,4 +3,5 @@ IMPORTS = cabinet
C_SRCS = \ extract.c \ - fdi.c + fdi.c \ + version.c diff --git a/dlls/cabinet/tests/version.c b/dlls/cabinet/tests/version.c new file mode 100644 index 00000000000..5c7f0fbc6ec --- /dev/null +++ b/dlls/cabinet/tests/version.c @@ -0,0 +1,73 @@ +#include <stdio.h> +#include <string.h> +#include <windows.h> +#include <winbase.h> +#include <wine/test.h> + + +#include "windef.h" +#define NO_SHLWAPI_REG +#include "shlwapi.h" +#undef NO_SHLWAPI_REG +#include "winbase.h" + + +typedef VOID (__stdcall *f_dllget)(PCABINETDLLVERSIONINFO); +typedef LPCSTR (__stdcall *f_getdll)(void); + + +static void test_dllget(HMODULE libHandle) +{ + PCABINETDLLVERSIONINFO verInfo; + char *version; + int sizeVerInfo; + DWORD FileVersionMS; + DWORD FileVersionLS; + int majorV; + int minorV; + int buildV; + int revisV; + + f_dllget DllGetVersion = (f_dllget)GetProcAddress(libHandle, "DllGetVersion"); + ok(libHandle != NULL, "Function DllGetVersion in DLL not found: Error = %ld.\n", GetLastError()); + + + verInfo = malloc(sizeof(CABINETDLLVERSIONINFO)); + ok(verInfo != NULL, "Couldn't allocate memory to run tests properly!\n"); + DllGetVersion(verInfo); + + FileVersionMS = verInfo->dwFileVersionMS; + FileVersionLS = verInfo->dwFileVersionLS; + + /*length of 4 DWORDs + buffer*/ + sizeVerInfo = 32; + + version = malloc(sizeVerInfo); + ok(version != NULL, "Couldn't allocate memory to run tests properly!\n"); + + majorV = (int)( FileVersionMS >> 16 ) & 0xffff; + minorV = (int)( FileVersionMS >> 0 ) & 0xffff; + buildV = (int)( FileVersionLS >> 16 ) & 0xffff; + revisV = (int)( FileVersionLS >> 0 ) & 0xffff; + + snprintf(version, sizeVerInfo, "%d.%d.%d.%d\n",majorV,minorV,buildV,revisV);; + + ok(strcmp(version,"") != 0, "Cabinet struct doesn't contain correct version: Error = %ld.\n", GetLastError()); +} + + +static void test_getdll(HMODULE libHandle) +{ + f_getdll GetDllVersion = (f_getdll)GetProcAddress(libHandle, "GetDllVersion"); + ok(libHandle != NULL, "Function GetDllVersion in DLL not found: Error = %ld.\n", GetLastError()); + ok(strcmp(GetDllVersion(),"") != 0, "GetDllVersion doesn't return correct version: Error = %ld.\n", GetLastError()); +} + +START_TEST(version) +{ + HMODULE libHandle; + libHandle = LoadLibraryA("Cabinet.dll"); + ok(libHandle != NULL, "Cabinet.dll not found: Error = %ld.\n", GetLastError()); + test_dllget(libHandle); + test_getdll(libHandle); +} diff --git a/include/shlwapi.h b/include/shlwapi.h index 6149c7081a3..028a6e7efba 100644 --- a/include/shlwapi.h +++ b/include/shlwapi.h @@ -1065,6 +1065,15 @@ typedef struct _DllVersionInfo { DWORD dwPlatformID; } DLLVERSIONINFO;
+/*version information used in cabinet.dll*/ +typedef struct _CABINETDLLVERSIONINFO { + DWORD cbStruct; + DWORD dwReserved1; + DWORD dwReserved2; + DWORD dwFileVersionMS; + DWORD dwFileVersionLS; +} CABINETDLLVERSIONINFO, *PCABINETDLLVERSIONINFO; + #define DLLVER_PLATFORM_WINDOWS 0x01 /* Win9x */ #define DLLVER_PLATFORM_NT 0x02 /* WinNT */
On Sun Jul 31 17:06:12 2022 +0000, **** wrote:
Marvin replied on the mailing list:
Hi, It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated. The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=120249 Your paranoid android. === debian11 (build log) === ../wine/dlls/cabinet/cabinet_main.c:58:13: error: conflicting types for ���DllGetVersion��� Task: The win32 Wine build failed === debian11 (build log) === ../wine/dlls/cabinet/cabinet_main.c:58:13: error: conflicting types for ���DllGetVersion��� Task: The wow64 Wine build failed
Does someone know how I can fix this? :sweat_smile:
It seems like I broke something during code clean-up. The compilation process isn't reliable for me. The function imports in the spec file don't always seem to work. Does someone know how I can fix that?
I think a first good thing to do, would be to split this into more commits. For example, the changes to the tests.
On Sun Jul 31 18:36:31 2022 +0000, Bernhard K��lbl wrote:
I think a first good thing to do, would be to split this into more commits. For example, the changes to the tests.
I'll do that, should I also split the two implementations? I don't know how helpful that would be as a) both happen in the same file and b) GetDllVersion depends on DllGetVersion. What do you think?
On Sun Jul 31 18:36:31 2022 +0000, Tobias G��rgens wrote:
I'll do that, should I also split the two implementations? I don't know how helpful that would be as a) both happen in the same file and b) GetDllVersion depends on DllGetVersion. What do you think?
It's generally wanted to only have "atomic" changes per commit, so it's easier to bisect if an issue arises in the future. So put everything into a commit that is introducing an independent feature change / new feature. So yeah, put both implementations in separate commits as well. Regarding the tests, you can mark stuff, which is going to be fixed by a future commit, with `todo_wine`. So commit tests first and the impl afterwards.
On Mon Aug 1 08:57:20 2022 +0000, Bernhard K��lbl wrote:
It's generally wanted to only have "atomic" changes per commit, so it's easier to bisect if an issue arises in the future. So put everything into a commit that is introducing an independent feature change / new feature. So yeah, put both implementations in separate commits as well. Regarding the tests, you can mark stuff, which is going to be fixed by a future commit, with `todo_wine`. So commit tests first and the impl afterwards.
Oh, and the prefix for any commit is usually the folder where you do commit to. So instead of `cabinet.dll: Do foobar.` it's just `cabinet: Do foobar.` One exception are headers, where it's `include/foo.h: Do foobar.`