diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c index 13f1ffd2adf..291859d40cc 100644 --- a/dlls/ntdll/tests/info.c +++ b/dlls/ntdll/tests/info.c @@ -120,6 +120,107 @@ static void test_query_handle() HeapFree( GetProcessHeap(), 0, shi); } +static void test_query_process() +{ + DWORD status; + ULONG ReturnLength; + int i = 0, j = 0, k = 0; + int isnt = 0; + SYSTEM_BASIC_INFORMATION sbi; + + /* Copy of our winternl.h structure turned into a private one */ + typedef struct _SYSTEM_PROCESS_INFORMATION_PRIVATE { + DWORD dwOffset; + DWORD dwThreadCount; + DWORD dwUnknown1[6]; + FILETIME ftCreationTime; + FILETIME ftUserTime; + FILETIME ftKernelTime; + UNICODE_STRING ProcessName; + DWORD dwBasePriority; + DWORD dwProcessID; + DWORD dwParentProcessID; + DWORD dwHandleCount; + DWORD dwUnknown3; + DWORD dwUnknown4; + VM_COUNTERS vmCounters; + IO_COUNTERS ioCounters; + SYSTEM_THREAD_INFORMATION ti[1]; + } SYSTEM_PROCESS_INFORMATION_PRIVATE, *PSYSTEM_PROCESS_INFORMATION_PRIVATE; + + ULONG SystemInformationLength = sizeof(SYSTEM_PROCESS_INFORMATION_PRIVATE); + SYSTEM_PROCESS_INFORMATION_PRIVATE* spi = HeapAlloc(GetProcessHeap(), 0, SystemInformationLength); + + /* Only W2K3 returns the needed length, the rest returns 0, so we have to loop */ + + for (;;) + { + status = pNtQuerySystemInformation(SystemProcessInformation, spi, SystemInformationLength, &ReturnLength); + + if (status != STATUS_INFO_LENGTH_MISMATCH) break; + + spi = HeapReAlloc(GetProcessHeap(), 0, spi , SystemInformationLength *= 2); + } + + ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08lx\n", status); + + /* Get the first dwOffset, from this we can deduce the OS version we're running + * + * W2K/WinXP/W2K3: + * dwOffset for a process is 184 + (no. of threads) * sizeof(SYSTEM_THREAD_INFORMATION) + * NT: + * dwOffset for a process is 136 + (no. of threads) * sizeof(SYSTEM_THREAD_INFORMATION) + * Wine (with every windows version): + * dwOffset for a process is 0 if just this test is running + * dwOffset for a process is 184 + (no. of threads + 1) * sizeof(SYSTEM_THREAD_INFORMATION) + + * ProcessName.MaximumLength + * if more wine processes are running + * + * Note : On windows the first process is in fact the Idle 'process' with a thread for every processor + */ + + pNtQuerySystemInformation(SystemBasicInformation, &sbi, sizeof(sbi), &ReturnLength); + + isnt = ( spi->dwOffset - (sbi.NumberOfProcessors * sizeof(SYSTEM_THREAD_INFORMATION)) == 136); + + if (isnt) trace("Windows version is NT, we will skip thread tests\n"); + + /* Check if we have some return values + * + * On windows there will be several processes running (Including the always present Idle and System) + * On wine we only have one (if this test is the only wine process running) + */ + + /* Loop through the processes */ + + for (;;) + { + i++; + + ok( spi->dwThreadCount > 0, "Expected some threads for this process, got 0\""); + + /* Loop through the threads, skip NT4 for now */ + + if (!isnt) + { + for ( j = 0; j < spi->dwThreadCount; j++) + { + k++; + ok ( spi->ti[j].dwOwningPID == spi->dwProcessID, + "The owning pid of the thread (%ld) doesn't equal the pid (%ld) of the process\n", + spi->ti[j].dwOwningPID, spi->dwProcessID); + } + } + + if (!spi->dwOffset) break; + + spi = (SYSTEM_PROCESS_INFORMATION_PRIVATE*)((char*)spi + spi->dwOffset); + } + trace("Total number of running processes : %d\n", i); + if (!isnt) trace("Total number of running threads : %d\n", k); + + HeapFree( GetProcessHeap(), 0, spi); +} START_TEST(info) { @@ -130,6 +231,10 @@ START_TEST(info) trace("Starting test_query_basic()\n"); test_query_basic(); + /* 5 SystemProcessInformation */ + trace("Starting test_query_process()\n"); + test_query_process(); + /* 0x10 SystemHandleInformation */ trace("Starting test_query_handle()\n"); test_query_handle();