diff --git a/dlls/kernel32/heap.c b/dlls/kernel32/heap.c index 93cf545308b..e85ccc331eb 100644 --- a/dlls/kernel32/heap.c +++ b/dlls/kernel32/heap.c @@ -291,6 +291,14 @@ SIZE_T WINAPI HeapSize( HANDLE heap, DWORD flags, LPCVOID ptr ) return RtlSizeHeap( heap, flags, ptr ); } +BOOL WINAPI HeapQueryInformation( HANDLE heap, HEAP_INFORMATION_CLASS info_class, + PVOID info, SIZE_T size_in, PSIZE_T size_out) +{ + NTSTATUS ret = RtlQueryHeapInformation( heap, info_class, info, size_in, size_out ); + if (ret) SetLastError( RtlNtStatusToDosError(ret) ); + return !ret; +} + BOOL WINAPI HeapSetInformation( HANDLE heap, HEAP_INFORMATION_CLASS infoclass, PVOID info, SIZE_T size) { FIXME("%p %d %p %ld\n", heap, infoclass, info, size ); diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec index c97aa2835e8..f5df03154d1 100644 --- a/dlls/kernel32/kernel32.spec +++ b/dlls/kernel32/kernel32.spec @@ -707,7 +707,7 @@ @ stub HeapExtend @ stdcall HeapFree(long long long) ntdll.RtlFreeHeap @ stdcall HeapLock(long) -# @ stub HeapQueryInformation +@ stdcall HeapQueryInformation(long long ptr long ptr) @ stub HeapQueryTagW @ stdcall HeapReAlloc(long long ptr long) ntdll.RtlReAllocateHeap @ stub HeapSetFlags diff --git a/dlls/kernel32/tests/heap.c b/dlls/kernel32/tests/heap.c index 19b410678e5..c59d304b246 100644 --- a/dlls/kernel32/tests/heap.c +++ b/dlls/kernel32/tests/heap.c @@ -28,6 +28,8 @@ #define MAGIC_DEAD 0xdeadbeef +static BOOL (WINAPI *pHeapQueryInformation)(HANDLE, HEAP_INFORMATION_CLASS, PVOID, SIZE_T, PSIZE_T); + static SIZE_T resize_9x(SIZE_T size) { DWORD dwSizeAligned = (size + 3) & ~3; @@ -410,6 +412,58 @@ static void test_obsolete_flags(void) } } +static void test_HeapQueryInformation(void) +{ + ULONG info; + SIZE_T size; + BOOL ret; + + pHeapQueryInformation = (void *)GetProcAddress(GetModuleHandle("kernel32.dll"), "HeapQueryInformation"); + if (!pHeapQueryInformation) + { + win_skip("HeapQueryInformation is not available\n"); + return; + } + + if (0) /* crashes under XP */ + { + size = 0; + ret = pHeapQueryInformation(0, + HeapCompatibilityInformation, + &info, sizeof(info), &size); + size = 0; + ret = pHeapQueryInformation(GetProcessHeap(), + HeapCompatibilityInformation, + NULL, sizeof(info), &size); + } + + size = 0; + SetLastError(0xdeadbeef); + ret = pHeapQueryInformation(GetProcessHeap(), + HeapCompatibilityInformation, + NULL, 0, &size); + ok(!ret, "HeapQueryInformation should fail\n"); + ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, + "expected ERROR_INSUFFICIENT_BUFFER got %u\n", GetLastError()); + ok(size == sizeof(ULONG), "expected 4, got %lu\n", size); + + SetLastError(0xdeadbeef); + ret = pHeapQueryInformation(GetProcessHeap(), + HeapCompatibilityInformation, + NULL, 0, NULL); + ok(!ret, "HeapQueryInformation should fail\n"); + ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER, + "expected ERROR_INSUFFICIENT_BUFFER got %u\n", GetLastError()); + + info = 0xdeadbeaf; + SetLastError(0xdeadbeef); + ret = pHeapQueryInformation(GetProcessHeap(), + HeapCompatibilityInformation, + &info, sizeof(info) + 1, NULL); + ok(ret, "HeapQueryInformation error %u\n", GetLastError()); + ok(info == 0 || info == 1 || info == 2, "expected 0, 1 or 2, got %u\n", info); +} + START_TEST(heap) { test_heap(); @@ -422,4 +476,5 @@ START_TEST(heap) test_sized_HeapReAlloc(1, (1 << 20)); test_sized_HeapReAlloc((1 << 20), (2 << 20)); test_sized_HeapReAlloc((1 << 20), 1); + test_HeapQueryInformation(); } diff --git a/dlls/ntdll/heap.c b/dlls/ntdll/heap.c index 14cac32dc1b..adaf693ef2a 100644 --- a/dlls/ntdll/heap.c +++ b/dlls/ntdll/heap.c @@ -1961,3 +1961,26 @@ ULONG WINAPI RtlGetProcessHeaps( ULONG count, HANDLE *heaps ) RtlLeaveCriticalSection( &processHeap->critSection ); return total; } + +/*********************************************************************** + * RtlQueryHeapInformation (NTDLL.@) + */ +NTSTATUS WINAPI RtlQueryHeapInformation( HANDLE heap, HEAP_INFORMATION_CLASS info_class, + PVOID info, SIZE_T size_in, PSIZE_T size_out) +{ + switch (info_class) + { + case HeapCompatibilityInformation: + if (size_out) *size_out = sizeof(ULONG); + + if (size_in < sizeof(ULONG)) + return STATUS_BUFFER_TOO_SMALL; + + *(ULONG *)info = 0; /* standard heap */ + return STATUS_SUCCESS; + + default: + FIXME("Unknown heap information class %u\n", info_class); + return STATUS_INVALID_INFO_CLASS; + } +} diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 878761124ae..70647d247b4 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -768,7 +768,7 @@ @ stdcall RtlQueryAtomInAtomTable(ptr long ptr ptr ptr ptr) @ stdcall RtlQueryDepthSList(ptr) @ stdcall RtlQueryEnvironmentVariable_U(ptr ptr ptr) -@ stub RtlQueryHeapInformation +@ stdcall RtlQueryHeapInformation(long long ptr long ptr) @ stdcall RtlQueryInformationAcl(ptr ptr long long) @ stdcall RtlQueryInformationActivationContext(long long ptr long ptr long ptr) @ stub RtlQueryInformationActiveActivationContext diff --git a/include/winternl.h b/include/winternl.h index a6fea7d8f3d..a78e9e5eba6 100644 --- a/include/winternl.h +++ b/include/winternl.h @@ -2412,6 +2412,7 @@ NTSYSAPI BOOLEAN WINAPI RtlPrefixString(const STRING*,const STRING*,BOOLEAN); NTSYSAPI BOOLEAN WINAPI RtlPrefixUnicodeString(const UNICODE_STRING*,const UNICODE_STRING*,BOOLEAN); NTSYSAPI NTSTATUS WINAPI RtlQueryAtomInAtomTable(RTL_ATOM_TABLE,RTL_ATOM,ULONG*,ULONG*,WCHAR*,ULONG*); NTSYSAPI NTSTATUS WINAPI RtlQueryEnvironmentVariable_U(PWSTR,PUNICODE_STRING,PUNICODE_STRING); +NTSYSAPI NTSTATUS WINAPI RtlQueryHeapInformation(HANDLE,HEAP_INFORMATION_CLASS,PVOID,SIZE_T,PSIZE_T); NTSYSAPI NTSTATUS WINAPI RtlQueryInformationAcl(PACL,LPVOID,DWORD,ACL_INFORMATION_CLASS); NTSYSAPI NTSTATUS WINAPI RtlQueryInformationActivationContext(ULONG,HANDLE,PVOID,ULONG,PVOID,SIZE_T,SIZE_T*); NTSYSAPI NTSTATUS WINAPI RtlQueryProcessDebugInformation(ULONG,ULONG,PDEBUG_BUFFER);