1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
#include <config.h>
#include "roken.h"
#include <psapi.h>
static DWORD
GetVersionInfo(CHAR *filename, CHAR *szOutput, DWORD dwOutput)
{
DWORD dwVersionHandle;
LPVOID pVersionInfo = 0;
DWORD retval = 0;
LPDWORD pLangInfo = 0;
LPTSTR szVersion = 0;
UINT len = 0;
TCHAR szVerQ[] = TEXT("\\StringFileInfo\\12345678\\FileVersion");
DWORD size = GetFileVersionInfoSize(filename, &dwVersionHandle);
if (!size)
return GetLastError();
pVersionInfo = malloc(size);
if (!pVersionInfo)
return ERROR_NOT_ENOUGH_MEMORY;
GetFileVersionInfo(filename, dwVersionHandle, size, pVersionInfo);
if (retval = GetLastError())
goto cleanup;
VerQueryValue(pVersionInfo, TEXT("\\VarFileInfo\\Translation"),
(LPVOID*)&pLangInfo, &len);
if (retval = GetLastError())
goto cleanup;
wsprintf(szVerQ,
TEXT("\\StringFileInfo\\%04x%04x\\FileVersion"),
LOWORD(*pLangInfo), HIWORD(*pLangInfo));
VerQueryValue(pVersionInfo, szVerQ, (LPVOID*)&szVersion, &len);
if (retval = GetLastError()) {
/* try again with language 409 since the old binaries were tagged wrong */
wsprintf(szVerQ,
TEXT("\\StringFileInfo\\0409%04x\\FileVersion"),
HIWORD(*pLangInfo));
VerQueryValue(pVersionInfo, szVerQ, (LPVOID*)&szVersion, &len);
if (retval = GetLastError())
goto cleanup;
}
snprintf(szOutput, dwOutput, TEXT("%s"), szVersion);
szOutput[dwOutput - 1] = 0;
cleanup:
free(pVersionInfo);
return retval;
}
ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
win32_getLibraryVersion(const char *libname, char **outname, char **outversion)
{
CHAR modVersion[128];
HMODULE hMods[1024];
HANDLE hProcess;
DWORD cbNeeded;
unsigned int i;
int success = -1;
HINSTANCE hPSAPI;
DWORD (WINAPI *pGetModuleFileNameExA)(HANDLE hProcess, HMODULE hModule, LPTSTR lpFilename, DWORD nSize);
BOOL (WINAPI *pEnumProcessModules)(HANDLE hProcess, HMODULE* lphModule, DWORD cb, LPDWORD lpcbNeeded);
if (outversion)
*outversion = NULL;
if (outname)
*outname = NULL;
hPSAPI = LoadLibrary("psapi");
if ( hPSAPI == NULL )
return -1;
if (((FARPROC) pGetModuleFileNameExA =
GetProcAddress( hPSAPI, "GetModuleFileNameExA" )) == NULL ||
((FARPROC) pEnumProcessModules =
GetProcAddress( hPSAPI, "EnumProcessModules" )) == NULL)
{
goto out;
}
// Get a list of all the modules in this process.
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE, GetCurrentProcessId());
if (pEnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
{
for (i = 0; i < (cbNeeded / sizeof(HMODULE)); i++)
{
char szModName[2048];
// Get the full path to the module's file.
if (pGetModuleFileNameExA(hProcess, hMods[i], szModName, sizeof(szModName)))
{
CHAR checkName[1024];
lstrcpy(checkName, szModName);
strlwr(checkName);
if (strstr(checkName, libname)) {
if (GetVersionInfo(szModName, modVersion, sizeof(modVersion)) == 0) {
success = 0;
if (outversion) {
*outversion = strdup(modVersion);
if (*outversion == NULL)
success = -1;
}
if (outname) {
*outname = strdup(szModName);
if (*outname == NULL)
success = -1;
}
}
break;
}
}
}
}
CloseHandle(hProcess);
out:
FreeLibrary(hPSAPI);
return success;
}
|