VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/Support/testcase/tstNtQueryStuff.cpp

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 16.8 KB
Line 
1/* $Id: tstNtQueryStuff.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * SUP Testcase - Exploring some NT Query APIs.
4 */
5
6/*
7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#include <iprt/nt/nt-and-windows.h>
42#include <iprt/test.h>
43#include <iprt/string.h>
44
45
46/*********************************************************************************************************************************
47* Structures and Typedefs *
48*********************************************************************************************************************************/
49typedef struct FLAGDESC
50{
51 ULONG f;
52 const char *psz;
53} FLAGDESC;
54typedef const FLAGDESC *PCFLAGDESC;
55
56
57
58/*********************************************************************************************************************************
59* Global Variables *
60*********************************************************************************************************************************/
61static RTTEST g_hTest = NIL_RTTEST;
62static HANDLE g_hProcess = NULL;
63
64
65static char *stringifyAppend(char *pszBuf, size_t *pcbBuf, const char *pszAppend, bool fWithSpace)
66{
67 size_t cchAppend = strlen(pszAppend);
68 if (cchAppend + 1 + fWithSpace <= *pcbBuf)
69 {
70 if (fWithSpace)
71 {
72 *pszBuf++ = ' ';
73 *pcbBuf += 1;
74 }
75 memcpy(pszBuf, pszAppend, cchAppend + 1);
76 *pcbBuf -= cchAppend;
77 pszBuf += cchAppend;
78 }
79
80 return pszBuf;
81}
82
83
84static char *stringifyAppendUnknownFlags(uint32_t fFlags, char *pszBuf, size_t *pcbBuf, bool fWithSpace)
85{
86 for (unsigned iBit = 0; iBit < 32; iBit++)
87 if (fFlags & RT_BIT_32(iBit))
88 {
89 char szTmp[32]; /* lazy bird */
90 RTStrPrintf(szTmp, sizeof(szTmp), "BIT(%d)", iBit);
91 pszBuf = stringifyAppend(pszBuf, pcbBuf, szTmp, fWithSpace);
92 fWithSpace = true;
93 }
94
95 return pszBuf;
96}
97
98
99static char *stringifyFlags(uint32_t fFlags, char *pszBuf, size_t cbBuf, PCFLAGDESC paFlagDesc, size_t cFlagDesc)
100{
101 char *pszBufStart = pszBuf;
102 if (fFlags)
103 {
104 for (size_t i = 0; i < cFlagDesc; i++)
105 {
106 if (fFlags & paFlagDesc[i].f)
107 {
108 fFlags &= ~paFlagDesc[i].f;
109 pszBuf = stringifyAppend(pszBuf, &cbBuf, paFlagDesc[i].psz, pszBuf != pszBufStart);
110 }
111 }
112
113 if (fFlags)
114 stringifyAppendUnknownFlags(fFlags, pszBuf, &cbBuf, pszBuf != pszBufStart);
115 }
116 else
117 {
118 pszBuf[0] = '0';
119 pszBuf[1] = '\0';
120 }
121 return pszBufStart;
122}
123
124
125static char *stringifyMemType(uint32_t fType, char *pszBuf, size_t cbBuf)
126{
127 static const FLAGDESC s_aMemTypes[] =
128 {
129 { MEM_PRIVATE, "PRIVATE" },
130 { MEM_MAPPED, "MAPPED" },
131 { MEM_IMAGE, "IMAGE" },
132 };
133 return stringifyFlags(fType, pszBuf, cbBuf, s_aMemTypes, RT_ELEMENTS(s_aMemTypes));
134}
135
136
137static char *stringifyMemState(uint32_t fState, char *pszBuf, size_t cbBuf)
138{
139 static const FLAGDESC s_aMemStates[] =
140 {
141 { MEM_FREE, "FREE" },
142 { MEM_COMMIT, "COMMIT" },
143 { MEM_RESERVE, "RESERVE" },
144 { MEM_DECOMMIT, "DECOMMMIT" },
145 };
146 return stringifyFlags(fState, pszBuf, cbBuf, s_aMemStates, RT_ELEMENTS(s_aMemStates));
147}
148
149
150static char *stringifyMemProt(uint32_t fProt, char *pszBuf, size_t cbBuf)
151{
152 static const FLAGDESC s_aProtections[] =
153 {
154 { PAGE_NOACCESS, "NOACCESS" },
155 { PAGE_READONLY, "READONLY" },
156 { PAGE_READWRITE, "READWRITE" },
157 { PAGE_WRITECOPY, "WRITECOPY" },
158 { PAGE_EXECUTE, "EXECUTE" },
159 { PAGE_EXECUTE_READ, "EXECUTE_READ" },
160 { PAGE_EXECUTE_READWRITE, "EXECUTE_READWRITE" },
161 { PAGE_EXECUTE_WRITECOPY, "EXECUTE_WRITECOPY" },
162 { PAGE_GUARD, "GUARD" },
163 { PAGE_NOCACHE, "NOCACHE" },
164 { PAGE_WRITECOMBINE, "WRITECOMBINE" },
165
166 };
167 return stringifyFlags(fProt, pszBuf, cbBuf, s_aProtections, RT_ELEMENTS(s_aProtections));
168}
169
170
171
172static void tstQueryVirtualMemory(void)
173{
174 RTTestISub("NtQueryVirtualMemory");
175
176 uintptr_t cbAdvance = 0;
177 uintptr_t uPtrWhere = 0;
178 for (;;)
179 {
180 SIZE_T cbActual = 0;
181 MEMORY_BASIC_INFORMATION MemInfo = { 0, 0, 0, 0, 0, 0, 0 };
182 NTSTATUS rcNt = NtQueryVirtualMemory(g_hProcess,
183 (void const *)uPtrWhere,
184 MemoryBasicInformation,
185 &MemInfo,
186 sizeof(MemInfo),
187 &cbActual);
188 if (!NT_SUCCESS(rcNt))
189 {
190 RTTestIPrintf(RTTESTLVL_ALWAYS, "%p: rcNt=%#x\n", uPtrWhere, rcNt);
191 break;
192 }
193
194 /* stringify the memory state. */
195 char szMemType[1024];
196 char szMemState[1024];
197 char szMemProt[1024];
198 char szAllocProt[1024];
199
200 if ( MemInfo.AllocationBase != NULL
201 && MemInfo.AllocationBase == MemInfo.BaseAddress
202 && MemInfo.Protect != MemInfo.AllocationProtect)
203 RTTestIPrintf(RTTESTLVL_ALWAYS, "\n");
204
205 RTTestIPrintf(RTTESTLVL_ALWAYS, "%p-%p %-8s %-8s %-12s",
206 MemInfo.BaseAddress, (uintptr_t)MemInfo.BaseAddress + MemInfo.RegionSize - 1,
207 stringifyMemType(MemInfo.Type, szMemType, sizeof(szMemType)),
208 stringifyMemState(MemInfo.State, szMemState, sizeof(szMemState)),
209 stringifyMemProt(MemInfo.Protect, szMemProt, sizeof(szMemProt))
210 );
211 if ((uintptr_t)MemInfo.AllocationBase != 0)
212 {
213 if (MemInfo.AllocationBase != MemInfo.BaseAddress)
214 RTTestIPrintf(RTTESTLVL_ALWAYS, " %p", MemInfo.AllocationBase);
215 else
216 RTTestIPrintf(RTTESTLVL_ALWAYS, " %s", stringifyMemProt(MemInfo.AllocationProtect, szAllocProt, sizeof(szAllocProt)));
217 }
218 RTTestIPrintf(RTTESTLVL_ALWAYS, "\n");
219
220 if ((uintptr_t)MemInfo.BaseAddress != uPtrWhere)
221 RTTestIPrintf(RTTESTLVL_ALWAYS, " !Warning! Queried %p got BaseAddress=%p!\n",
222 uPtrWhere, MemInfo.BaseAddress);
223
224 /* Image or mapped, then try get a file name. */
225 if (MemInfo.Type == MEM_IMAGE || MemInfo.Type == MEM_MAPPED)
226 {
227 union
228 {
229 MEMORY_SECTION_NAME Core;
230 WCHAR awcPadding[UNICODE_STRING_MAX_CHARS + (sizeof(UNICODE_STRING_MAX_CHARS) + 1) / sizeof(WCHAR)];
231 } uBuf;
232 RT_ZERO(uBuf);
233 uBuf.Core.SectionFileName.Length = UNICODE_STRING_MAX_CHARS * 2;
234 uBuf.Core.SectionFileName.MaximumLength = UNICODE_STRING_MAX_CHARS * 2;
235 uBuf.Core.SectionFileName.Buffer = &uBuf.Core.NameBuffer[0];
236
237 cbActual = 0;
238 rcNt = NtQueryVirtualMemory(g_hProcess,
239 (void const *)uPtrWhere,
240 MemorySectionName,
241 &uBuf,
242 sizeof(uBuf),
243 &cbActual);
244 if (NT_SUCCESS(rcNt))
245 RTTestIPrintf(RTTESTLVL_ALWAYS, " %.*ls\n",
246 uBuf.Core.SectionFileName.Length / 2, uBuf.Core.SectionFileName.Buffer);
247 else
248 {
249 RTTestIPrintf(RTTESTLVL_ALWAYS, "%p: MemorySectionName - rcNt=%#x\n", uPtrWhere, rcNt);
250 RTTESTI_CHECK(rcNt == STATUS_FILE_INVALID && MemInfo.Type == MEM_MAPPED);
251 }
252 }
253
254 /* Advance. */
255 cbAdvance = MemInfo.RegionSize;
256 //cbAdvance = 0;
257 if (uPtrWhere + cbAdvance <= uPtrWhere)
258 break;
259 uPtrWhere += MemInfo.RegionSize;
260 }
261}
262
263
264static void tstQueryInformationProcess(void)
265{
266 RTTestISub("NtQueryInformationProcess");
267
268 NTSTATUS rcNt;
269
270 /* Basic info */
271 PROCESS_BASIC_INFORMATION BasicInfo;
272 RT_ZERO(BasicInfo);
273 DWORD cbActual = 0;
274 rcNt = NtQueryInformationProcess(g_hProcess,
275 ProcessBasicInformation,
276 &BasicInfo, sizeof(BasicInfo), &cbActual);
277 RTTESTI_CHECK_MSG(NT_SUCCESS(rcNt), ("rcNt=%#x\n", rcNt));
278 if (NT_SUCCESS(rcNt))
279 RTTestIPrintf(RTTESTLVL_ALWAYS, "BasicInfo:\n"
280 " UniqueProcessId = %#x (%6d)\n"
281 " InheritedFromUniqueProcessId = %#x (%6d)\n"
282 " ExitStatus = %#x\n"
283 " PebBaseAddress = %p\n"
284 " AffinityMask = %#zx\n"
285 " BasePriority = %#zx\n"
286 ,
287 BasicInfo.UniqueProcessId, BasicInfo.UniqueProcessId,
288 BasicInfo.InheritedFromUniqueProcessId, BasicInfo.InheritedFromUniqueProcessId,
289 BasicInfo.ExitStatus,
290 BasicInfo.PebBaseAddress,
291 BasicInfo.AffinityMask,
292 BasicInfo.BasePriority
293 );
294
295 /* Debugger present? */
296 DWORD_PTR uPtr = ~(DWORD_PTR)0;
297 cbActual = 0;
298 rcNt = NtQueryInformationProcess(g_hProcess,
299 ProcessDebugPort,
300 &uPtr, sizeof(uPtr), &cbActual);
301 RTTESTI_CHECK_MSG(NT_SUCCESS(rcNt), ("rcNt=%#x\n", rcNt));
302 if (NT_SUCCESS(rcNt))
303 RTTestIPrintf(RTTESTLVL_ALWAYS, "ProcessDebugPort: %p\n", uPtr);
304
305 /* Debug object handle, whatever that is... */
306 uPtr = ~(DWORD_PTR)0;
307 cbActual = 0;
308 rcNt = NtQueryInformationProcess(g_hProcess,
309 ProcessDebugObjectHandle,
310 &uPtr, sizeof(uPtr), &cbActual);
311 if (NT_SUCCESS(rcNt))
312 RTTestIPrintf(RTTESTLVL_ALWAYS, "ProcessDebugObjectHandle: %p\n", uPtr);
313 else if (rcNt == STATUS_PORT_NOT_SET)
314 RTTestIPrintf(RTTESTLVL_ALWAYS, "ProcessDebugObjectHandle: rcNt=%#x (STATUS_PORT_NOT_SET)\n", uPtr);
315 else
316 RTTESTI_CHECK_MSG(NT_SUCCESS(rcNt), ("rcNt=%#x\n", rcNt));
317
318 /* 32-bit app on 64-bit host? */
319 uPtr = ~(DWORD_PTR)0;
320 cbActual = 0;
321 rcNt = NtQueryInformationProcess(g_hProcess,
322 ProcessWow64Information,
323 &uPtr, sizeof(uPtr), &cbActual);
324 RTTESTI_CHECK_MSG(NT_SUCCESS(rcNt), ("rcNt=%#x\n", rcNt));
325 if (NT_SUCCESS(rcNt))
326 RTTestIPrintf(RTTESTLVL_ALWAYS, "ProcessWow64Information: %p\n", uPtr);
327
328 /* Process image name (NT). */
329 struct
330 {
331 UNICODE_STRING UniStr;
332 WCHAR awBuffer[UNICODE_STRING_MAX_CHARS];
333 } StrBuf;
334 RT_ZERO(StrBuf);
335 StrBuf.UniStr.Length = UNICODE_STRING_MAX_CHARS * 2;
336 StrBuf.UniStr.MaximumLength = UNICODE_STRING_MAX_CHARS * 2;
337 StrBuf.UniStr.Buffer = &StrBuf.awBuffer[0];
338 cbActual = 0;
339 rcNt = NtQueryInformationProcess(g_hProcess,
340 ProcessImageFileName,
341 &StrBuf, sizeof(StrBuf), &cbActual);
342 RTTESTI_CHECK_MSG(NT_SUCCESS(rcNt), ("rcNt=%#x\n", rcNt));
343 if (NT_SUCCESS(rcNt))
344 RTTestIPrintf(RTTESTLVL_ALWAYS, "ProcessImageFileName: len=%u\n %.*ls\n",
345 StrBuf.UniStr.Length, StrBuf.UniStr.Length, StrBuf.UniStr.Buffer);
346
347 /* Process image name (Win32) - Not available on Windows 2003. */
348 RT_ZERO(StrBuf);
349 StrBuf.UniStr.Length = UNICODE_STRING_MAX_CHARS * 2;
350 StrBuf.UniStr.MaximumLength = UNICODE_STRING_MAX_CHARS * 2;
351 StrBuf.UniStr.Buffer = &StrBuf.awBuffer[0];
352 cbActual = 0;
353 rcNt = NtQueryInformationProcess(g_hProcess,
354 ProcessImageFileNameWin32,
355 &StrBuf, sizeof(StrBuf), &cbActual);
356 if (rcNt != STATUS_INVALID_INFO_CLASS)
357 {
358 RTTESTI_CHECK_MSG(NT_SUCCESS(rcNt), ("rcNt=%#x\n", rcNt));
359 if (NT_SUCCESS(rcNt))
360 RTTestIPrintf(RTTESTLVL_ALWAYS, "ProcessImageFileNameWin32: len=%u\n %.*ls\n",
361 StrBuf.UniStr.Length, StrBuf.UniStr.Length, StrBuf.UniStr.Buffer);
362 }
363 else
364 RTTestIPrintf(RTTESTLVL_ALWAYS, "ProcessImageFileNameWin32: Not supported (STATUS_INVALID_INFO_CLASS).\n");
365
366 /* Process image mapping - Not available on Windows 2003. */
367 uPtr = ~(DWORD_PTR)0;
368 cbActual = 0;
369 rcNt = NtQueryInformationProcess(g_hProcess,
370 ProcessImageFileMapping,
371 &uPtr, sizeof(uPtr), &cbActual);
372 if (NT_SUCCESS(rcNt))
373 RTTestIPrintf(RTTESTLVL_ALWAYS, "ProcessImageFileMapping: %p\n", uPtr);
374 else if (rcNt == STATUS_OBJECT_TYPE_MISMATCH)
375 RTTestIPrintf(RTTESTLVL_ALWAYS, "ProcessImageFileMapping: rcNt=%#x (STATUS_OBJECT_TYPE_MISMATCH)\n", rcNt);
376 else if (rcNt == STATUS_INVALID_INFO_CLASS)
377 RTTestIPrintf(RTTESTLVL_ALWAYS, "ProcessImageFileMapping: Not supported (STATUS_INVALID_INFO_CLASS).\n");
378 else
379 RTTestIFailed("ProcessImageFileMapping: rcNt=%#x\n", rcNt);
380
381
382 /* Handles. Broken for 64-bit input. */
383 uint32_t u32 = UINT32_MAX;
384 cbActual = 0;
385 rcNt = NtQueryInformationProcess(g_hProcess,
386 ProcessHandleCount,
387 &u32, sizeof(u32), &cbActual);
388 if (NT_SUCCESS(rcNt))
389 RTTestIPrintf(RTTESTLVL_ALWAYS, "ProcessHandleCount: %#x (%d)\n", u32, u32);
390 else
391 RTTestIFailed("ProcessHandleCount: rcNt=%#x\n", rcNt);
392
393 /* Execute flags. */
394#if 0 /* fails... wrong process handle? */
395 u32 = ~(DWORD_PTR)0;
396 cbActual = 0;
397 rcNt = NtQueryInformationProcess(g_hProcess,
398 ProcessExecuteFlags,
399 &u32, sizeof(u32), &cbActual);
400 if (NT_SUCCESS(rcNt))
401 RTTestIPrintf(RTTESTLVL_ALWAYS, "ProcessExecuteFlags: %#p\n", u32);
402 else
403 RTTestIFailed("ProcessExecuteFlags: rcNt=%#x\n", rcNt);
404#endif
405
406 /** @todo ProcessImageInformation */
407}
408
409
410int main(int argc, char **argv)
411{
412 RTEXITCODE rcExit = RTTestInitAndCreate("tstNtQueryStuff", &g_hTest);
413 if (rcExit != RTEXITCODE_SUCCESS)
414 return rcExit;
415 RTTestBanner(g_hTest);
416
417 g_hProcess = GetCurrentProcess();
418 if (argc >= 2 && argv[1][0] != '-')
419 {
420 const char *pszPid = argv[1];
421 uint32_t idPid = RTStrToInt32(pszPid);
422
423 uint32_t fAccess = PROCESS_QUERY_INFORMATION;
424 if (argc >= 3)
425 fAccess = RTStrToInt32(argv[2]);
426
427 g_hProcess = OpenProcess(fAccess, FALSE, idPid);
428 if (g_hProcess == NULL)
429 {
430 RTTestIFailed("Error %u opening process %u (%s)\n", GetLastError(), idPid, pszPid);
431 return RTTestSummaryAndDestroy(g_hTest);
432 }
433 }
434
435 tstQueryVirtualMemory();
436 tstQueryInformationProcess();
437
438 return RTTestSummaryAndDestroy(g_hTest);
439}
440
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use