VirtualBox

source: vbox/trunk/src/VBox/Runtime/r0drv/nt/initterm-r0drv-nt.cpp@ 70153

Last change on this file since 70153 was 70153, checked in by vboxsync, 7 years ago

IPRT: Don't call ExAllocatePool[WithTag] directly unless you must, use RTMemAlloc et al instead. Simplified the NT4 ExAllocatePool/ExAllocatePoolWithTag unwrapping.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 20.2 KB
Line 
1/* $Id: initterm-r0drv-nt.cpp 70153 2017-12-15 15:07:27Z vboxsync $ */
2/** @file
3 * IPRT - Initialization & Termination, R0 Driver, NT.
4 */
5
6/*
7 * Copyright (C) 2006-2017 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include "the-nt-kernel.h"
32#include <iprt/asm-amd64-x86.h>
33#include <iprt/dbg.h>
34#include <iprt/err.h>
35#include <iprt/string.h>
36#include "internal/initterm.h"
37#include "internal-r0drv-nt.h"
38#include "symdb.h"
39#include "symdbdata.h"
40
41
42/*********************************************************************************************************************************
43* Global Variables *
44*********************************************************************************************************************************/
45/** ExAllocatePoolWithTag, introduced in W2K. */
46decltype(ExAllocatePoolWithTag) *g_pfnrtExAllocatePoolWithTag;
47/** ExSetTimerResolution, introduced in W2K. */
48PFNMYEXSETTIMERRESOLUTION g_pfnrtNtExSetTimerResolution;
49/** KeFlushQueuedDpcs, introduced in XP. */
50PFNMYKEFLUSHQUEUEDDPCS g_pfnrtNtKeFlushQueuedDpcs;
51/** HalRequestIpi, version introduced with windows 7. */
52PFNHALREQUESTIPI_W7PLUS g_pfnrtHalRequestIpiW7Plus;
53/** HalRequestIpi, version valid up to windows vista?? */
54PFNHALREQUESTIPI_PRE_W7 g_pfnrtHalRequestIpiPreW7;
55/** Worker for RTMpPokeCpu. */
56PFNRTSENDIPI g_pfnrtMpPokeCpuWorker;
57/** KeIpiGenericCall - Introduced in Windows Server 2003. */
58PFNRTKEIPIGENERICCALL g_pfnrtKeIpiGenericCall;
59/** KeSetTargetProcessorDpcEx - Introduced in Windows 7. */
60PFNKESETTARGETPROCESSORDPCEX g_pfnrtKeSetTargetProcessorDpcEx;
61/** KeInitializeAffinityEx - Introducted in Windows 7. */
62PFNKEINITIALIZEAFFINITYEX g_pfnrtKeInitializeAffinityEx;
63/** KeAddProcessorAffinityEx - Introducted in Windows 7. */
64PFNKEADDPROCESSORAFFINITYEX g_pfnrtKeAddProcessorAffinityEx;
65/** KeGetProcessorIndexFromNumber - Introducted in Windows 7. */
66PFNKEGETPROCESSORINDEXFROMNUMBER g_pfnrtKeGetProcessorIndexFromNumber;
67/** KeGetProcessorNumberFromIndex - Introducted in Windows 7. */
68PFNKEGETPROCESSORNUMBERFROMINDEX g_pfnrtKeGetProcessorNumberFromIndex;
69/** KeGetCurrentProcessorNumberEx - Introducted in Windows 7. */
70PFNKEGETCURRENTPROCESSORNUMBEREX g_pfnrtKeGetCurrentProcessorNumberEx;
71/** KeQueryActiveProcessors - Introducted in Windows 2000. */
72PFNKEQUERYACTIVEPROCESSORS g_pfnrtKeQueryActiveProcessors;
73/** KeQueryMaximumProcessorCount - Introducted in Vista and obsoleted W7. */
74PFNKEQUERYMAXIMUMPROCESSORCOUNT g_pfnrtKeQueryMaximumProcessorCount;
75/** KeQueryMaximumProcessorCountEx - Introducted in Windows 7. */
76PFNKEQUERYMAXIMUMPROCESSORCOUNTEX g_pfnrtKeQueryMaximumProcessorCountEx;
77/** KeQueryMaximumGroupCount - Introducted in Windows 7. */
78PFNKEQUERYMAXIMUMGROUPCOUNT g_pfnrtKeQueryMaximumGroupCount;
79/** KeQueryActiveProcessorCount - Introducted in Vista and obsoleted W7. */
80PFNKEQUERYACTIVEPROCESSORCOUNT g_pfnrtKeQueryActiveProcessorCount;
81/** KeQueryActiveProcessorCountEx - Introducted in Windows 7. */
82PFNKEQUERYACTIVEPROCESSORCOUNTEX g_pfnrtKeQueryActiveProcessorCountEx;
83/** KeQueryLogicalProcessorRelationship - Introducted in Windows 7. */
84PFNKEQUERYLOGICALPROCESSORRELATIONSHIP g_pfnrtKeQueryLogicalProcessorRelationship;
85/** KeRegisterProcessorChangeCallback - Introducted in Windows 7. */
86PFNKEREGISTERPROCESSORCHANGECALLBACK g_pfnrtKeRegisterProcessorChangeCallback;
87/** KeDeregisterProcessorChangeCallback - Introducted in Windows 7. */
88PFNKEDEREGISTERPROCESSORCHANGECALLBACK g_pfnrtKeDeregisterProcessorChangeCallback;
89/** Pointer to the MmProtectMdlSystemAddress kernel function if it's available.
90 * This API was introduced in XP. */
91decltype(MmProtectMdlSystemAddress) *g_pfnrtMmProtectMdlSystemAddress;
92/** MmAllocatePagesForMdl - Introduced in Windows 2000. */
93decltype(MmAllocatePagesForMdl) *g_pfnrtMmAllocatePagesForMdl;
94/** MmFreePagesFromMdl - Introduced in Windows 2000. */
95decltype(MmFreePagesFromMdl) *g_pfnrtMmFreePagesFromMdl;
96/** MmMapLockedPagesSpecifyCache - Introduced in Windows NT4 SP4. */
97decltype(MmMapLockedPagesSpecifyCache) *g_pfnrtMmMapLockedPagesSpecifyCache;
98/** MmAllocateContiguousMemorySpecifyCache - Introduced in Windows 2000. */
99decltype(MmAllocateContiguousMemorySpecifyCache) *g_pfnrtMmAllocateContiguousMemorySpecifyCache;
100/** RtlGetVersion, introduced in ??. */
101PFNRTRTLGETVERSION g_pfnrtRtlGetVersion;
102#ifndef RT_ARCH_AMD64
103/** KeQueryInterruptTime - exported/new in Windows 2000. */
104PFNRTKEQUERYINTERRUPTTIME g_pfnrtKeQueryInterruptTime;
105/** KeQuerySystemTime - exported/new in Windows 2000. */
106PFNRTKEQUERYSYSTEMTIME g_pfnrtKeQuerySystemTime;
107#endif
108/** KeQueryInterruptTimePrecise - new in Windows 8. */
109PFNRTKEQUERYINTERRUPTTIMEPRECISE g_pfnrtKeQueryInterruptTimePrecise;
110/** KeQuerySystemTimePrecise - new in Windows 8. */
111PFNRTKEQUERYSYSTEMTIMEPRECISE g_pfnrtKeQuerySystemTimePrecise;
112
113/** Offset of the _KPRCB::QuantumEnd field. 0 if not found. */
114uint32_t g_offrtNtPbQuantumEnd;
115/** Size of the _KPRCB::QuantumEnd field. 0 if not found. */
116uint32_t g_cbrtNtPbQuantumEnd;
117/** Offset of the _KPRCB::DpcQueueDepth field. 0 if not found. */
118uint32_t g_offrtNtPbDpcQueueDepth;
119
120/** The combined NT version, see RTNT_MAKE_VERSION. */
121uint32_t g_uRtNtVersion;
122/** The major version number. */
123uint8_t g_uRtNtMajorVer;
124/** The minor version number. */
125uint8_t g_uRtNtMinorVer;
126/** The build number. */
127uint32_t g_uRtNtBuildNo;
128
129/** Pointer to the MmHighestUserAddress kernel variable - can be NULL. */
130uintptr_t const *g_puRtMmHighestUserAddress;
131/** Pointer to the MmSystemRangeStart kernel variable - can be NULL. */
132uintptr_t const *g_puRtMmSystemRangeStart;
133
134
135/**
136 * Determines the NT kernel verison information.
137 *
138 * @param pOsVerInfo Where to return the version information.
139 *
140 * @remarks pOsVerInfo->fSmp is only definitive if @c true.
141 * @remarks pOsVerInfo->uCsdNo is set to MY_NIL_CSD if it cannot be determined.
142 */
143static void rtR0NtGetOsVersionInfo(PRTNTSDBOSVER pOsVerInfo)
144{
145 ULONG ulMajorVersion = 0;
146 ULONG ulMinorVersion = 0;
147 ULONG ulBuildNumber = 0;
148
149 pOsVerInfo->fChecked = PsGetVersion(&ulMajorVersion, &ulMinorVersion, &ulBuildNumber, NULL) == TRUE;
150 pOsVerInfo->uMajorVer = (uint8_t)ulMajorVersion;
151 pOsVerInfo->uMinorVer = (uint8_t)ulMinorVersion;
152 pOsVerInfo->uBuildNo = ulBuildNumber;
153#define MY_NIL_CSD 0x3f
154 pOsVerInfo->uCsdNo = MY_NIL_CSD;
155
156 if (g_pfnrtRtlGetVersion)
157 {
158 RTL_OSVERSIONINFOEXW VerInfo;
159 RT_ZERO(VerInfo);
160 VerInfo.dwOSVersionInfoSize = sizeof(VerInfo);
161
162 NTSTATUS rcNt = g_pfnrtRtlGetVersion(&VerInfo);
163 if (NT_SUCCESS(rcNt))
164 pOsVerInfo->uCsdNo = VerInfo.wServicePackMajor;
165 }
166
167 /* Note! We cannot quite say if something is MP or UNI. So, fSmp is
168 redefined to indicate that it must be MP.
169 Note! RTMpGetCount is not available here. */
170 pOsVerInfo->fSmp = ulMajorVersion >= 6; /* Vista and later has no UNI kernel AFAIK. */
171 if (!pOsVerInfo->fSmp)
172 {
173 if ( g_pfnrtKeQueryMaximumProcessorCountEx
174 && g_pfnrtKeQueryMaximumProcessorCountEx(ALL_PROCESSOR_GROUPS) > 1)
175 pOsVerInfo->fSmp = true;
176 else if ( g_pfnrtKeQueryMaximumProcessorCount
177 && g_pfnrtKeQueryMaximumProcessorCount() > 1)
178 pOsVerInfo->fSmp = true;
179 else if ( g_pfnrtKeQueryActiveProcessors
180 && g_pfnrtKeQueryActiveProcessors() > 1)
181 pOsVerInfo->fSmp = true;
182 else if (KeNumberProcessors > 1)
183 pOsVerInfo->fSmp = true;
184 }
185}
186
187
188/**
189 * Tries a set against the current kernel.
190 *
191 * @retval true if it matched up, global variables are updated.
192 * @retval false otherwise (no globals updated).
193 * @param pSet The data set.
194 * @param pbPrcb Pointer to the processor control block.
195 * @param pszVendor Pointer to the processor vendor string.
196 * @param pOsVerInfo The OS version info.
197 */
198static bool rtR0NtTryMatchSymSet(PCRTNTSDBSET pSet, uint8_t *pbPrcb, const char *pszVendor, PCRTNTSDBOSVER pOsVerInfo)
199{
200 /*
201 * Don't bother trying stuff where the NT kernel version number differs, or
202 * if the build type or SMPness doesn't match up.
203 */
204 if ( pSet->OsVerInfo.uMajorVer != pOsVerInfo->uMajorVer
205 || pSet->OsVerInfo.uMinorVer != pOsVerInfo->uMinorVer
206 || pSet->OsVerInfo.fChecked != pOsVerInfo->fChecked
207 || (!pSet->OsVerInfo.fSmp && pOsVerInfo->fSmp /*must-be-smp*/) )
208 {
209 //DbgPrint("IPRT: #%d Version/type mismatch.\n", pSet - &g_artNtSdbSets[0]);
210 return false;
211 }
212
213 /*
214 * Do the CPU vendor test.
215 *
216 * Note! The MmIsAddressValid call is the real #PF security here as the
217 * __try/__except has limited/no ability to catch everything we need.
218 */
219 char *pszPrcbVendorString = (char *)&pbPrcb[pSet->KPRCB.offVendorString];
220 if (!MmIsAddressValid(&pszPrcbVendorString[4 * 3 - 1]))
221 {
222 //DbgPrint("IPRT: #%d invalid vendor string address.\n", pSet - &g_artNtSdbSets[0]);
223 return false;
224 }
225 __try
226 {
227 if (memcmp(pszPrcbVendorString, pszVendor, RT_MIN(4 * 3, pSet->KPRCB.cbVendorString)) != 0)
228 {
229 //DbgPrint("IPRT: #%d Vendor string mismatch.\n", pSet - &g_artNtSdbSets[0]);
230 return false;
231 }
232 }
233 __except(EXCEPTION_EXECUTE_HANDLER)
234 {
235 DbgPrint("IPRT: %#d Exception\n", pSet - &g_artNtSdbSets[0]);
236 return false;
237 }
238
239 /*
240 * Got a match, update the global variables and report succcess.
241 */
242 g_offrtNtPbQuantumEnd = pSet->KPRCB.offQuantumEnd;
243 g_cbrtNtPbQuantumEnd = pSet->KPRCB.cbQuantumEnd;
244 g_offrtNtPbDpcQueueDepth = pSet->KPRCB.offDpcQueueDepth;
245
246#if 0
247 DbgPrint("IPRT: Using data set #%u for %u.%usp%u build %u %s %s.\n",
248 pSet - &g_artNtSdbSets[0],
249 pSet->OsVerInfo.uMajorVer,
250 pSet->OsVerInfo.uMinorVer,
251 pSet->OsVerInfo.uCsdNo,
252 pSet->OsVerInfo.uBuildNo,
253 pSet->OsVerInfo.fSmp ? "smp" : "uni",
254 pSet->OsVerInfo.fChecked ? "checked" : "free");
255#endif
256 return true;
257}
258
259
260DECLHIDDEN(int) rtR0InitNative(void)
261{
262 /*
263 * Initialize the function pointers.
264 */
265 RTDBGKRNLINFO hKrnlInfo;
266 int rc = RTR0DbgKrnlInfoOpen(&hKrnlInfo, 0/*fFlags*/);
267 AssertRCReturn(rc, rc);
268
269#define GET_SYSTEM_ROUTINE_EX(a_Prf, a_Name, a_pfnType) \
270 do { RT_CONCAT3(g_pfnrt, a_Prf, a_Name) = (a_pfnType)RTR0DbgKrnlInfoGetSymbol(hKrnlInfo, NULL, #a_Name); } while (0)
271#define GET_SYSTEM_ROUTINE(a_Name) GET_SYSTEM_ROUTINE_EX(RT_NOTHING, a_Name, decltype(a_Name) *)
272#define GET_SYSTEM_ROUTINE_PRF(a_Prf,a_Name) GET_SYSTEM_ROUTINE_EX(a_Prf, a_Name, decltype(a_Name) *)
273#define GET_SYSTEM_ROUTINE_TYPE(a_Name, a_pfnType) GET_SYSTEM_ROUTINE_EX(RT_NOTHING, a_Name, a_pfnType)
274
275 GET_SYSTEM_ROUTINE(ExAllocatePoolWithTag);
276 GET_SYSTEM_ROUTINE_PRF(Nt,ExSetTimerResolution);
277 GET_SYSTEM_ROUTINE_PRF(Nt,KeFlushQueuedDpcs);
278 GET_SYSTEM_ROUTINE(KeIpiGenericCall);
279 GET_SYSTEM_ROUTINE(KeSetTargetProcessorDpcEx);
280 GET_SYSTEM_ROUTINE(KeInitializeAffinityEx);
281 GET_SYSTEM_ROUTINE(KeAddProcessorAffinityEx);
282 GET_SYSTEM_ROUTINE_TYPE(KeGetProcessorIndexFromNumber, PFNKEGETPROCESSORINDEXFROMNUMBER);
283 GET_SYSTEM_ROUTINE(KeGetProcessorNumberFromIndex);
284 GET_SYSTEM_ROUTINE_TYPE(KeGetCurrentProcessorNumberEx, PFNKEGETCURRENTPROCESSORNUMBEREX);
285 GET_SYSTEM_ROUTINE(KeQueryActiveProcessors);
286 GET_SYSTEM_ROUTINE(KeQueryMaximumProcessorCount);
287 GET_SYSTEM_ROUTINE(KeQueryMaximumProcessorCountEx);
288 GET_SYSTEM_ROUTINE(KeQueryMaximumGroupCount);
289 GET_SYSTEM_ROUTINE(KeQueryActiveProcessorCount);
290 GET_SYSTEM_ROUTINE(KeQueryActiveProcessorCountEx);
291 GET_SYSTEM_ROUTINE(KeQueryLogicalProcessorRelationship);
292 GET_SYSTEM_ROUTINE(KeRegisterProcessorChangeCallback);
293 GET_SYSTEM_ROUTINE(KeDeregisterProcessorChangeCallback);
294 GET_SYSTEM_ROUTINE(MmProtectMdlSystemAddress);
295 GET_SYSTEM_ROUTINE(MmAllocatePagesForMdl);
296 GET_SYSTEM_ROUTINE(MmFreePagesFromMdl);
297 GET_SYSTEM_ROUTINE(MmMapLockedPagesSpecifyCache);
298 GET_SYSTEM_ROUTINE(MmAllocateContiguousMemorySpecifyCache);
299
300 GET_SYSTEM_ROUTINE_TYPE(RtlGetVersion, PFNRTRTLGETVERSION);
301#ifndef RT_ARCH_AMD64
302 GET_SYSTEM_ROUTINE(KeQueryInterruptTime);
303 GET_SYSTEM_ROUTINE(KeQuerySystemTime);
304#endif
305 GET_SYSTEM_ROUTINE_TYPE(KeQueryInterruptTimePrecise, PFNRTKEQUERYINTERRUPTTIMEPRECISE);
306 GET_SYSTEM_ROUTINE_TYPE(KeQuerySystemTimePrecise, PFNRTKEQUERYSYSTEMTIMEPRECISE);
307
308 g_pfnrtHalRequestIpiW7Plus = (PFNHALREQUESTIPI_W7PLUS)RTR0DbgKrnlInfoGetSymbol(hKrnlInfo, NULL, "HalRequestIpi");
309 g_pfnrtHalRequestIpiPreW7 = (PFNHALREQUESTIPI_PRE_W7)g_pfnrtHalRequestIpiW7Plus;
310
311 g_puRtMmHighestUserAddress = (uintptr_t const *)RTR0DbgKrnlInfoGetSymbol(hKrnlInfo, NULL, "MmHighestUserAddress");
312 g_puRtMmSystemRangeStart = (uintptr_t const *)RTR0DbgKrnlInfoGetSymbol(hKrnlInfo, NULL, "MmSystemRangeStart");
313
314 RTR0DbgKrnlInfoRelease(hKrnlInfo);
315
316 /*
317 * HACK ALERT! (and déjà vu warning - remember win32k.sys?)
318 *
319 * Try find _KPRCB::QuantumEnd and _KPRCB::[DpcData.]DpcQueueDepth.
320 * For purpose of verification we use the VendorString member (12+1 chars).
321 *
322 * The offsets was initially derived by poking around with windbg
323 * (dt _KPRCB, !prcb ++, and such like). Systematic harvesting was then
324 * planned using dia2dump, grep and the symbol pack in a manner like this:
325 * dia2dump -type _KDPC_DATA -type _KPRCB EXE\ntkrnlmp.pdb | grep -wE "QuantumEnd|DpcData|DpcQueueDepth|VendorString"
326 *
327 * The final solution ended up using a custom harvester program called
328 * ntBldSymDb that recursively searches thru unpacked symbol packages for
329 * the desired structure offsets. The program assumes that the packages
330 * are unpacked into directories with the same name as the package, with
331 * exception of some of the w2k packages which requires a 'w2k' prefix to
332 * be distinguishable from another.
333 */
334
335 RTNTSDBOSVER OsVerInfo;
336 rtR0NtGetOsVersionInfo(&OsVerInfo);
337
338 /* Publish the version info in globals. */
339 g_uRtNtVersion = RTNT_MAKE_VERSION(OsVerInfo.uMajorVer, OsVerInfo.uMinorVer);
340 g_uRtNtMinorVer = OsVerInfo.uMinorVer;
341 g_uRtNtMajorVer = OsVerInfo.uMajorVer;
342 g_uRtNtBuildNo = OsVerInfo.uBuildNo;
343
344 /*
345 * Gather consistent CPU vendor string and PRCB pointers.
346 */
347 KIRQL OldIrql;
348 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); /* make sure we stay on the same cpu */
349
350 union
351 {
352 uint32_t auRegs[4];
353 char szVendor[4*3+1];
354 } u;
355 ASMCpuId(0, &u.auRegs[3], &u.auRegs[0], &u.auRegs[2], &u.auRegs[1]);
356 u.szVendor[4*3] = '\0';
357
358 uint8_t *pbPrcb;
359 __try /* Warning. This try/except statement may provide some false safety. */
360 {
361#if defined(RT_ARCH_X86)
362 PKPCR pPcr = (PKPCR)__readfsdword(RT_OFFSETOF(KPCR,SelfPcr));
363 pbPrcb = (uint8_t *)pPcr->Prcb;
364#elif defined(RT_ARCH_AMD64)
365 PKPCR pPcr = (PKPCR)__readgsqword(RT_OFFSETOF(KPCR,Self));
366 pbPrcb = (uint8_t *)pPcr->CurrentPrcb;
367#else
368# error "port me"
369 pbPrcb = NULL;
370#endif
371 }
372 __except(EXCEPTION_EXECUTE_HANDLER)
373 {
374 pbPrcb = NULL;
375 }
376
377 /*
378 * Search the database
379 */
380 if (pbPrcb)
381 {
382 /* Find the best matching kernel version based on build number. */
383 uint32_t iBest = UINT32_MAX;
384 int32_t iBestDelta = INT32_MAX;
385 for (uint32_t i = 0; i < RT_ELEMENTS(g_artNtSdbSets); i++)
386 {
387 if (g_artNtSdbSets[i].OsVerInfo.fChecked != OsVerInfo.fChecked)
388 continue;
389 if (OsVerInfo.fSmp /*must-be-smp*/ && !g_artNtSdbSets[i].OsVerInfo.fSmp)
390 continue;
391
392 int32_t iDelta = RT_ABS((int32_t)OsVerInfo.uBuildNo - (int32_t)g_artNtSdbSets[i].OsVerInfo.uBuildNo);
393 if ( iDelta == 0
394 && (g_artNtSdbSets[i].OsVerInfo.uCsdNo == OsVerInfo.uCsdNo || OsVerInfo.uCsdNo == MY_NIL_CSD))
395 {
396 /* prefect */
397 iBestDelta = iDelta;
398 iBest = i;
399 break;
400 }
401 if ( iDelta < iBestDelta
402 || iBest == UINT32_MAX
403 || ( iDelta == iBestDelta
404 && OsVerInfo.uCsdNo != MY_NIL_CSD
405 && RT_ABS(g_artNtSdbSets[i ].OsVerInfo.uCsdNo - (int32_t)OsVerInfo.uCsdNo)
406 < RT_ABS(g_artNtSdbSets[iBest].OsVerInfo.uCsdNo - (int32_t)OsVerInfo.uCsdNo)
407 )
408 )
409 {
410 iBestDelta = iDelta;
411 iBest = i;
412 }
413 }
414 if (iBest < RT_ELEMENTS(g_artNtSdbSets))
415 {
416 /* Try all sets: iBest -> End; iBest -> Start. */
417 bool fDone = false;
418 int32_t i = iBest;
419 while ( i < RT_ELEMENTS(g_artNtSdbSets)
420 && !(fDone = rtR0NtTryMatchSymSet(&g_artNtSdbSets[i], pbPrcb, u.szVendor, &OsVerInfo)))
421 i++;
422 if (!fDone)
423 {
424 i = (int32_t)iBest - 1;
425 while ( i >= 0
426 && !(fDone = rtR0NtTryMatchSymSet(&g_artNtSdbSets[i], pbPrcb, u.szVendor, &OsVerInfo)))
427 i--;
428 }
429 }
430 else
431 DbgPrint("IPRT: Failed to locate data set.\n");
432 }
433 else
434 DbgPrint("IPRT: Failed to get PCBR pointer.\n");
435
436 KeLowerIrql(OldIrql); /* Lowering the IRQL early in the hope that we may catch exceptions below. */
437
438#ifndef IN_GUEST
439 if (!g_offrtNtPbQuantumEnd && !g_offrtNtPbDpcQueueDepth)
440 DbgPrint("IPRT: Neither _KPRCB::QuantumEnd nor _KPRCB::DpcQueueDepth was not found! Kernel %u.%u %u %s\n",
441 OsVerInfo.uMajorVer, OsVerInfo.uMinorVer, OsVerInfo.uBuildNo, OsVerInfo.fChecked ? "checked" : "free");
442# ifdef DEBUG
443 else
444 DbgPrint("IPRT: _KPRCB:{.QuantumEnd=%x/%d, .DpcQueueDepth=%x/%d} Kernel %u.%u %u %s\n",
445 g_offrtNtPbQuantumEnd, g_cbrtNtPbQuantumEnd, g_offrtNtPbDpcQueueDepth, g_offrtNtPbDpcQueueDepth,
446 OsVerInfo.uMajorVer, OsVerInfo.uMinorVer, OsVerInfo.uBuildNo, OsVerInfo.fChecked ? "checked" : "free");
447# endif
448#endif
449
450 /*
451 * Initialize multi processor stuff. This registers a callback, so
452 * we call rtR0TermNative to do the deregistration on failure.
453 */
454 rc = rtR0MpNtInit(&OsVerInfo);
455 if (RT_FAILURE(rc))
456 {
457 rtR0TermNative();
458 DbgPrint("IPRT: Fatal: rtR0MpNtInit failed: %d\n", rc);
459 return rc;
460 }
461
462 return VINF_SUCCESS;
463}
464
465
466DECLHIDDEN(void) rtR0TermNative(void)
467{
468 rtR0MpNtTerm();
469}
470
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette