From: Yuxuan Shui yshui@codeweavers.com
On old WoW64 PEB->LdrData is NULL, so later ReadProcessMemory(&NULL->InLoadOrderModuleList.Flink) fails. Don't return failure in this case. --- dlls/kernel32/toolhelp.c | 69 ++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 31 deletions(-)
diff --git a/dlls/kernel32/toolhelp.c b/dlls/kernel32/toolhelp.c index 5e1ec84d100..282f6828f86 100644 --- a/dlls/kernel32/toolhelp.c +++ b/dlls/kernel32/toolhelp.c @@ -92,42 +92,49 @@ static BOOL fetch_module( DWORD process, DWORD flags, LDR_DATA_TABLE_ENTRY **ldr if (set_ntstatus( NtQueryInformationProcess( hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), NULL ))) { - if (ReadProcessMemory( hProcess, &pbi.PebBaseAddress->LdrData, - &pLdrData, sizeof(pLdrData), NULL ) && - ReadProcessMemory( hProcess, - &pLdrData->InLoadOrderModuleList.Flink, - &curr, sizeof(curr), NULL )) + if (!ReadProcessMemory( hProcess, &pbi.PebBaseAddress->LdrData, + &pLdrData, sizeof(pLdrData), NULL )) + goto out; + if (!pLdrData) { - head = &pLdrData->InLoadOrderModuleList; - - while (curr != head) - { - if (!*num) - *ldr_mod = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LDR_DATA_TABLE_ENTRY) ); - else - *ldr_mod = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, *ldr_mod, - (*num + 1) * sizeof(LDR_DATA_TABLE_ENTRY) ); - if (!*ldr_mod) break; - if (!ReadProcessMemory( hProcess, - CONTAINING_RECORD(curr, LDR_DATA_TABLE_ENTRY, - InLoadOrderLinks), - &(*ldr_mod)[*num], - sizeof(LDR_DATA_TABLE_ENTRY), NULL)) - break; - curr = (*ldr_mod)[*num].InLoadOrderLinks.Flink; - /* if we cannot fetch the strings, then just ignore this LDR_DATA_TABLE_ENTRY - * and continue loading the other ones in the list - */ - if (!fetch_string( hProcess, &(*ldr_mod)[*num].BaseDllName )) continue; - if (fetch_string( hProcess, &(*ldr_mod)[*num].FullDllName )) - (*num)++; - else - HeapFree( GetProcessHeap(), 0, (*ldr_mod)[*num].BaseDllName.Buffer ); - } + /* This happens on "old" wow64. Don't fail, just return an empty modules list. */ ret = TRUE; + goto out; + } + if (!ReadProcessMemory( hProcess, &pLdrData->InLoadOrderModuleList.Flink, + &curr, sizeof(curr), NULL )) + goto out; + + head = &pLdrData->InLoadOrderModuleList; + + while (curr != head) + { + if (!*num) + *ldr_mod = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(LDR_DATA_TABLE_ENTRY) ); + else + *ldr_mod = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, *ldr_mod, + (*num + 1) * sizeof(LDR_DATA_TABLE_ENTRY) ); + if (!*ldr_mod) break; + if (!ReadProcessMemory( hProcess, + CONTAINING_RECORD(curr, LDR_DATA_TABLE_ENTRY, + InLoadOrderLinks), + &(*ldr_mod)[*num], + sizeof(LDR_DATA_TABLE_ENTRY), NULL)) + break; + curr = (*ldr_mod)[*num].InLoadOrderLinks.Flink; + /* if we cannot fetch the strings, then just ignore this LDR_DATA_TABLE_ENTRY + * and continue loading the other ones in the list + */ + if (!fetch_string( hProcess, &(*ldr_mod)[*num].BaseDllName )) continue; + if (fetch_string( hProcess, &(*ldr_mod)[*num].FullDllName )) + (*num)++; + else + HeapFree( GetProcessHeap(), 0, (*ldr_mod)[*num].BaseDllName.Buffer ); } + ret = TRUE; }
+out: if (process) CloseHandle( hProcess ); return ret; }