diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index ab901888b7f..c28ab985298 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -758,6 +758,55 @@ NTSTATUS WINAPI LdrLoadDll(LPCWSTR path_name, DWORD flags, PUNICODE_STRING libna return nts; } +/****************************************************************** + * LdrQueryProcessModuleInformation + * + */ +NTSTATUS WINAPI LdrQueryProcessModuleInformation(PSYSTEM_MODULE_INFORMATION smi, + ULONG buf_size, ULONG* req_size) +{ + SYSTEM_MODULE* sm = &smi->Modules[0]; + ULONG size = sizeof(ULONG); + NTSTATUS nts = STATUS_SUCCESS; + ANSI_STRING str; + char* ptr; + WINE_MODREF* wm; + + smi->ModulesCount = 0; + + RtlEnterCriticalSection( &loader_section ); + for ( wm = MODULE_modref_list; wm; wm = wm->next ) + { + size += sizeof(*sm); + if (size <= buf_size) + { + sm->Reserved1 = 0; /* FIXME */ + sm->Reserved2 = 0; /* FIXME */ + sm->ImageBaseAddress = wm->ldr.BaseAddress; + sm->ImageSize = wm->ldr.SizeOfImage; + sm->Flags = wm->ldr.Flags; + sm->Id = 0; /* FIXME */ + sm->Rank = 0; /* FIXME */ + sm->Unknown = 0; /* FIXME */ + str.Length = 0; + str.MaximumLength = MAXIMUM_FILENAME_LENGTH; + str.Buffer = sm->Name; + RtlUnicodeStringToAnsiString(&str, &wm->ldr.FullDllName, FALSE); + ptr = strrchr(sm->Name, '\\'); + sm->NameOffset = (ptr != NULL) ? (ptr - (char*)sm->Name + 1) : 0; + + smi->ModulesCount++; + sm++; + } + else nts = STATUS_INFO_LENGTH_MISMATCH; + } + RtlLeaveCriticalSection( &loader_section ); + + if (req_size) *req_size = size; + + return nts; +} + /****************************************************************** * LdrShutdownProcess (NTDLL.@) * diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index ca33a84e74e..0a8bdb3c9e8 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -46,7 +46,7 @@ @ stdcall LdrLockLoaderLock(long ptr ptr) @ stub LdrProcessRelocationBlock @ stub LdrQueryImageFileExecutionOptions -@ stub LdrQueryProcessModuleInformation +@ stdcall LdrQueryProcessModuleInformation(ptr long ptr) @ stdcall LdrShutdownProcess() @ stdcall LdrShutdownThread() @ stdcall LdrUnloadDll(ptr) diff --git a/include/winternl.h b/include/winternl.h index cc2acd4e25c..adfc19d2462 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -1227,6 +1227,7 @@ NTSTATUS WINAPI LdrGetDllHandle(ULONG, ULONG, PUNICODE_STRING, HMODULE*); NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE, PANSI_STRING, ULONG, void**); NTSTATUS WINAPI LdrLoadDll(LPCWSTR, DWORD, PUNICODE_STRING, HMODULE*); NTSTATUS WINAPI LdrLockLoaderLock(ULONG,ULONG*,ULONG*); +NTSTATUS WINAPI LdrQueryProcessModuleInformation(SYSTEM_MODULE_INFORMATION*, ULONG, ULONG*); NTSTATUS WINAPI LdrShutdownProcess(void); NTSTATUS WINAPI LdrShutdownThread(void); NTSTATUS WINAPI LdrUnloadDll(HMODULE); diff --git a/misc/version.c b/misc/version.c index 0172020824b..75e91d0068a 100644 --- a/misc/version.c +++ b/misc/version.c @@ -37,6 +37,7 @@ #include "module.h" #include "wine/unicode.h" #include "wine/debug.h" +#include "ntdll_misc.h" WINE_DEFAULT_DEBUG_CHANNEL(ver); @@ -444,51 +445,64 @@ static DWORD VERSION_GetSystemDLLVersion( HMODULE hmod ) */ static DWORD VERSION_GetLinkedDllVersion(void) { - WINE_MODREF *wm; DWORD WinVersion = NB_WINDOWS_VERSIONS; PIMAGE_OPTIONAL_HEADER ophd; IMAGE_NT_HEADERS *nt; + ULONG count, required; + SYSTEM_MODULE_INFORMATION* smi; /* First check the native dlls provided. These have to be from one windows version */ - for ( wm = MODULE_modref_list; wm; wm=wm->next ) - { - nt = RtlImageNtHeader(wm->ldr.BaseAddress); - ophd = &nt->OptionalHeader; + smi = (SYSTEM_MODULE_INFORMATION*)&count; + LdrQueryProcessModuleInformation(smi, sizeof(count), &required); + smi = RtlAllocateHeap(ntdll_get_process_heap(), 0, required); + if (smi) + { + if (LdrQueryProcessModuleInformation(smi, required, NULL) == STATUS_SUCCESS) + { + int k; + for (k = 0; k < smi->ModulesCount; k++) + { + nt = RtlImageNtHeader(smi->Modules[k].ImageBaseAddress); + ophd = &nt->OptionalHeader; + + TRACE("%s: %02x.%02x/%02x.%02x/%02x.%02x/%02x.%02x\n", + &smi->Modules[k].Name[smi->Modules[k].NameOffset], + ophd->MajorLinkerVersion, ophd->MinorLinkerVersion, + ophd->MajorOperatingSystemVersion, ophd->MinorOperatingSystemVersion, + ophd->MajorImageVersion, ophd->MinorImageVersion, + ophd->MajorSubsystemVersion, ophd->MinorSubsystemVersion); + } - TRACE("%s: %02x.%02x/%02x.%02x/%02x.%02x/%02x.%02x\n", - wm->modname, - ophd->MajorLinkerVersion, ophd->MinorLinkerVersion, - ophd->MajorOperatingSystemVersion, ophd->MinorOperatingSystemVersion, - ophd->MajorImageVersion, ophd->MinorImageVersion, - ophd->MajorSubsystemVersion, ophd->MinorSubsystemVersion); - - /* test if it is an external (native) dll */ - if (!(wm->ldr.Flags & LDR_WINE_INTERNAL)) - { - int i; - for (i = 0; special_dlls[i]; i++) - { - /* test if it is a special dll */ - if (!strcasecmp(wm->modname, special_dlls[i])) - { - DWORD DllVersion = VERSION_GetSystemDLLVersion(wm->ldr.BaseAddress); - if (WinVersion == NB_WINDOWS_VERSIONS) - WinVersion = DllVersion; - else { - if (WinVersion != DllVersion) { - ERR("You mixed system DLLs from different windows versions! Expect a crash! (%s: expected version '%s', but is '%s')\n", - wm->modname, - VersionData[WinVersion].getVersionEx.szCSDVersion, - VersionData[DllVersion].getVersionEx.szCSDVersion); - return WIN20; /* this may let the exe exiting */ - } - } - break; - } - } - } - } + /* test if it is an external (native) dll */ + if (!(smi->Modules[k].Flags & LDR_WINE_INTERNAL)) + { + int i; + for (i = 0; special_dlls[i]; i++) + { + /* test if it is a special dll */ + if (!strcasecmp(&smi->Modules[k].Name[smi->Modules[k].NameOffset], special_dlls[i])) + { + DWORD DllVersion = VERSION_GetSystemDLLVersion(smi->Modules[k].ImageBaseAddress); + if (WinVersion == NB_WINDOWS_VERSIONS) + WinVersion = DllVersion; + else + { + if (WinVersion != DllVersion) { + ERR("You mixed system DLLs from different windows versions! Expect a crash! (%s: expected version '%s', but is '%s')\n", + &smi->Modules[k].Name[smi->Modules[k].NameOffset], + VersionData[WinVersion].getVersionEx.szCSDVersion, + VersionData[DllVersion].getVersionEx.szCSDVersion); + return WIN20; /* this may let the exe exiting */ + } + } + break; + } + } + } + } + RtlFreeHeap(ntdll_get_process_heap(), 0, smi); + } if(WinVersion != NB_WINDOWS_VERSIONS) return WinVersion;