Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3186 lines
99 KiB

  1. /*++
  2. Copyright (c) 1989-1993 Microsoft Corporation
  3. Module Name:
  4. ioinit.c
  5. Abstract:
  6. This module contains the code to initialize the I/O system.
  7. Author:
  8. Darryl E. Havens (darrylh) April 27, 1989
  9. Environment:
  10. Kernel mode, system initialization code
  11. Revision History:
  12. --*/
  13. #include "iomgr.h"
  14. #include <setupblk.h>
  15. #include <inbv.h>
  16. #include <ntddstor.h>
  17. #include <hdlsblk.h>
  18. #include <hdlsterm.h>
  19. //
  20. // Define the default number of IRP that can be in progress and allocated
  21. // from a lookaside list.
  22. //
  23. #define DEFAULT_LOOKASIDE_IRP_LIMIT 512
  24. //
  25. // I/O Error logging support
  26. //
  27. PVOID IopErrorLogObject = NULL;
  28. //
  29. // Define a macro for initializing drivers.
  30. //
  31. #define InitializeDriverObject( Object ) { \
  32. ULONG i; \
  33. RtlZeroMemory( Object, \
  34. sizeof( DRIVER_OBJECT ) + sizeof ( DRIVER_EXTENSION )); \
  35. Object->DriverExtension = (PDRIVER_EXTENSION) (Object + 1); \
  36. Object->DriverExtension->DriverObject = Object; \
  37. for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) \
  38. Object->MajorFunction[i] = IopInvalidDeviceRequest; \
  39. Object->Type = IO_TYPE_DRIVER; \
  40. Object->Size = sizeof( DRIVER_OBJECT ); \
  41. }
  42. ULONG IopInitFailCode; // Debugging aid for IoInitSystem
  43. //
  44. // Define external procedures not in common header files
  45. //
  46. VOID
  47. IopInitializeData(
  48. VOID
  49. );
  50. //
  51. // Define the local procedures
  52. //
  53. BOOLEAN
  54. IopCreateObjectTypes(
  55. VOID
  56. );
  57. BOOLEAN
  58. IopCreateRootDirectories(
  59. VOID
  60. );
  61. NTSTATUS
  62. IopInitializeAttributesAndCreateObject(
  63. IN PUNICODE_STRING ObjectName,
  64. IN OUT POBJECT_ATTRIBUTES ObjectAttributes,
  65. OUT PDRIVER_OBJECT *DriverObject
  66. );
  67. BOOLEAN
  68. IopReassignSystemRoot(
  69. IN PLOADER_PARAMETER_BLOCK LoaderBlock,
  70. OUT PSTRING NtDeviceName
  71. );
  72. VOID
  73. IopSetIoRoutines(
  74. IN VOID
  75. );
  76. VOID
  77. IopStoreSystemPartitionInformation(
  78. IN PUNICODE_STRING NtSystemPartitionDeviceName,
  79. IN OUT PUNICODE_STRING OsLoaderPathName
  80. );
  81. //
  82. // The following allows the I/O system's initialization routines to be
  83. // paged out of memory.
  84. //
  85. #ifdef ALLOC_PRAGMA
  86. #pragma alloc_text(INIT,IoInitSystem)
  87. #pragma alloc_text(INIT,IopCreateArcNames)
  88. #pragma alloc_text(INIT,IopCreateObjectTypes)
  89. #pragma alloc_text(INIT,IopCreateRootDirectories)
  90. #pragma alloc_text(INIT,IopInitializeAttributesAndCreateObject)
  91. #pragma alloc_text(INIT,IopInitializeBuiltinDriver)
  92. #pragma alloc_text(INIT,IopMarkBootPartition)
  93. #pragma alloc_text(INIT,IopReassignSystemRoot)
  94. #pragma alloc_text(INIT,IopSetIoRoutines)
  95. #pragma alloc_text(INIT,IopStoreSystemPartitionInformation)
  96. #pragma alloc_text(INIT,IopInitializeReserveIrp)
  97. #endif
  98. BOOLEAN
  99. IoInitSystem(
  100. PLOADER_PARAMETER_BLOCK LoaderBlock
  101. )
  102. /*++
  103. Routine Description:
  104. This routine initializes the I/O system.
  105. Arguments:
  106. LoaderBlock - Supplies a pointer to the loader parameter block that was
  107. created by the OS Loader.
  108. Return Value:
  109. The function value is a BOOLEAN indicating whether or not the I/O system
  110. was successfully initialized.
  111. --*/
  112. {
  113. PDRIVER_OBJECT driverObject;
  114. PDRIVER_OBJECT *nextDriverObject;
  115. STRING ntDeviceName;
  116. UCHAR deviceNameBuffer[256];
  117. ULONG largePacketSize;
  118. ULONG smallPacketSize;
  119. ULONG mdlPacketSize;
  120. PLIST_ENTRY entry;
  121. LARGE_INTEGER deltaTime;
  122. MM_SYSTEMSIZE systemSize;
  123. USHORT completionZoneSize;
  124. USHORT largeIrpZoneSize;
  125. USHORT smallIrpZoneSize;
  126. USHORT mdlZoneSize;
  127. ULONG oldNtGlobalFlag;
  128. NTSTATUS status;
  129. ANSI_STRING ansiString;
  130. UNICODE_STRING eventName;
  131. UNICODE_STRING startTypeName;
  132. OBJECT_ATTRIBUTES objectAttributes;
  133. HANDLE handle;
  134. PGENERAL_LOOKASIDE lookaside;
  135. ULONG lookasideIrpLimit;
  136. ULONG lookasideSize;
  137. ULONG Index;
  138. PKPRCB prcb;
  139. ULONG len;
  140. PKEY_VALUE_PARTIAL_INFORMATION value;
  141. UCHAR valueBuffer[32];
  142. ASSERT( IopQueryOperationLength[FileMaximumInformation] == 0xff );
  143. ASSERT( IopSetOperationLength[FileMaximumInformation] == 0xff );
  144. ASSERT( IopQueryOperationAccess[FileMaximumInformation] == 0xffffffff );
  145. ASSERT( IopSetOperationAccess[FileMaximumInformation] == 0xffffffff );
  146. ASSERT( IopQueryFsOperationLength[FileFsMaximumInformation] == 0xff );
  147. ASSERT( IopSetFsOperationLength[FileFsMaximumInformation] == 0xff );
  148. ASSERT( IopQueryFsOperationAccess[FileFsMaximumInformation] == 0xffffffff );
  149. ASSERT( IopSetFsOperationAccess[FileFsMaximumInformation] == 0xffffffff );
  150. //
  151. // Initialize the I/O database resource, lock, and the file system and
  152. // network file system queue headers. Also allocate the cancel spin
  153. // lock.
  154. //
  155. ntDeviceName.Buffer = deviceNameBuffer;
  156. ntDeviceName.MaximumLength = sizeof(deviceNameBuffer);
  157. ntDeviceName.Length = 0;
  158. ExInitializeResourceLite( &IopDatabaseResource );
  159. ExInitializeResourceLite( &IopSecurityResource );
  160. ExInitializeResourceLite( &IopCrashDumpLock );
  161. InitializeListHead( &IopDiskFileSystemQueueHead );
  162. InitializeListHead( &IopCdRomFileSystemQueueHead );
  163. InitializeListHead( &IopTapeFileSystemQueueHead );
  164. InitializeListHead( &IopNetworkFileSystemQueueHead );
  165. InitializeListHead( &IopBootDriverReinitializeQueueHead );
  166. InitializeListHead( &IopDriverReinitializeQueueHead );
  167. InitializeListHead( &IopNotifyShutdownQueueHead );
  168. InitializeListHead( &IopNotifyLastChanceShutdownQueueHead );
  169. InitializeListHead( &IopFsNotifyChangeQueueHead );
  170. KeInitializeSpinLock( &IoStatisticsLock );
  171. IopSetIoRoutines();
  172. //
  173. // Initialize the unique device object number counter used by IoCreateDevice
  174. // when automatically generating a device object name.
  175. //
  176. IopUniqueDeviceObjectNumber = 0;
  177. //
  178. // Initialize the large I/O Request Packet (IRP) lookaside list head and the
  179. // mutex which guards the list.
  180. //
  181. if (!IopLargeIrpStackLocations) {
  182. IopLargeIrpStackLocations = DEFAULT_LARGE_IRP_LOCATIONS;
  183. IopIrpStackProfiler.Flags |= IOP_ENABLE_AUTO_SIZING;
  184. }
  185. systemSize = MmQuerySystemSize();
  186. switch ( systemSize ) {
  187. case MmSmallSystem :
  188. completionZoneSize = 6;
  189. smallIrpZoneSize = 6;
  190. largeIrpZoneSize = 8;
  191. mdlZoneSize = 16;
  192. lookasideIrpLimit = DEFAULT_LOOKASIDE_IRP_LIMIT;
  193. break;
  194. case MmMediumSystem :
  195. completionZoneSize = 24;
  196. smallIrpZoneSize = 24;
  197. largeIrpZoneSize = 32;
  198. mdlZoneSize = 90;
  199. lookasideIrpLimit = DEFAULT_LOOKASIDE_IRP_LIMIT * 2;
  200. break;
  201. case MmLargeSystem :
  202. if (MmIsThisAnNtAsSystem()) {
  203. completionZoneSize = 96;
  204. smallIrpZoneSize = 96;
  205. largeIrpZoneSize = 128;
  206. mdlZoneSize = 256;
  207. lookasideIrpLimit = DEFAULT_LOOKASIDE_IRP_LIMIT * 128; // 64k
  208. } else {
  209. completionZoneSize = 32;
  210. smallIrpZoneSize = 32;
  211. largeIrpZoneSize = 64;
  212. mdlZoneSize = 128;
  213. lookasideIrpLimit = DEFAULT_LOOKASIDE_IRP_LIMIT * 3;
  214. }
  215. break;
  216. }
  217. //
  218. // Initialize the system I/O completion lookaside list.
  219. //
  220. ExInitializeSystemLookasideList( &IopCompletionLookasideList,
  221. NonPagedPool,
  222. sizeof(IOP_MINI_COMPLETION_PACKET),
  223. ' pcI',
  224. completionZoneSize,
  225. &ExSystemLookasideListHead );
  226. //
  227. // Initialize the system large IRP lookaside list.
  228. //
  229. largePacketSize = (ULONG) (sizeof( IRP ) + (IopLargeIrpStackLocations * sizeof( IO_STACK_LOCATION )));
  230. ExInitializeSystemLookasideList( &IopLargeIrpLookasideList,
  231. NonPagedPool,
  232. largePacketSize,
  233. 'lprI',
  234. largeIrpZoneSize,
  235. &ExSystemLookasideListHead );
  236. //
  237. // Initialize the system small IRP lookaside list.
  238. //
  239. smallPacketSize = (ULONG) (sizeof( IRP ) + sizeof( IO_STACK_LOCATION ));
  240. ExInitializeSystemLookasideList( &IopSmallIrpLookasideList,
  241. NonPagedPool,
  242. smallPacketSize,
  243. 'sprI',
  244. smallIrpZoneSize,
  245. &ExSystemLookasideListHead );
  246. //
  247. // Initialize the system MDL lookaside list.
  248. //
  249. mdlPacketSize = (ULONG) (sizeof( MDL ) + (IOP_FIXED_SIZE_MDL_PFNS * sizeof( PFN_NUMBER )));
  250. ExInitializeSystemLookasideList( &IopMdlLookasideList,
  251. NonPagedPool,
  252. mdlPacketSize,
  253. ' ldM',
  254. mdlZoneSize,
  255. &ExSystemLookasideListHead );
  256. //
  257. // Compute the lookaside IRP float credits per processor.
  258. //
  259. lookasideIrpLimit /= KeNumberProcessors;
  260. //
  261. // Initialize the per processor nonpaged lookaside lists and descriptors.
  262. //
  263. // N.B. All the I/O related lookaside list structures are allocated at
  264. // one time to make sure they are aligned, if possible, and to avoid
  265. // pool overhead.
  266. //
  267. lookasideSize = 4 * KeNumberProcessors * sizeof(GENERAL_LOOKASIDE);
  268. lookaside = ExAllocatePoolWithTag( NonPagedPool, lookasideSize, 'oI');
  269. for (Index = 0; Index < (ULONG)KeNumberProcessors; Index += 1) {
  270. prcb = KiProcessorBlock[Index];
  271. //
  272. // Set the per processor IRP float credits.
  273. //
  274. prcb->LookasideIrpFloat = lookasideIrpLimit;
  275. //
  276. // Initialize the I/O completion per processor lookaside pointers
  277. //
  278. prcb->PPLookasideList[LookasideCompletionList].L = &IopCompletionLookasideList;
  279. if (lookaside != NULL) {
  280. ExInitializeSystemLookasideList( lookaside,
  281. NonPagedPool,
  282. sizeof(IOP_MINI_COMPLETION_PACKET),
  283. 'PpcI',
  284. completionZoneSize,
  285. &ExSystemLookasideListHead );
  286. prcb->PPLookasideList[LookasideCompletionList].P = lookaside;
  287. lookaside += 1;
  288. } else {
  289. prcb->PPLookasideList[LookasideCompletionList].P = &IopCompletionLookasideList;
  290. }
  291. //
  292. // Initialize the large IRP per processor lookaside pointers.
  293. //
  294. prcb->PPLookasideList[LookasideLargeIrpList].L = &IopLargeIrpLookasideList;
  295. if (lookaside != NULL) {
  296. ExInitializeSystemLookasideList( lookaside,
  297. NonPagedPool,
  298. largePacketSize,
  299. 'LprI',
  300. largeIrpZoneSize,
  301. &ExSystemLookasideListHead );
  302. prcb->PPLookasideList[LookasideLargeIrpList].P = lookaside;
  303. lookaside += 1;
  304. } else {
  305. prcb->PPLookasideList[LookasideLargeIrpList].P = &IopLargeIrpLookasideList;
  306. }
  307. //
  308. // Initialize the small IRP per processor lookaside pointers.
  309. //
  310. prcb->PPLookasideList[LookasideSmallIrpList].L = &IopSmallIrpLookasideList;
  311. if (lookaside != NULL) {
  312. ExInitializeSystemLookasideList( lookaside,
  313. NonPagedPool,
  314. smallPacketSize,
  315. 'SprI',
  316. smallIrpZoneSize,
  317. &ExSystemLookasideListHead );
  318. prcb->PPLookasideList[LookasideSmallIrpList].P = lookaside;
  319. lookaside += 1;
  320. } else {
  321. prcb->PPLookasideList[LookasideSmallIrpList].P = &IopSmallIrpLookasideList;
  322. }
  323. //
  324. // Initialize the MDL per processor lookaside list pointers.
  325. //
  326. prcb->PPLookasideList[LookasideMdlList].L = &IopMdlLookasideList;
  327. if (lookaside != NULL) {
  328. ExInitializeSystemLookasideList( lookaside,
  329. NonPagedPool,
  330. mdlPacketSize,
  331. 'PldM',
  332. mdlZoneSize,
  333. &ExSystemLookasideListHead );
  334. prcb->PPLookasideList[LookasideMdlList].P = lookaside;
  335. lookaside += 1;
  336. } else {
  337. prcb->PPLookasideList[LookasideMdlList].P = &IopMdlLookasideList;
  338. }
  339. }
  340. //
  341. // Initalize the error log spin locks and log list.
  342. //
  343. KeInitializeSpinLock( &IopErrorLogLock );
  344. InitializeListHead( &IopErrorLogListHead );
  345. if (IopInitializeReserveIrp(&IopReserveIrpAllocator) == FALSE) {
  346. IopInitFailCode = 1;
  347. return FALSE;
  348. }
  349. if (IopIrpAutoSizingEnabled() && !NT_SUCCESS(IopInitializeIrpStackProfiler())) {
  350. IopInitFailCode = 13;
  351. return FALSE;
  352. }
  353. //
  354. // Determine if the Error Log service will ever run this boot.
  355. //
  356. InitializeObjectAttributes (&objectAttributes,
  357. &CmRegistryMachineSystemCurrentControlSetServicesEventLog,
  358. OBJ_CASE_INSENSITIVE,
  359. (HANDLE) NULL,
  360. (PSECURITY_DESCRIPTOR) NULL );
  361. status = ZwOpenKey(&handle,
  362. KEY_READ,
  363. &objectAttributes
  364. );
  365. if (NT_SUCCESS (status)) {
  366. RtlInitUnicodeString (&startTypeName, L"Start");
  367. value = (PKEY_VALUE_PARTIAL_INFORMATION) valueBuffer;
  368. status = NtQueryValueKey (handle,
  369. &startTypeName,
  370. KeyValuePartialInformation,
  371. valueBuffer,
  372. sizeof (valueBuffer),
  373. &len);
  374. if (NT_SUCCESS (status) && (value->Type == REG_DWORD)) {
  375. if (SERVICE_DISABLED == (*(PULONG) (value->Data))) {
  376. //
  377. // We are disabled for this boot.
  378. //
  379. IopErrorLogDisabledThisBoot = TRUE;
  380. } else {
  381. IopErrorLogDisabledThisBoot = FALSE;
  382. }
  383. } else {
  384. //
  385. // Didn't find the value so we are not enabled.
  386. //
  387. IopErrorLogDisabledThisBoot = TRUE;
  388. }
  389. } else {
  390. //
  391. // Didn't find the key so we are not enabled
  392. //
  393. IopErrorLogDisabledThisBoot = TRUE;
  394. }
  395. //
  396. // Initialize the timer database and start the timer DPC routine firing
  397. // so that drivers can use it during initialization.
  398. //
  399. deltaTime.QuadPart = - 10 * 1000 * 1000;
  400. KeInitializeSpinLock( &IopTimerLock );
  401. InitializeListHead( &IopTimerQueueHead );
  402. KeInitializeDpc( &IopTimerDpc, IopTimerDispatch, NULL );
  403. KeInitializeTimerEx( &IopTimer, SynchronizationTimer );
  404. (VOID) KeSetTimerEx( &IopTimer, deltaTime, 1000, &IopTimerDpc );
  405. //
  406. // Initialize the IopHardError structure used for informational pop-ups.
  407. //
  408. ExInitializeWorkItem( &IopHardError.ExWorkItem,
  409. IopHardErrorThread,
  410. NULL );
  411. InitializeListHead( &IopHardError.WorkQueue );
  412. KeInitializeSpinLock( &IopHardError.WorkQueueSpinLock );
  413. KeInitializeSemaphore( &IopHardError.WorkQueueSemaphore,
  414. 0,
  415. MAXLONG );
  416. IopHardError.ThreadStarted = FALSE;
  417. IopCurrentHardError = NULL;
  418. //
  419. // Create the link tracking named event.
  420. //
  421. RtlInitUnicodeString( &eventName, L"\\Security\\TRKWKS_EVENT" );
  422. InitializeObjectAttributes( &objectAttributes,
  423. &eventName,
  424. OBJ_PERMANENT,
  425. (HANDLE) NULL,
  426. (PSECURITY_DESCRIPTOR) NULL );
  427. status = NtCreateEvent( &handle,
  428. EVENT_ALL_ACCESS,
  429. &objectAttributes,
  430. NotificationEvent,
  431. FALSE );
  432. if (!NT_SUCCESS( status )) {
  433. #if DBG
  434. DbgPrint( "IOINIT: NtCreateEvent failed\n" );
  435. #endif
  436. HeadlessKernelAddLogEntry(HEADLESS_LOG_EVENT_CREATE_FAILED, NULL);
  437. return FALSE;
  438. }
  439. (VOID) ObReferenceObjectByHandle( handle,
  440. 0,
  441. ExEventObjectType,
  442. KernelMode,
  443. (PVOID *) &IopLinkTrackingServiceEvent,
  444. NULL );
  445. KeInitializeEvent( &IopLinkTrackingPacket.Event, NotificationEvent, FALSE );
  446. KeInitializeEvent(&IopLinkTrackingPortObject, SynchronizationEvent, TRUE );
  447. //
  448. // Create all of the objects for the I/O system.
  449. //
  450. if (!IopCreateObjectTypes()) {
  451. #if DBG
  452. DbgPrint( "IOINIT: IopCreateObjectTypes failed\n" );
  453. #endif
  454. HeadlessKernelAddLogEntry(HEADLESS_LOG_OBJECT_TYPE_CREATE_FAILED, NULL);
  455. IopInitFailCode = 2;
  456. return FALSE;
  457. }
  458. //
  459. // Create the root directories for the I/O system.
  460. //
  461. if (!IopCreateRootDirectories()) {
  462. #if DBG
  463. DbgPrint( "IOINIT: IopCreateRootDirectories failed\n" );
  464. #endif
  465. HeadlessKernelAddLogEntry(HEADLESS_LOG_ROOT_DIR_CREATE_FAILED, NULL);
  466. IopInitFailCode = 3;
  467. return FALSE;
  468. }
  469. //
  470. // Initialize PlugPlay services phase 0
  471. //
  472. status = IopInitializePlugPlayServices(LoaderBlock, 0);
  473. if (!NT_SUCCESS(status)) {
  474. HeadlessKernelAddLogEntry(HEADLESS_LOG_PNP_PHASE0_INIT_FAILED, NULL);
  475. IopInitFailCode = 4;
  476. return FALSE;
  477. }
  478. //
  479. // Call Power manager to initialize for drivers
  480. //
  481. PoInitDriverServices(0);
  482. //
  483. // Call HAL to initialize PnP bus driver
  484. //
  485. HalInitPnpDriver();
  486. IopMarkHalDeviceNode();
  487. //
  488. // Call WMI to initialize it and allow it to create its driver object
  489. // Note that no calls to WMI can occur until it is initialized here.
  490. //
  491. WMIInitialize(0, (PVOID)LoaderBlock);
  492. //
  493. // Save this for use during PnP enumeration -- we NULL it out later
  494. // before LoaderBlock is reused.
  495. //
  496. IopLoaderBlock = (PVOID)LoaderBlock;
  497. //
  498. // If this is a remote boot, we need to add a few values to the registry.
  499. //
  500. if (IoRemoteBootClient) {
  501. status = IopAddRemoteBootValuesToRegistry(LoaderBlock);
  502. if (!NT_SUCCESS(status)) {
  503. KeBugCheckEx( NETWORK_BOOT_INITIALIZATION_FAILED,
  504. 1,
  505. status,
  506. 0,
  507. 0 );
  508. }
  509. }
  510. //
  511. // Initialize PlugPlay services phase 1 to execute firmware mapper
  512. //
  513. status = IopInitializePlugPlayServices(LoaderBlock, 1);
  514. if (!NT_SUCCESS(status)) {
  515. HeadlessKernelAddLogEntry(HEADLESS_LOG_PNP_PHASE1_INIT_FAILED, NULL);
  516. IopInitFailCode = 5;
  517. return FALSE;
  518. }
  519. //
  520. // Initialize the drivers loaded by the boot loader (OSLOADER)
  521. //
  522. nextDriverObject = &driverObject;
  523. if (!IopInitializeBootDrivers( LoaderBlock,
  524. nextDriverObject )) {
  525. #if DBG
  526. DbgPrint( "IOINIT: Initializing boot drivers failed\n" );
  527. #endif // DBG
  528. HeadlessKernelAddLogEntry(HEADLESS_LOG_BOOT_DRIVERS_INIT_FAILED, NULL);
  529. IopInitFailCode = 6;
  530. return FALSE;
  531. }
  532. //
  533. // Once we have initialized the boot drivers, we don't need the
  534. // copy of the pointer to the loader block any more.
  535. //
  536. IopLoaderBlock = NULL;
  537. //
  538. // If this is a remote boot, start the network and assign
  539. // C: to \Device\LanmanRedirector.
  540. //
  541. if (IoRemoteBootClient) {
  542. status = IopStartNetworkForRemoteBoot(LoaderBlock);
  543. if (!NT_SUCCESS( status )) {
  544. KeBugCheckEx( NETWORK_BOOT_INITIALIZATION_FAILED,
  545. 2,
  546. status,
  547. 0,
  548. 0 );
  549. }
  550. }
  551. //
  552. // Do last known good boot processing. If this is a last known good boot,
  553. // we will copy over the last known good drivers and files. Otherwise we
  554. // will ensure this boot doesn't taint our last good info (in case we crash
  555. // before the boot is marked good). Note that loading of the correct boot
  556. // drivers was handled by the boot loader, who chose an LKG boot in the
  557. // first place.
  558. //
  559. PpLastGoodDoBootProcessing();
  560. //
  561. // Save the current value of the NT Global Flags and enable kernel debugger
  562. // symbol loading while drivers are being loaded so that systems can be
  563. // debugged regardless of whether they are free or checked builds.
  564. //
  565. oldNtGlobalFlag = NtGlobalFlag;
  566. if (!(NtGlobalFlag & FLG_ENABLE_KDEBUG_SYMBOL_LOAD)) {
  567. NtGlobalFlag |= FLG_ENABLE_KDEBUG_SYMBOL_LOAD;
  568. }
  569. status = PsLocateSystemDll();
  570. if (!NT_SUCCESS( status )) {
  571. HeadlessKernelAddLogEntry(HEADLESS_LOG_LOCATE_SYSTEM_DLL_FAILED, NULL);
  572. IopInitFailCode = 7;
  573. return FALSE;
  574. }
  575. //
  576. // Notify the boot prefetcher of boot progress.
  577. //
  578. CcPfBeginBootPhase(PfSystemDriverInitPhase);
  579. //
  580. // Initialize the device drivers for the system.
  581. //
  582. if (!IopInitializeSystemDrivers()) {
  583. #if DBG
  584. DbgPrint( "IOINIT: Initializing system drivers failed\n" );
  585. #endif // DBG
  586. HeadlessKernelAddLogEntry(HEADLESS_LOG_SYSTEM_DRIVERS_INIT_FAILED, NULL);
  587. IopInitFailCode = 8;
  588. return FALSE;
  589. }
  590. IopCallDriverReinitializationRoutines();
  591. //
  592. // Reassign \SystemRoot to NT device name path.
  593. //
  594. if (!IopReassignSystemRoot( LoaderBlock, &ntDeviceName )) {
  595. HeadlessKernelAddLogEntry(HEADLESS_LOG_ASSIGN_SYSTEM_ROOT_FAILED, NULL);
  596. IopInitFailCode = 9;
  597. return FALSE;
  598. }
  599. //
  600. // Protect the system partition of an ARC system if necessary
  601. //
  602. if (!IopProtectSystemPartition( LoaderBlock )) {
  603. HeadlessKernelAddLogEntry(HEADLESS_LOG_PROTECT_SYSTEM_ROOT_FAILED, NULL);
  604. IopInitFailCode = 10;
  605. return FALSE;
  606. }
  607. //
  608. // Assign DOS drive letters to disks and cdroms and define \SystemRoot.
  609. //
  610. ansiString.MaximumLength = NtSystemRoot.MaximumLength / sizeof( WCHAR );
  611. ansiString.Length = 0;
  612. ansiString.Buffer = (RtlAllocateStringRoutine)( ansiString.MaximumLength );
  613. status = RtlUnicodeStringToAnsiString( &ansiString,
  614. &NtSystemRoot,
  615. FALSE
  616. );
  617. if (!NT_SUCCESS( status )) {
  618. DbgPrint( "IOINIT: UnicodeToAnsi( %wZ ) failed - %x\n", &NtSystemRoot, status );
  619. HeadlessKernelAddLogEntry(HEADLESS_LOG_UNICODE_TO_ANSI_FAILED, NULL);
  620. IopInitFailCode = 11;
  621. return FALSE;
  622. }
  623. IoAssignDriveLetters( LoaderBlock,
  624. &ntDeviceName,
  625. ansiString.Buffer,
  626. &ansiString );
  627. status = RtlAnsiStringToUnicodeString( &NtSystemRoot,
  628. &ansiString,
  629. FALSE
  630. );
  631. if (!NT_SUCCESS( status )) {
  632. DbgPrint( "IOINIT: AnsiToUnicode( %Z ) failed - %x\n", &ansiString, status );
  633. HeadlessKernelAddLogEntry(HEADLESS_LOG_ANSI_TO_UNICODE_FAILED, NULL);
  634. IopInitFailCode = 12;
  635. return FALSE;
  636. }
  637. //
  638. // Also restore the NT Global Flags to their original state.
  639. //
  640. NtGlobalFlag = oldNtGlobalFlag;
  641. //
  642. // Let WMI have a second chance to initialize, now that all drivers
  643. // are started and should be ready to get WMI irps
  644. //
  645. WMIInitialize(1, NULL);
  646. //
  647. // Call Power manager to initialize for post-boot drivers
  648. //
  649. PoInitDriverServices(1);
  650. //
  651. // Indicate that the I/O system successfully initialized itself.
  652. //
  653. return TRUE;
  654. }
  655. VOID
  656. IopSetIoRoutines()
  657. {
  658. if (pIofCallDriver == NULL) {
  659. pIofCallDriver = IopfCallDriver;
  660. }
  661. if (pIofCompleteRequest == NULL) {
  662. pIofCompleteRequest = IopfCompleteRequest;
  663. }
  664. if (pIoAllocateIrp == NULL) {
  665. pIoAllocateIrp = IopAllocateIrpPrivate;
  666. }
  667. if (pIoFreeIrp == NULL) {
  668. pIoFreeIrp = IopFreeIrp;
  669. }
  670. }
  671. VOID
  672. IopCreateArcNames(
  673. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  674. )
  675. /*++
  676. Routine Description:
  677. The loader block contains a table of disk signatures and corresponding
  678. ARC names. Each device that the loader can access will appear in the
  679. table. This routine opens each disk device in the system, reads the
  680. signature and compares it to the table. For each match, it creates a
  681. symbolic link between the nt device name and the ARC name.
  682. The checksum value provided by the loader is the ULONG sum of all
  683. elements in the checksum, inverted, plus 1:
  684. checksum = ~sum + 1;
  685. This way the sum of all of the elements can be calculated here and
  686. added to the checksum in the loader block. If the result is zero, then
  687. there is a match.
  688. Arguments:
  689. LoaderBlock - Supplies a pointer to the loader parameter block that was
  690. created by the OS Loader.
  691. Return Value:
  692. None.
  693. --*/
  694. {
  695. STRING arcBootDeviceString;
  696. UCHAR deviceNameBuffer[128];
  697. STRING deviceNameString;
  698. UNICODE_STRING deviceNameUnicodeString;
  699. PDEVICE_OBJECT deviceObject;
  700. UCHAR arcNameBuffer[128];
  701. STRING arcNameString;
  702. UNICODE_STRING arcNameUnicodeString;
  703. PFILE_OBJECT fileObject;
  704. NTSTATUS status;
  705. IO_STATUS_BLOCK ioStatusBlock;
  706. DISK_GEOMETRY diskGeometry;
  707. PDRIVE_LAYOUT_INFORMATION_EX driveLayout;
  708. PLIST_ENTRY listEntry;
  709. PARC_DISK_SIGNATURE diskBlock;
  710. ULONG diskNumber;
  711. ULONG partitionNumber;
  712. PCHAR arcName;
  713. PULONG buffer;
  714. PIRP irp;
  715. KEVENT event;
  716. LARGE_INTEGER offset;
  717. ULONG checkSum;
  718. ULONG i;
  719. PVOID tmpPtr;
  720. BOOLEAN useLegacyEnumeration = FALSE;
  721. BOOLEAN singleBiosDiskFound;
  722. BOOLEAN bootDiskFound = FALSE;
  723. PARC_DISK_INFORMATION arcInformation = LoaderBlock->ArcDiskInformation;
  724. ULONG totalDriverDisksFound = IoGetConfigurationInformation()->DiskCount;
  725. ULONG totalPnpDisksFound = 0;
  726. STRING arcSystemDeviceString;
  727. STRING osLoaderPathString;
  728. UNICODE_STRING osLoaderPathUnicodeString;
  729. PWSTR diskList = NULL;
  730. wchar_t *pDiskNameList;
  731. STORAGE_DEVICE_NUMBER pnpDiskDeviceNumber;
  732. ULONG diskSignature;
  733. //
  734. // ask PNP to give us a list with all the currently active disks
  735. //
  736. pDiskNameList = diskList;
  737. pnpDiskDeviceNumber.DeviceNumber = 0xFFFFFFFF;
  738. status = IoGetDeviceInterfaces(&DiskClassGuid, NULL, 0, &diskList);
  739. if (!NT_SUCCESS(status)) {
  740. useLegacyEnumeration = TRUE;
  741. if (pDiskNameList) {
  742. *pDiskNameList = L'\0';
  743. }
  744. } else {
  745. //
  746. // count the number of disks returned
  747. //
  748. pDiskNameList = diskList;
  749. while (*pDiskNameList != L'\0') {
  750. totalPnpDisksFound++;
  751. pDiskNameList = pDiskNameList + (wcslen(pDiskNameList) + 1);
  752. }
  753. pDiskNameList = diskList;
  754. //
  755. // if the disk returned by PNP are not all the disks in the system
  756. // it means that some legacy driver has generated a disk device object/link.
  757. // In that case we need to enumerate all pnp disks and then using the legacy
  758. // for-loop also enumerate the non-pnp disks
  759. //
  760. if (totalPnpDisksFound < totalDriverDisksFound) {
  761. useLegacyEnumeration = TRUE;
  762. }
  763. }
  764. //
  765. // If a single bios disk was found if there is only a
  766. // single entry on the disk signature list.
  767. //
  768. singleBiosDiskFound = (arcInformation->DiskSignatures.Flink->Flink ==
  769. &arcInformation->DiskSignatures) ? (TRUE) : (FALSE);
  770. //
  771. // Create hal/loader partition name
  772. //
  773. sprintf( arcNameBuffer, "\\ArcName\\%s", LoaderBlock->ArcHalDeviceName );
  774. RtlInitAnsiString( &arcNameString, arcNameBuffer );
  775. RtlAnsiStringToUnicodeString (&IoArcHalDeviceName, &arcNameString, TRUE);
  776. //
  777. // Create boot partition name
  778. //
  779. sprintf( arcNameBuffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName );
  780. RtlInitAnsiString( &arcNameString, arcNameBuffer );
  781. RtlAnsiStringToUnicodeString (&IoArcBootDeviceName, &arcNameString, TRUE);
  782. i = strlen (LoaderBlock->ArcBootDeviceName) + 1;
  783. IoLoaderArcBootDeviceName = ExAllocatePool (PagedPool, i);
  784. if (IoLoaderArcBootDeviceName) {
  785. memcpy (IoLoaderArcBootDeviceName, LoaderBlock->ArcBootDeviceName, i);
  786. }
  787. if (singleBiosDiskFound && strstr(LoaderBlock->ArcBootDeviceName, "cdrom")) {
  788. singleBiosDiskFound = FALSE;
  789. }
  790. //
  791. // Get ARC boot device name from loader block.
  792. //
  793. RtlInitAnsiString( &arcBootDeviceString,
  794. LoaderBlock->ArcBootDeviceName );
  795. //
  796. // Get ARC system device name from loader block.
  797. //
  798. RtlInitAnsiString( &arcSystemDeviceString,
  799. LoaderBlock->ArcHalDeviceName );
  800. //
  801. // If this is a remote boot, create an ArcName for the redirector path.
  802. //
  803. if (IoRemoteBootClient) {
  804. bootDiskFound = TRUE;
  805. RtlInitAnsiString( &deviceNameString, "\\Device\\LanmanRedirector" );
  806. status = RtlAnsiStringToUnicodeString( &deviceNameUnicodeString,
  807. &deviceNameString,
  808. TRUE );
  809. if (NT_SUCCESS( status )) {
  810. sprintf( arcNameBuffer,
  811. "\\ArcName\\%s",
  812. LoaderBlock->ArcBootDeviceName );
  813. RtlInitAnsiString( &arcNameString, arcNameBuffer );
  814. status = RtlAnsiStringToUnicodeString( &arcNameUnicodeString,
  815. &arcNameString,
  816. TRUE );
  817. if (NT_SUCCESS( status )) {
  818. //
  819. // Create symbolic link between NT device name and ARC name.
  820. //
  821. IoCreateSymbolicLink( &arcNameUnicodeString,
  822. &deviceNameUnicodeString );
  823. RtlFreeUnicodeString( &arcNameUnicodeString );
  824. //
  825. // We've found the system partition--store it away in the registry
  826. // to later be transferred to a application-friendly location.
  827. //
  828. RtlInitAnsiString( &osLoaderPathString, LoaderBlock->NtHalPathName );
  829. status = RtlAnsiStringToUnicodeString( &osLoaderPathUnicodeString,
  830. &osLoaderPathString,
  831. TRUE );
  832. #if DBG
  833. if (!NT_SUCCESS( status )) {
  834. DbgPrint("IopCreateArcNames: couldn't allocate unicode string for OsLoader path - %x\n", status);
  835. }
  836. #endif // DBG
  837. if (NT_SUCCESS( status )) {
  838. IopStoreSystemPartitionInformation( &deviceNameUnicodeString,
  839. &osLoaderPathUnicodeString );
  840. RtlFreeUnicodeString( &osLoaderPathUnicodeString );
  841. }
  842. }
  843. RtlFreeUnicodeString( &deviceNameUnicodeString );
  844. }
  845. }
  846. //
  847. // For each disk in the system do the following:
  848. // 1. open the device
  849. // 2. get its geometry
  850. // 3. read the MBR
  851. // 4. determine ARC name via disk signature and checksum
  852. // 5. construct ARC name.
  853. // In order to deal with the case of disk dissappearing before we get to this point
  854. // (due to a failed start on one of many disks present in the system) we ask PNP for a list
  855. // of all the currenttly active disks in the system. If the number of disks returned is
  856. // less than the IoGetConfigurationInformation()->DiskCount, then we have legacy disks
  857. // that we need to enumerate in the for loop.
  858. // In the legacy case, the ending condition for the loop is NOT the total disk on the
  859. // system but an arbitrary number of the max total legacy disks expected in the system..
  860. // Additional note: Legacy disks get assigned symbolic links AFTER all pnp enumeration is complete
  861. //
  862. totalDriverDisksFound = max(totalPnpDisksFound,totalDriverDisksFound);
  863. if (useLegacyEnumeration && (totalPnpDisksFound == 0)) {
  864. //
  865. // search up to a maximum arbitrary number of legacy disks
  866. //
  867. totalDriverDisksFound +=20;
  868. }
  869. for (diskNumber = 0;
  870. diskNumber < totalDriverDisksFound;
  871. diskNumber++) {
  872. //
  873. // Construct the NT name for a disk and obtain a reference.
  874. //
  875. if (pDiskNameList && (*pDiskNameList != L'\0')) {
  876. //
  877. // retrieve the first symbolic linkname from the PNP disk list
  878. //
  879. RtlInitUnicodeString(&deviceNameUnicodeString, pDiskNameList);
  880. pDiskNameList = pDiskNameList + (wcslen(pDiskNameList) + 1);
  881. status = IoGetDeviceObjectPointer( &deviceNameUnicodeString,
  882. FILE_READ_ATTRIBUTES,
  883. &fileObject,
  884. &deviceObject );
  885. if (NT_SUCCESS(status)) {
  886. //
  887. // since PNP gave s just asym link we have to retrieve the actual
  888. // disk number through an IOCTL call to the disk stack.
  889. // Create IRP for get device number device control.
  890. //
  891. irp = IoBuildDeviceIoControlRequest( IOCTL_STORAGE_GET_DEVICE_NUMBER,
  892. deviceObject,
  893. NULL,
  894. 0,
  895. &pnpDiskDeviceNumber,
  896. sizeof(STORAGE_DEVICE_NUMBER),
  897. FALSE,
  898. &event,
  899. &ioStatusBlock );
  900. if (!irp) {
  901. ObDereferenceObject( fileObject );
  902. continue;
  903. }
  904. KeInitializeEvent( &event,
  905. NotificationEvent,
  906. FALSE );
  907. status = IoCallDriver( deviceObject,
  908. irp );
  909. if (status == STATUS_PENDING) {
  910. KeWaitForSingleObject( &event,
  911. Executive,
  912. KernelMode,
  913. FALSE,
  914. NULL );
  915. status = ioStatusBlock.Status;
  916. }
  917. if (!NT_SUCCESS( status )) {
  918. ObDereferenceObject( fileObject );
  919. continue;
  920. }
  921. }
  922. if (useLegacyEnumeration && (*pDiskNameList == L'\0') ) {
  923. //
  924. // end of pnp disks
  925. // if there are any legacy disks following we need to update
  926. // the total disk found number to cover the maximum disk number
  927. // a legacy disk could be at. (in a sparse name space)
  928. //
  929. if (pnpDiskDeviceNumber.DeviceNumber == 0xFFFFFFFF) {
  930. pnpDiskDeviceNumber.DeviceNumber = 0;
  931. }
  932. diskNumber = max(diskNumber,pnpDiskDeviceNumber.DeviceNumber);
  933. totalDriverDisksFound = diskNumber + 20;
  934. }
  935. } else {
  936. sprintf( deviceNameBuffer,
  937. "\\Device\\Harddisk%d\\Partition0",
  938. diskNumber );
  939. RtlInitAnsiString( &deviceNameString, deviceNameBuffer );
  940. status = RtlAnsiStringToUnicodeString( &deviceNameUnicodeString,
  941. &deviceNameString,
  942. TRUE );
  943. if (!NT_SUCCESS( status )) {
  944. continue;
  945. }
  946. status = IoGetDeviceObjectPointer( &deviceNameUnicodeString,
  947. FILE_READ_ATTRIBUTES,
  948. &fileObject,
  949. &deviceObject );
  950. RtlFreeUnicodeString( &deviceNameUnicodeString );
  951. //
  952. // set the pnpDiskNumber value so its not used.
  953. //
  954. pnpDiskDeviceNumber.DeviceNumber = 0xFFFFFFFF;
  955. }
  956. if (!NT_SUCCESS( status )) {
  957. continue;
  958. }
  959. //
  960. // Create IRP for get drive geometry device control.
  961. //
  962. irp = IoBuildDeviceIoControlRequest( IOCTL_DISK_GET_DRIVE_GEOMETRY,
  963. deviceObject,
  964. NULL,
  965. 0,
  966. &diskGeometry,
  967. sizeof(DISK_GEOMETRY),
  968. FALSE,
  969. &event,
  970. &ioStatusBlock );
  971. if (!irp) {
  972. ObDereferenceObject( fileObject );
  973. continue;
  974. }
  975. KeInitializeEvent( &event,
  976. NotificationEvent,
  977. FALSE );
  978. status = IoCallDriver( deviceObject,
  979. irp );
  980. if (status == STATUS_PENDING) {
  981. KeWaitForSingleObject( &event,
  982. Executive,
  983. KernelMode,
  984. FALSE,
  985. NULL );
  986. status = ioStatusBlock.Status;
  987. }
  988. if (!NT_SUCCESS( status )) {
  989. ObDereferenceObject( fileObject );
  990. continue;
  991. }
  992. //
  993. // Get partition information for this disk.
  994. //
  995. status = IoReadPartitionTableEx(deviceObject,
  996. &driveLayout );
  997. if (!NT_SUCCESS( status )) {
  998. ObDereferenceObject( fileObject );
  999. continue;
  1000. }
  1001. //
  1002. // Make sure sector size is at least 512 bytes.
  1003. //
  1004. if (diskGeometry.BytesPerSector < 512) {
  1005. diskGeometry.BytesPerSector = 512;
  1006. }
  1007. //
  1008. // Check to see if EZ Drive is out there on this disk. If
  1009. // it is then zero out the signature in the drive layout since
  1010. // this will never be written by anyone AND change to offset to
  1011. // actually read sector 1 rather than 0 cause that's what the
  1012. // loader actually did.
  1013. //
  1014. offset.QuadPart = 0;
  1015. HalExamineMBR( deviceObject,
  1016. diskGeometry.BytesPerSector,
  1017. (ULONG)0x55,
  1018. &tmpPtr );
  1019. if (tmpPtr) {
  1020. offset.QuadPart = diskGeometry.BytesPerSector;
  1021. ExFreePool(tmpPtr);
  1022. }
  1023. //
  1024. // Allocate buffer for sector read and construct the read request.
  1025. //
  1026. buffer = ExAllocatePool( NonPagedPoolCacheAlignedMustS,
  1027. diskGeometry.BytesPerSector );
  1028. if (buffer) {
  1029. irp = IoBuildSynchronousFsdRequest( IRP_MJ_READ,
  1030. deviceObject,
  1031. buffer,
  1032. diskGeometry.BytesPerSector,
  1033. &offset,
  1034. &event,
  1035. &ioStatusBlock );
  1036. if (!irp) {
  1037. ExFreePool(driveLayout);
  1038. ExFreePool(buffer);
  1039. ObDereferenceObject( fileObject );
  1040. continue;
  1041. }
  1042. } else {
  1043. ExFreePool(driveLayout);
  1044. ObDereferenceObject( fileObject );
  1045. continue;
  1046. }
  1047. KeInitializeEvent( &event,
  1048. NotificationEvent,
  1049. FALSE );
  1050. status = IoCallDriver( deviceObject,
  1051. irp );
  1052. if (status == STATUS_PENDING) {
  1053. KeWaitForSingleObject( &event,
  1054. Executive,
  1055. KernelMode,
  1056. FALSE,
  1057. NULL );
  1058. status = ioStatusBlock.Status;
  1059. }
  1060. if (!NT_SUCCESS( status )) {
  1061. ExFreePool(driveLayout);
  1062. ExFreePool(buffer);
  1063. ObDereferenceObject( fileObject );
  1064. continue;
  1065. }
  1066. ObDereferenceObject( fileObject );
  1067. //
  1068. // Calculate MBR sector checksum. Only 512 bytes are used.
  1069. //
  1070. checkSum = 0;
  1071. for (i = 0; i < 128; i++) {
  1072. checkSum += buffer[i];
  1073. }
  1074. //
  1075. // For each ARC disk information record in the loader block
  1076. // match the disk signature and checksum to determine its ARC
  1077. // name and construct the NT ARC names symbolic links.
  1078. //
  1079. for (listEntry = arcInformation->DiskSignatures.Flink;
  1080. listEntry != &arcInformation->DiskSignatures;
  1081. listEntry = listEntry->Flink) {
  1082. //
  1083. // Get next record and compare disk signatures.
  1084. //
  1085. diskBlock = CONTAINING_RECORD( listEntry,
  1086. ARC_DISK_SIGNATURE,
  1087. ListEntry );
  1088. //
  1089. // Compare disk signatures.
  1090. //
  1091. // Or if there is only a single disk drive from
  1092. // both the bios and driver viewpoints then
  1093. // assign an arc name to that drive.
  1094. //
  1095. if ((singleBiosDiskFound &&
  1096. (totalDriverDisksFound == 1) &&
  1097. (driveLayout->PartitionStyle == PARTITION_STYLE_MBR)) ||
  1098. (IopVerifyDiskSignature(driveLayout, diskBlock, &diskSignature) &&
  1099. !(diskBlock->CheckSum + checkSum))) {
  1100. //
  1101. // Create unicode device name for physical disk.
  1102. //
  1103. if (pnpDiskDeviceNumber.DeviceNumber == 0xFFFFFFFF) {
  1104. sprintf( deviceNameBuffer,
  1105. "\\Device\\Harddisk%d\\Partition0",
  1106. diskNumber );
  1107. } else {
  1108. sprintf( deviceNameBuffer,
  1109. "\\Device\\Harddisk%d\\Partition0",
  1110. pnpDiskDeviceNumber.DeviceNumber );
  1111. }
  1112. RtlInitAnsiString( &deviceNameString, deviceNameBuffer );
  1113. status = RtlAnsiStringToUnicodeString( &deviceNameUnicodeString,
  1114. &deviceNameString,
  1115. TRUE );
  1116. if (!NT_SUCCESS( status )) {
  1117. continue;
  1118. }
  1119. //
  1120. // Create unicode ARC name for this partition.
  1121. //
  1122. arcName = diskBlock->ArcName;
  1123. sprintf( arcNameBuffer,
  1124. "\\ArcName\\%s",
  1125. arcName );
  1126. RtlInitAnsiString( &arcNameString, arcNameBuffer );
  1127. status = RtlAnsiStringToUnicodeString( &arcNameUnicodeString,
  1128. &arcNameString,
  1129. TRUE );
  1130. if (!NT_SUCCESS( status )) {
  1131. continue;
  1132. }
  1133. //
  1134. // Create symbolic link between NT device name and ARC name.
  1135. //
  1136. IoCreateSymbolicLink( &arcNameUnicodeString,
  1137. &deviceNameUnicodeString );
  1138. RtlFreeUnicodeString( &arcNameUnicodeString );
  1139. RtlFreeUnicodeString( &deviceNameUnicodeString );
  1140. //
  1141. // Create an ARC name for every partition on this disk.
  1142. //
  1143. for (partitionNumber = 0;
  1144. partitionNumber < driveLayout->PartitionCount;
  1145. partitionNumber++) {
  1146. //
  1147. // Create unicode NT device name.
  1148. //
  1149. if (pnpDiskDeviceNumber.DeviceNumber == 0xFFFFFFFF) {
  1150. sprintf( deviceNameBuffer,
  1151. "\\Device\\Harddisk%d\\Partition%d",
  1152. diskNumber,
  1153. partitionNumber+1 );
  1154. } else {
  1155. sprintf( deviceNameBuffer,
  1156. "\\Device\\Harddisk%d\\Partition%d",
  1157. pnpDiskDeviceNumber.DeviceNumber,
  1158. partitionNumber+1 );
  1159. }
  1160. RtlInitAnsiString( &deviceNameString, deviceNameBuffer );
  1161. status = RtlAnsiStringToUnicodeString( &deviceNameUnicodeString,
  1162. &deviceNameString,
  1163. TRUE );
  1164. if (!NT_SUCCESS( status )) {
  1165. continue;
  1166. }
  1167. //
  1168. // Create unicode ARC name for this partition and
  1169. // check to see if this is the boot disk.
  1170. //
  1171. sprintf( arcNameBuffer,
  1172. "%spartition(%d)",
  1173. arcName,
  1174. partitionNumber+1 );
  1175. RtlInitAnsiString( &arcNameString, arcNameBuffer );
  1176. if (RtlEqualString( &arcNameString,
  1177. &arcBootDeviceString,
  1178. TRUE )) {
  1179. bootDiskFound = TRUE;
  1180. }
  1181. //
  1182. // See if this is the system partition.
  1183. //
  1184. if (RtlEqualString( &arcNameString,
  1185. &arcSystemDeviceString,
  1186. TRUE )) {
  1187. //
  1188. // We've found the system partition--store it away in the registry
  1189. // to later be transferred to a application-friendly location.
  1190. //
  1191. RtlInitAnsiString( &osLoaderPathString, LoaderBlock->NtHalPathName );
  1192. status = RtlAnsiStringToUnicodeString( &osLoaderPathUnicodeString,
  1193. &osLoaderPathString,
  1194. TRUE );
  1195. #if DBG
  1196. if (!NT_SUCCESS( status )) {
  1197. DbgPrint("IopCreateArcNames: couldn't allocate unicode string for OsLoader path - %x\n", status);
  1198. }
  1199. #endif // DBG
  1200. if (NT_SUCCESS( status )) {
  1201. IopStoreSystemPartitionInformation( &deviceNameUnicodeString,
  1202. &osLoaderPathUnicodeString );
  1203. RtlFreeUnicodeString( &osLoaderPathUnicodeString );
  1204. }
  1205. }
  1206. //
  1207. // Add the NT ARC namespace prefix to the ARC name constructed.
  1208. //
  1209. sprintf( arcNameBuffer,
  1210. "\\ArcName\\%spartition(%d)",
  1211. arcName,
  1212. partitionNumber+1 );
  1213. RtlInitAnsiString( &arcNameString, arcNameBuffer );
  1214. status = RtlAnsiStringToUnicodeString( &arcNameUnicodeString,
  1215. &arcNameString,
  1216. TRUE );
  1217. if (!NT_SUCCESS( status )) {
  1218. continue;
  1219. }
  1220. //
  1221. // Create symbolic link between NT device name and ARC name.
  1222. //
  1223. IoCreateSymbolicLink( &arcNameUnicodeString,
  1224. &deviceNameUnicodeString );
  1225. RtlFreeUnicodeString( &arcNameUnicodeString );
  1226. RtlFreeUnicodeString( &deviceNameUnicodeString );
  1227. }
  1228. } else {
  1229. #if DBG
  1230. //
  1231. // Check key indicators to see if this condition may be
  1232. // caused by a viral infection.
  1233. //
  1234. if (diskBlock->Signature == diskSignature &&
  1235. (diskBlock->CheckSum + checkSum) != 0 &&
  1236. diskBlock->ValidPartitionTable) {
  1237. DbgPrint("IopCreateArcNames: Virus or duplicate disk signatures\n");
  1238. }
  1239. #endif
  1240. }
  1241. }
  1242. ExFreePool( driveLayout );
  1243. ExFreePool( buffer );
  1244. }
  1245. if (!bootDiskFound) {
  1246. //
  1247. // Locate the disk block that represents the boot device.
  1248. //
  1249. diskBlock = NULL;
  1250. for (listEntry = arcInformation->DiskSignatures.Flink;
  1251. listEntry != &arcInformation->DiskSignatures;
  1252. listEntry = listEntry->Flink) {
  1253. diskBlock = CONTAINING_RECORD( listEntry,
  1254. ARC_DISK_SIGNATURE,
  1255. ListEntry );
  1256. if (strcmp( diskBlock->ArcName, LoaderBlock->ArcBootDeviceName ) == 0) {
  1257. break;
  1258. }
  1259. diskBlock = NULL;
  1260. }
  1261. if (diskBlock) {
  1262. //
  1263. // This could be a CdRom boot. Search all of the NT CdRoms
  1264. // to locate a checksum match on the diskBlock found. If
  1265. // there is a match, assign the ARC name to the CdRom.
  1266. //
  1267. irp = NULL;
  1268. buffer = ExAllocatePool( NonPagedPoolCacheAlignedMustS,
  1269. 2048 );
  1270. if (buffer) {
  1271. //
  1272. // Construct the NT names for CdRoms and search each one
  1273. // for a checksum match. If found, create the ARC Name
  1274. // symbolic link.
  1275. //
  1276. for (diskNumber = 0; TRUE; diskNumber++) {
  1277. sprintf( deviceNameBuffer,
  1278. "\\Device\\CdRom%d",
  1279. diskNumber );
  1280. RtlInitAnsiString( &deviceNameString, deviceNameBuffer );
  1281. status = RtlAnsiStringToUnicodeString( &deviceNameUnicodeString,
  1282. &deviceNameString,
  1283. TRUE );
  1284. if (NT_SUCCESS( status )) {
  1285. status = IoGetDeviceObjectPointer( &deviceNameUnicodeString,
  1286. FILE_READ_ATTRIBUTES,
  1287. &fileObject,
  1288. &deviceObject );
  1289. if (!NT_SUCCESS( status )) {
  1290. //
  1291. // All CdRoms have been processed.
  1292. //
  1293. RtlFreeUnicodeString( &deviceNameUnicodeString );
  1294. break;
  1295. }
  1296. //
  1297. // Read the block for the checksum calculation.
  1298. //
  1299. offset.QuadPart = 0x8000;
  1300. irp = IoBuildSynchronousFsdRequest( IRP_MJ_READ,
  1301. deviceObject,
  1302. buffer,
  1303. 2048,
  1304. &offset,
  1305. &event,
  1306. &ioStatusBlock );
  1307. checkSum = 0;
  1308. if (irp) {
  1309. KeInitializeEvent( &event,
  1310. NotificationEvent,
  1311. FALSE );
  1312. status = IoCallDriver( deviceObject,
  1313. irp );
  1314. if (status == STATUS_PENDING) {
  1315. KeWaitForSingleObject( &event,
  1316. Executive,
  1317. KernelMode,
  1318. FALSE,
  1319. NULL );
  1320. status = ioStatusBlock.Status;
  1321. }
  1322. if (NT_SUCCESS( status )) {
  1323. //
  1324. // Calculate MBR sector checksum.
  1325. // 2048 bytes are used.
  1326. //
  1327. for (i = 0; i < 2048 / sizeof(ULONG) ; i++) {
  1328. checkSum += buffer[i];
  1329. }
  1330. }
  1331. }
  1332. ObDereferenceObject( fileObject );
  1333. if (!(diskBlock->CheckSum + checkSum)) {
  1334. //
  1335. // This is the boot CdRom. Create the symlink for
  1336. // the ARC name from the loader block.
  1337. //
  1338. sprintf( arcNameBuffer,
  1339. "\\ArcName\\%s",
  1340. LoaderBlock->ArcBootDeviceName );
  1341. RtlInitAnsiString( &arcNameString, arcNameBuffer );
  1342. status = RtlAnsiStringToUnicodeString( &arcNameUnicodeString,
  1343. &arcNameString,
  1344. TRUE );
  1345. if (NT_SUCCESS( status )) {
  1346. IoCreateSymbolicLink( &arcNameUnicodeString,
  1347. &deviceNameUnicodeString );
  1348. RtlFreeUnicodeString( &arcNameUnicodeString );
  1349. }
  1350. RtlFreeUnicodeString( &deviceNameUnicodeString );
  1351. break;
  1352. }
  1353. RtlFreeUnicodeString( &deviceNameUnicodeString );
  1354. }
  1355. }
  1356. ExFreePool(buffer);
  1357. }
  1358. }
  1359. }
  1360. if (diskList) {
  1361. ExFreePool(diskList);
  1362. }
  1363. }
  1364. #ifdef ALLOC_DATA_PRAGMA
  1365. #pragma const_seg("PAGECONST")
  1366. #endif // ALLOC_DATA_PRAGMA
  1367. const GENERIC_MAPPING IopFileMapping = {
  1368. STANDARD_RIGHTS_READ |
  1369. FILE_READ_DATA | FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE,
  1370. STANDARD_RIGHTS_WRITE |
  1371. FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_APPEND_DATA | SYNCHRONIZE,
  1372. STANDARD_RIGHTS_EXECUTE |
  1373. SYNCHRONIZE | FILE_READ_ATTRIBUTES | FILE_EXECUTE,
  1374. FILE_ALL_ACCESS
  1375. };
  1376. #ifdef ALLOC_DATA_PRAGMA
  1377. #pragma const_seg("INITCONST")
  1378. #endif // ALLOC_DATA_PRAGMA
  1379. const GENERIC_MAPPING IopCompletionMapping = {
  1380. STANDARD_RIGHTS_READ |
  1381. IO_COMPLETION_QUERY_STATE,
  1382. STANDARD_RIGHTS_WRITE |
  1383. IO_COMPLETION_MODIFY_STATE,
  1384. STANDARD_RIGHTS_EXECUTE |
  1385. SYNCHRONIZE,
  1386. IO_COMPLETION_ALL_ACCESS
  1387. };
  1388. BOOLEAN
  1389. IopCreateObjectTypes(
  1390. VOID
  1391. )
  1392. /*++
  1393. Routine Description:
  1394. This routine creates the object types used by the I/O system and its
  1395. components. The object types created are:
  1396. Adapter
  1397. Controller
  1398. Device
  1399. Driver
  1400. File
  1401. I/O Completion
  1402. Arguments:
  1403. None.
  1404. Return Value:
  1405. The function value is a BOOLEAN indicating whether or not the object
  1406. types were successfully created.
  1407. --*/
  1408. {
  1409. OBJECT_TYPE_INITIALIZER objectTypeInitializer;
  1410. UNICODE_STRING nameString;
  1411. //
  1412. // Initialize the common fields of the Object Type Initializer record
  1413. //
  1414. RtlZeroMemory( &objectTypeInitializer, sizeof( objectTypeInitializer ) );
  1415. objectTypeInitializer.Length = sizeof( objectTypeInitializer );
  1416. objectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
  1417. objectTypeInitializer.GenericMapping = IopFileMapping;
  1418. objectTypeInitializer.PoolType = NonPagedPool;
  1419. objectTypeInitializer.ValidAccessMask = FILE_ALL_ACCESS;
  1420. objectTypeInitializer.UseDefaultObject = TRUE;
  1421. //
  1422. // Create the object type for adapter objects.
  1423. //
  1424. RtlInitUnicodeString( &nameString, L"Adapter" );
  1425. // objectTypeInitializer.DefaultNonPagedPoolCharge = sizeof( struct _ADAPTER_OBJECT );
  1426. if (!NT_SUCCESS( ObCreateObjectType( &nameString,
  1427. &objectTypeInitializer,
  1428. (PSECURITY_DESCRIPTOR) NULL,
  1429. &IoAdapterObjectType ))) {
  1430. return FALSE;
  1431. }
  1432. #ifdef _PNP_POWER_
  1433. //
  1434. // Create the object type for device helper objects.
  1435. //
  1436. RtlInitUnicodeString( &nameString, L"DeviceHandler" );
  1437. if (!NT_SUCCESS( ObCreateObjectType( &nameString,
  1438. &objectTypeInitializer,
  1439. (PSECURITY_DESCRIPTOR) NULL,
  1440. &IoDeviceHandlerObjectType ))) {
  1441. return FALSE;
  1442. }
  1443. IoDeviceHandlerObjectSize = sizeof(DEVICE_HANDLER_OBJECT);
  1444. #endif
  1445. //
  1446. // Create the object type for controller objects.
  1447. //
  1448. RtlInitUnicodeString( &nameString, L"Controller" );
  1449. objectTypeInitializer.DefaultNonPagedPoolCharge = sizeof( CONTROLLER_OBJECT );
  1450. if (!NT_SUCCESS( ObCreateObjectType( &nameString,
  1451. &objectTypeInitializer,
  1452. (PSECURITY_DESCRIPTOR) NULL,
  1453. &IoControllerObjectType ))) {
  1454. return FALSE;
  1455. }
  1456. //
  1457. // Create the object type for device objects.
  1458. //
  1459. RtlInitUnicodeString( &nameString, L"Device" );
  1460. objectTypeInitializer.DefaultNonPagedPoolCharge = sizeof( DEVICE_OBJECT );
  1461. objectTypeInitializer.ParseProcedure = IopParseDevice;
  1462. objectTypeInitializer.CaseInsensitive = TRUE;
  1463. objectTypeInitializer.DeleteProcedure = IopDeleteDevice;
  1464. objectTypeInitializer.SecurityProcedure = IopGetSetSecurityObject;
  1465. objectTypeInitializer.QueryNameProcedure = (OB_QUERYNAME_METHOD)NULL;
  1466. if (!NT_SUCCESS( ObCreateObjectType( &nameString,
  1467. &objectTypeInitializer,
  1468. (PSECURITY_DESCRIPTOR) NULL,
  1469. &IoDeviceObjectType ))) {
  1470. return FALSE;
  1471. }
  1472. //
  1473. // Create the object type for driver objects.
  1474. //
  1475. RtlInitUnicodeString( &nameString, L"Driver" );
  1476. objectTypeInitializer.DefaultNonPagedPoolCharge = sizeof( DRIVER_OBJECT );
  1477. objectTypeInitializer.ParseProcedure = (OB_PARSE_METHOD) NULL;
  1478. objectTypeInitializer.DeleteProcedure = IopDeleteDriver;
  1479. objectTypeInitializer.SecurityProcedure = (OB_SECURITY_METHOD) NULL;
  1480. objectTypeInitializer.QueryNameProcedure = (OB_QUERYNAME_METHOD)NULL;
  1481. //
  1482. // This allows us to get a list of Driver objects.
  1483. //
  1484. if (IopVerifierOn) {
  1485. objectTypeInitializer.MaintainTypeList = TRUE;
  1486. }
  1487. if (!NT_SUCCESS( ObCreateObjectType( &nameString,
  1488. &objectTypeInitializer,
  1489. (PSECURITY_DESCRIPTOR) NULL,
  1490. &IoDriverObjectType ))) {
  1491. return FALSE;
  1492. }
  1493. //
  1494. // Create the object type for I/O completion objects.
  1495. //
  1496. RtlInitUnicodeString( &nameString, L"IoCompletion" );
  1497. objectTypeInitializer.DefaultNonPagedPoolCharge = sizeof( KQUEUE );
  1498. objectTypeInitializer.InvalidAttributes = OBJ_PERMANENT | OBJ_OPENLINK;
  1499. objectTypeInitializer.GenericMapping = IopCompletionMapping;
  1500. objectTypeInitializer.ValidAccessMask = IO_COMPLETION_ALL_ACCESS;
  1501. objectTypeInitializer.DeleteProcedure = IopDeleteIoCompletion;
  1502. if (!NT_SUCCESS( ObCreateObjectType( &nameString,
  1503. &objectTypeInitializer,
  1504. (PSECURITY_DESCRIPTOR) NULL,
  1505. &IoCompletionObjectType ))) {
  1506. return FALSE;
  1507. }
  1508. //
  1509. // Create the object type for file objects.
  1510. //
  1511. RtlInitUnicodeString( &nameString, L"File" );
  1512. objectTypeInitializer.DefaultPagedPoolCharge = IO_FILE_OBJECT_PAGED_POOL_CHARGE;
  1513. objectTypeInitializer.DefaultNonPagedPoolCharge = IO_FILE_OBJECT_NON_PAGED_POOL_CHARGE +
  1514. sizeof( FILE_OBJECT );
  1515. objectTypeInitializer.InvalidAttributes = OBJ_PERMANENT | OBJ_EXCLUSIVE | OBJ_OPENLINK;
  1516. objectTypeInitializer.GenericMapping = IopFileMapping;
  1517. objectTypeInitializer.ValidAccessMask = FILE_ALL_ACCESS;
  1518. objectTypeInitializer.MaintainHandleCount = TRUE;
  1519. objectTypeInitializer.CloseProcedure = IopCloseFile;
  1520. objectTypeInitializer.DeleteProcedure = IopDeleteFile;
  1521. objectTypeInitializer.ParseProcedure = IopParseFile;
  1522. objectTypeInitializer.SecurityProcedure = IopGetSetSecurityObject;
  1523. objectTypeInitializer.QueryNameProcedure = IopQueryName;
  1524. objectTypeInitializer.UseDefaultObject = FALSE;
  1525. PERFINFO_MUNG_FILE_OBJECT_TYPE_INITIALIZER(objectTypeInitializer);
  1526. if (!NT_SUCCESS( ObCreateObjectType( &nameString,
  1527. &objectTypeInitializer,
  1528. (PSECURITY_DESCRIPTOR) NULL,
  1529. &IoFileObjectType ))) {
  1530. return FALSE;
  1531. }
  1532. PERFINFO_UNMUNG_FILE_OBJECT_TYPE_INITIALIZER(objectTypeInitializer);
  1533. return TRUE;
  1534. }
  1535. BOOLEAN
  1536. IopCreateRootDirectories(
  1537. VOID
  1538. )
  1539. /*++
  1540. Routine Description:
  1541. This routine is invoked to create the object manager directory objects
  1542. to contain the various device and file system driver objects.
  1543. Arguments:
  1544. None.
  1545. Return Value:
  1546. The function value is a BOOLEAN indicating whether or not the directory
  1547. objects were successfully created.
  1548. --*/
  1549. {
  1550. HANDLE handle;
  1551. OBJECT_ATTRIBUTES objectAttributes;
  1552. UNICODE_STRING nameString;
  1553. NTSTATUS status;
  1554. //
  1555. // Create the root directory object for the \Driver directory.
  1556. //
  1557. RtlInitUnicodeString( &nameString, L"\\Driver" );
  1558. InitializeObjectAttributes( &objectAttributes,
  1559. &nameString,
  1560. OBJ_PERMANENT,
  1561. (HANDLE) NULL,
  1562. (PSECURITY_DESCRIPTOR) NULL );
  1563. status = NtCreateDirectoryObject( &handle,
  1564. DIRECTORY_ALL_ACCESS,
  1565. &objectAttributes );
  1566. if (!NT_SUCCESS( status )) {
  1567. return FALSE;
  1568. } else {
  1569. (VOID) NtClose( handle );
  1570. }
  1571. //
  1572. // Create the root directory object for the \FileSystem directory.
  1573. //
  1574. RtlInitUnicodeString( &nameString, L"\\FileSystem" );
  1575. status = NtCreateDirectoryObject( &handle,
  1576. DIRECTORY_ALL_ACCESS,
  1577. &objectAttributes );
  1578. if (!NT_SUCCESS( status )) {
  1579. return FALSE;
  1580. } else {
  1581. (VOID) NtClose( handle );
  1582. }
  1583. //
  1584. // Create the root directory object for the \FileSystem\Filters directory.
  1585. //
  1586. RtlInitUnicodeString( &nameString, L"\\FileSystem\\Filters" );
  1587. status = NtCreateDirectoryObject( &handle,
  1588. DIRECTORY_ALL_ACCESS,
  1589. &objectAttributes );
  1590. if (!NT_SUCCESS( status )) {
  1591. return FALSE;
  1592. } else {
  1593. (VOID) NtClose( handle );
  1594. }
  1595. return TRUE;
  1596. }
  1597. NTSTATUS
  1598. IopInitializeAttributesAndCreateObject(
  1599. IN PUNICODE_STRING ObjectName,
  1600. IN OUT POBJECT_ATTRIBUTES ObjectAttributes,
  1601. OUT PDRIVER_OBJECT *DriverObject
  1602. )
  1603. /*++
  1604. Routine Description:
  1605. This routine is invoked to initialize a set of object attributes and
  1606. to create a driver object.
  1607. Arguments:
  1608. ObjectName - Supplies the name of the driver object.
  1609. ObjectAttributes - Supplies a pointer to the object attributes structure
  1610. to be initialized.
  1611. DriverObject - Supplies a variable to receive a pointer to the resultant
  1612. created driver object.
  1613. Return Value:
  1614. The function value is the final status of the operation.
  1615. --*/
  1616. {
  1617. NTSTATUS status;
  1618. //
  1619. // Simply initialize the object attributes and create the driver object.
  1620. //
  1621. InitializeObjectAttributes( ObjectAttributes,
  1622. ObjectName,
  1623. OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
  1624. (HANDLE) NULL,
  1625. (PSECURITY_DESCRIPTOR) NULL );
  1626. status = ObCreateObject( KeGetPreviousMode(),
  1627. IoDriverObjectType,
  1628. ObjectAttributes,
  1629. KernelMode,
  1630. (PVOID) NULL,
  1631. (ULONG) (sizeof( DRIVER_OBJECT ) + sizeof ( DRIVER_EXTENSION )),
  1632. 0,
  1633. 0,
  1634. (PVOID *)DriverObject );
  1635. return status;
  1636. }
  1637. NTSTATUS
  1638. IopInitializeBuiltinDriver(
  1639. IN PUNICODE_STRING DriverName,
  1640. IN PUNICODE_STRING RegistryPath,
  1641. IN PDRIVER_INITIALIZE DriverInitializeRoutine,
  1642. IN PKLDR_DATA_TABLE_ENTRY DriverEntry,
  1643. IN BOOLEAN IsFilter,
  1644. IN PDRIVER_OBJECT *Result
  1645. )
  1646. /*++
  1647. Routine Description:
  1648. This routine is invoked to initialize a built-in driver.
  1649. Arguments:
  1650. DriverName - Specifies the name to be used in creating the driver object.
  1651. RegistryPath - Specifies the path to be used by the driver to get to
  1652. the registry.
  1653. DriverInitializeRoutine - Specifies the initialization entry point of
  1654. the built-in driver.
  1655. DriverEntry - Specifies the driver data table entry to determine if the
  1656. driver is a wdm driver.
  1657. Return Value:
  1658. The function returns a pointer to a DRIVER_OBJECT if the built-in
  1659. driver successfully initialized. Otherwise, a value of NULL is returned.
  1660. --*/
  1661. {
  1662. HANDLE handle;
  1663. PDRIVER_OBJECT driverObject;
  1664. PDRIVER_OBJECT tmpDriverObject;
  1665. OBJECT_ATTRIBUTES objectAttributes;
  1666. PWSTR buffer;
  1667. NTSTATUS status;
  1668. HANDLE serviceHandle;
  1669. PWSTR pserviceName;
  1670. USHORT serviceNameLength;
  1671. PDRIVER_EXTENSION driverExtension;
  1672. PIMAGE_NT_HEADERS ntHeaders;
  1673. PVOID imageBase;
  1674. #if DBG
  1675. LARGE_INTEGER stime, etime;
  1676. ULONG dtime;
  1677. #endif
  1678. PLIST_ENTRY entry;
  1679. PKLDR_DATA_TABLE_ENTRY DataTableEntry;
  1680. *Result = NULL;
  1681. //
  1682. // Log the file name
  1683. //
  1684. HeadlessKernelAddLogEntry(HEADLESS_LOG_LOADING_FILENAME, DriverName);
  1685. //
  1686. // Begin by creating the driver object.
  1687. //
  1688. status = IopInitializeAttributesAndCreateObject( DriverName,
  1689. &objectAttributes,
  1690. &driverObject );
  1691. if (!NT_SUCCESS( status )) {
  1692. HeadlessKernelAddLogEntry(HEADLESS_LOG_LOAD_FAILED, NULL);
  1693. return status;
  1694. }
  1695. //
  1696. // Initialize the driver object.
  1697. //
  1698. InitializeDriverObject( driverObject );
  1699. driverObject->DriverInit = DriverInitializeRoutine;
  1700. //
  1701. // Insert the driver object into the object table.
  1702. //
  1703. status = ObInsertObject( driverObject,
  1704. NULL,
  1705. FILE_READ_DATA,
  1706. 0,
  1707. (PVOID *) NULL,
  1708. &handle );
  1709. if (!NT_SUCCESS( status )) {
  1710. HeadlessKernelAddLogEntry(HEADLESS_LOG_LOAD_FAILED, NULL);
  1711. return status;
  1712. }
  1713. //
  1714. // Reference the handle and obtain a pointer to the driver object so that
  1715. // the handle can be deleted without the object going away.
  1716. //
  1717. status = ObReferenceObjectByHandle( handle,
  1718. 0,
  1719. IoDriverObjectType,
  1720. KernelMode,
  1721. (PVOID *) &tmpDriverObject,
  1722. (POBJECT_HANDLE_INFORMATION) NULL );
  1723. ASSERT(status == STATUS_SUCCESS);
  1724. //
  1725. // Fill in the DriverSection so the image will be automatically unloaded on
  1726. // failures. We should use the entry from the PsModuleList.
  1727. //
  1728. entry = PsLoadedModuleList.Flink;
  1729. while (entry != &PsLoadedModuleList && DriverEntry) {
  1730. DataTableEntry = CONTAINING_RECORD(entry,
  1731. KLDR_DATA_TABLE_ENTRY,
  1732. InLoadOrderLinks);
  1733. if (RtlEqualString((PSTRING)&DriverEntry->BaseDllName,
  1734. (PSTRING)&DataTableEntry->BaseDllName,
  1735. TRUE
  1736. )) {
  1737. driverObject->DriverSection = DataTableEntry;
  1738. break;
  1739. }
  1740. entry = entry->Flink;
  1741. }
  1742. //
  1743. // The boot process takes a while loading drivers. Indicate that
  1744. // progress is being made.
  1745. //
  1746. InbvIndicateProgress();
  1747. //
  1748. // Get start and sice for the DriverObject.
  1749. //
  1750. if (DriverEntry) {
  1751. imageBase = DriverEntry->DllBase;
  1752. ntHeaders = RtlImageNtHeader(imageBase);
  1753. driverObject->DriverStart = imageBase;
  1754. driverObject->DriverSize = ntHeaders->OptionalHeader.SizeOfImage;
  1755. if (!(ntHeaders->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_WDM_DRIVER)) {
  1756. driverObject->Flags |= DRVO_LEGACY_DRIVER;
  1757. }
  1758. } else {
  1759. ntHeaders = NULL;
  1760. driverObject->Flags |= DRVO_LEGACY_DRIVER;
  1761. }
  1762. //
  1763. // Save the name of the driver so that it can be easily located by functions
  1764. // such as error logging.
  1765. //
  1766. buffer = ExAllocatePool( PagedPool, DriverName->MaximumLength + 2 );
  1767. if (buffer) {
  1768. driverObject->DriverName.Buffer = buffer;
  1769. driverObject->DriverName.MaximumLength = DriverName->MaximumLength;
  1770. driverObject->DriverName.Length = DriverName->Length;
  1771. RtlCopyMemory( driverObject->DriverName.Buffer,
  1772. DriverName->Buffer,
  1773. DriverName->MaximumLength );
  1774. buffer[DriverName->Length >> 1] = (WCHAR) '\0';
  1775. }
  1776. //
  1777. // Save the name of the service key so that it can be easily located by PnP
  1778. // mamager.
  1779. //
  1780. driverExtension = driverObject->DriverExtension;
  1781. if (RegistryPath && RegistryPath->Length != 0) {
  1782. pserviceName = RegistryPath->Buffer + RegistryPath->Length / sizeof (WCHAR) - 1;
  1783. if (*pserviceName == OBJ_NAME_PATH_SEPARATOR) {
  1784. pserviceName--;
  1785. }
  1786. serviceNameLength = 0;
  1787. while (pserviceName != RegistryPath->Buffer) {
  1788. if (*pserviceName == OBJ_NAME_PATH_SEPARATOR) {
  1789. pserviceName++;
  1790. break;
  1791. } else {
  1792. serviceNameLength += sizeof(WCHAR);
  1793. pserviceName--;
  1794. }
  1795. }
  1796. if (pserviceName == RegistryPath->Buffer) {
  1797. serviceNameLength += sizeof(WCHAR);
  1798. }
  1799. buffer = ExAllocatePool( NonPagedPool, serviceNameLength + sizeof(UNICODE_NULL) );
  1800. if (buffer) {
  1801. driverExtension->ServiceKeyName.Buffer = buffer;
  1802. driverExtension->ServiceKeyName.MaximumLength = serviceNameLength + sizeof(UNICODE_NULL);
  1803. driverExtension->ServiceKeyName.Length = serviceNameLength;
  1804. RtlCopyMemory( driverExtension->ServiceKeyName.Buffer,
  1805. pserviceName,
  1806. serviceNameLength );
  1807. buffer[driverExtension->ServiceKeyName.Length >> 1] = UNICODE_NULL;
  1808. } else {
  1809. status = STATUS_INSUFFICIENT_RESOURCES;
  1810. driverExtension->ServiceKeyName.Buffer = NULL;
  1811. driverExtension->ServiceKeyName.Length = 0;
  1812. goto exit;
  1813. }
  1814. //
  1815. // Prepare driver initialization
  1816. //
  1817. status = IopOpenRegistryKeyEx( &serviceHandle,
  1818. NULL,
  1819. RegistryPath,
  1820. KEY_ALL_ACCESS
  1821. );
  1822. if (NT_SUCCESS(status)) {
  1823. status = IopPrepareDriverLoading(&driverExtension->ServiceKeyName,
  1824. serviceHandle,
  1825. imageBase,
  1826. IsFilter);
  1827. NtClose(serviceHandle);
  1828. if (!NT_SUCCESS(status)) {
  1829. goto exit;
  1830. }
  1831. } else {
  1832. goto exit;
  1833. }
  1834. } else {
  1835. driverExtension->ServiceKeyName.Buffer = NULL;
  1836. driverExtension->ServiceKeyName.MaximumLength = 0;
  1837. driverExtension->ServiceKeyName.Length = 0;
  1838. }
  1839. //
  1840. // Load the Registry information in the appropriate fields of the device
  1841. // object.
  1842. //
  1843. driverObject->HardwareDatabase = &CmRegistryMachineHardwareDescriptionSystemName;
  1844. #if DBG
  1845. KeQuerySystemTime (&stime);
  1846. #endif
  1847. //
  1848. // Now invoke the driver's initialization routine to initialize itself.
  1849. //
  1850. status = driverObject->DriverInit( driverObject, RegistryPath );
  1851. #if DBG
  1852. //
  1853. // If DriverInit took longer than 5 seconds or the driver did not load,
  1854. // print a message.
  1855. //
  1856. KeQuerySystemTime (&etime);
  1857. dtime = (ULONG) ((etime.QuadPart - stime.QuadPart) / 1000000);
  1858. if (dtime > 50 || !NT_SUCCESS( status )) {
  1859. if (dtime < 10) {
  1860. DbgPrint( "IOINIT: Built-in driver %wZ failed to initialize - %lX\n",
  1861. DriverName, status );
  1862. } else {
  1863. DbgPrint( "IOINIT: Built-in driver %wZ took %d.%ds to ",
  1864. DriverName, dtime/10, dtime%10 );
  1865. if (NT_SUCCESS( status )) {
  1866. DbgPrint ("initialize\n");
  1867. } else {
  1868. DbgPrint ("fail initialization - %lX\n", status);
  1869. }
  1870. }
  1871. }
  1872. #endif
  1873. exit:
  1874. NtClose( handle );
  1875. if (NT_SUCCESS( status )) {
  1876. IopReadyDeviceObjects( driverObject );
  1877. HeadlessKernelAddLogEntry(HEADLESS_LOG_LOAD_SUCCESSFUL, NULL);
  1878. *Result = driverObject;
  1879. return status;
  1880. } else {
  1881. if (status != STATUS_PLUGPLAY_NO_DEVICE) {
  1882. //
  1883. // if STATUS_PLUGPLAY_NO_DEVICE, the driver was disable by hardware profile.
  1884. //
  1885. IopDriverLoadingFailed(NULL, &driverObject->DriverExtension->ServiceKeyName);
  1886. }
  1887. HeadlessKernelAddLogEntry(HEADLESS_LOG_LOAD_FAILED, NULL);
  1888. ObMakeTemporaryObject(driverObject);
  1889. ObDereferenceObject (driverObject);
  1890. return status;
  1891. }
  1892. }
  1893. BOOLEAN
  1894. IopMarkBootPartition(
  1895. IN PLOADER_PARAMETER_BLOCK LoaderBlock
  1896. )
  1897. /*++
  1898. Routine Description:
  1899. This routine is invoked to locate and mark the boot partition device object
  1900. as a boot device so that subsequent operations can fail more cleanly and
  1901. with a better explanation of why the system failed to boot and run properly.
  1902. Arguments:
  1903. LoaderBlock - Supplies a pointer to the loader parameter block created
  1904. by the OS Loader during the boot process. This structure contains
  1905. the various system partition and boot device names and paths.
  1906. Return Value:
  1907. The function value is TRUE if everything worked, otherwise FALSE.
  1908. Notes:
  1909. If the boot partition device object cannot be found, then the system will
  1910. bugcheck.
  1911. --*/
  1912. {
  1913. OBJECT_ATTRIBUTES objectAttributes;
  1914. STRING deviceNameString;
  1915. UCHAR deviceNameBuffer[256];
  1916. UNICODE_STRING deviceNameUnicodeString;
  1917. NTSTATUS status;
  1918. HANDLE fileHandle;
  1919. IO_STATUS_BLOCK ioStatus;
  1920. PFILE_OBJECT fileObject;
  1921. CHAR ArcNameFmt[12];
  1922. ArcNameFmt[0] = '\\';
  1923. ArcNameFmt[1] = 'A';
  1924. ArcNameFmt[2] = 'r';
  1925. ArcNameFmt[3] = 'c';
  1926. ArcNameFmt[4] = 'N';
  1927. ArcNameFmt[5] = 'a';
  1928. ArcNameFmt[6] = 'm';
  1929. ArcNameFmt[7] = 'e';
  1930. ArcNameFmt[8] = '\\';
  1931. ArcNameFmt[9] = '%';
  1932. ArcNameFmt[10] = 's';
  1933. ArcNameFmt[11] = '\0';
  1934. //
  1935. // Open the ARC boot device object. The boot device driver should have
  1936. // created the object.
  1937. //
  1938. sprintf( deviceNameBuffer,
  1939. ArcNameFmt,
  1940. LoaderBlock->ArcBootDeviceName );
  1941. RtlInitAnsiString( &deviceNameString, deviceNameBuffer );
  1942. status = RtlAnsiStringToUnicodeString( &deviceNameUnicodeString,
  1943. &deviceNameString,
  1944. TRUE );
  1945. if (!NT_SUCCESS( status )) {
  1946. return FALSE;
  1947. }
  1948. InitializeObjectAttributes( &objectAttributes,
  1949. &deviceNameUnicodeString,
  1950. OBJ_CASE_INSENSITIVE,
  1951. NULL,
  1952. NULL );
  1953. status = ZwOpenFile( &fileHandle,
  1954. FILE_READ_ATTRIBUTES,
  1955. &objectAttributes,
  1956. &ioStatus,
  1957. 0,
  1958. FILE_NON_DIRECTORY_FILE );
  1959. if (!NT_SUCCESS( status )) {
  1960. KeBugCheckEx( INACCESSIBLE_BOOT_DEVICE,
  1961. (ULONG_PTR) &deviceNameUnicodeString,
  1962. status,
  1963. 0,
  1964. 0 );
  1965. }
  1966. //
  1967. // Convert the file handle into a pointer to the device object itself.
  1968. //
  1969. status = ObReferenceObjectByHandle( fileHandle,
  1970. 0,
  1971. IoFileObjectType,
  1972. KernelMode,
  1973. (PVOID *) &fileObject,
  1974. NULL );
  1975. if (!NT_SUCCESS( status )) {
  1976. RtlFreeUnicodeString( &deviceNameUnicodeString );
  1977. return FALSE;
  1978. }
  1979. //
  1980. // Mark the device object represented by the file object.
  1981. //
  1982. fileObject->DeviceObject->Flags |= DO_SYSTEM_BOOT_PARTITION;
  1983. //
  1984. // Save away the characteristics of boot device object for later
  1985. // use in WinPE mode
  1986. //
  1987. if (InitIsWinPEMode) {
  1988. if (fileObject->DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) {
  1989. InitWinPEModeType |= INIT_WINPEMODE_REMOVABLE_MEDIA;
  1990. }
  1991. if (fileObject->DeviceObject->Characteristics & FILE_READ_ONLY_DEVICE) {
  1992. InitWinPEModeType |= INIT_WINPEMODE_READONLY_MEDIA;
  1993. }
  1994. }
  1995. //
  1996. // Reference the device object and store the reference.
  1997. //
  1998. ObReferenceObject(fileObject->DeviceObject);
  1999. IopErrorLogObject = fileObject->DeviceObject;
  2000. RtlFreeUnicodeString( &deviceNameUnicodeString );
  2001. //
  2002. // Finally, close the handle and dereference the file object.
  2003. //
  2004. NtClose( fileHandle );
  2005. ObDereferenceObject( fileObject );
  2006. return TRUE;
  2007. }
  2008. BOOLEAN
  2009. IopReassignSystemRoot(
  2010. IN PLOADER_PARAMETER_BLOCK LoaderBlock,
  2011. OUT PSTRING NtDeviceName
  2012. )
  2013. /*++
  2014. Routine Description:
  2015. This routine is invoked to reassign \SystemRoot from being an ARC path
  2016. name to its NT path name equivalent. This is done by looking up the
  2017. ARC device name as a symbolic link and determining which NT device object
  2018. is referred to by it. The link is then replaced with the new name.
  2019. Arguments:
  2020. LoaderBlock - Supplies a pointer to the loader parameter block created
  2021. by the OS Loader during the boot process. This structure contains
  2022. the various system partition and boot device names and paths.
  2023. NtDeviceName - Specifies a pointer to a STRING to receive the NT name of
  2024. the device from which the system was booted.
  2025. Return Value:
  2026. The function value is a BOOLEAN indicating whether or not the ARC name
  2027. was resolved to an NT name.
  2028. --*/
  2029. {
  2030. OBJECT_ATTRIBUTES objectAttributes;
  2031. NTSTATUS status;
  2032. UCHAR deviceNameBuffer[256];
  2033. WCHAR arcNameUnicodeBuffer[64];
  2034. UCHAR arcNameStringBuffer[256];
  2035. STRING deviceNameString;
  2036. STRING arcNameString;
  2037. STRING linkString;
  2038. UNICODE_STRING linkUnicodeString;
  2039. UNICODE_STRING deviceNameUnicodeString;
  2040. UNICODE_STRING arcNameUnicodeString;
  2041. HANDLE linkHandle;
  2042. #if DBG
  2043. UCHAR debugBuffer[256];
  2044. STRING debugString;
  2045. UNICODE_STRING debugUnicodeString;
  2046. #endif
  2047. CHAR ArcNameFmt[12];
  2048. ArcNameFmt[0] = '\\';
  2049. ArcNameFmt[1] = 'A';
  2050. ArcNameFmt[2] = 'r';
  2051. ArcNameFmt[3] = 'c';
  2052. ArcNameFmt[4] = 'N';
  2053. ArcNameFmt[5] = 'a';
  2054. ArcNameFmt[6] = 'm';
  2055. ArcNameFmt[7] = 'e';
  2056. ArcNameFmt[8] = '\\';
  2057. ArcNameFmt[9] = '%';
  2058. ArcNameFmt[10] = 's';
  2059. ArcNameFmt[11] = '\0';
  2060. //
  2061. // Open the ARC boot device symbolic link object. The boot device
  2062. // driver should have created the object.
  2063. //
  2064. sprintf( deviceNameBuffer,
  2065. ArcNameFmt,
  2066. LoaderBlock->ArcBootDeviceName );
  2067. RtlInitAnsiString( &deviceNameString, deviceNameBuffer );
  2068. status = RtlAnsiStringToUnicodeString( &deviceNameUnicodeString,
  2069. &deviceNameString,
  2070. TRUE );
  2071. if (!NT_SUCCESS( status )) {
  2072. return FALSE;
  2073. }
  2074. InitializeObjectAttributes( &objectAttributes,
  2075. &deviceNameUnicodeString,
  2076. OBJ_CASE_INSENSITIVE,
  2077. NULL,
  2078. NULL );
  2079. status = NtOpenSymbolicLinkObject( &linkHandle,
  2080. SYMBOLIC_LINK_ALL_ACCESS,
  2081. &objectAttributes );
  2082. if (!NT_SUCCESS( status )) {
  2083. #if DBG
  2084. sprintf( debugBuffer, "IOINIT: unable to resolve %s, Status == %X\n",
  2085. deviceNameBuffer,
  2086. status );
  2087. RtlInitAnsiString( &debugString, debugBuffer );
  2088. status = RtlAnsiStringToUnicodeString( &debugUnicodeString,
  2089. &debugString,
  2090. TRUE );
  2091. if (NT_SUCCESS( status )) {
  2092. ZwDisplayString( &debugUnicodeString );
  2093. RtlFreeUnicodeString( &debugUnicodeString );
  2094. }
  2095. #endif // DBG
  2096. RtlFreeUnicodeString( &deviceNameUnicodeString );
  2097. return FALSE;
  2098. }
  2099. //
  2100. // Get handle to \SystemRoot symbolic link.
  2101. //
  2102. arcNameUnicodeString.Buffer = arcNameUnicodeBuffer;
  2103. arcNameUnicodeString.Length = 0;
  2104. arcNameUnicodeString.MaximumLength = sizeof( arcNameUnicodeBuffer );
  2105. status = NtQuerySymbolicLinkObject( linkHandle,
  2106. &arcNameUnicodeString,
  2107. NULL );
  2108. if (!NT_SUCCESS( status )) {
  2109. return FALSE;
  2110. }
  2111. arcNameString.Buffer = arcNameStringBuffer;
  2112. arcNameString.Length = 0;
  2113. arcNameString.MaximumLength = sizeof( arcNameStringBuffer );
  2114. status = RtlUnicodeStringToAnsiString( &arcNameString,
  2115. &arcNameUnicodeString,
  2116. FALSE );
  2117. arcNameStringBuffer[arcNameString.Length] = '\0';
  2118. NtClose( linkHandle );
  2119. RtlFreeUnicodeString( &deviceNameUnicodeString );
  2120. RtlInitAnsiString( &linkString, INIT_SYSTEMROOT_LINKNAME );
  2121. status = RtlAnsiStringToUnicodeString( &linkUnicodeString,
  2122. &linkString,
  2123. TRUE);
  2124. if (!NT_SUCCESS( status )) {
  2125. return FALSE;
  2126. }
  2127. InitializeObjectAttributes( &objectAttributes,
  2128. &linkUnicodeString,
  2129. OBJ_CASE_INSENSITIVE,
  2130. NULL,
  2131. NULL );
  2132. status = NtOpenSymbolicLinkObject( &linkHandle,
  2133. SYMBOLIC_LINK_ALL_ACCESS,
  2134. &objectAttributes );
  2135. if (!NT_SUCCESS( status )) {
  2136. return FALSE;
  2137. }
  2138. NtMakeTemporaryObject( linkHandle );
  2139. NtClose( linkHandle );
  2140. sprintf( deviceNameBuffer,
  2141. "%Z%s",
  2142. &arcNameString,
  2143. LoaderBlock->NtBootPathName );
  2144. //
  2145. // Get NT device name for \SystemRoot assignment.
  2146. //
  2147. RtlCopyString( NtDeviceName, &arcNameString );
  2148. deviceNameBuffer[strlen(deviceNameBuffer)-1] = '\0';
  2149. RtlInitAnsiString(&deviceNameString, deviceNameBuffer);
  2150. InitializeObjectAttributes( &objectAttributes,
  2151. &linkUnicodeString,
  2152. OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
  2153. NULL,
  2154. NULL );
  2155. status = RtlAnsiStringToUnicodeString( &arcNameUnicodeString,
  2156. &deviceNameString,
  2157. TRUE);
  2158. if (!NT_SUCCESS( status )) {
  2159. return FALSE;
  2160. }
  2161. status = NtCreateSymbolicLinkObject( &linkHandle,
  2162. SYMBOLIC_LINK_ALL_ACCESS,
  2163. &objectAttributes,
  2164. &arcNameUnicodeString );
  2165. RtlFreeUnicodeString( &arcNameUnicodeString );
  2166. RtlFreeUnicodeString( &linkUnicodeString );
  2167. NtClose( linkHandle );
  2168. #if DBG
  2169. if (NT_SUCCESS( status )) {
  2170. sprintf( debugBuffer,
  2171. "INIT: Reassigned %s => %s\n",
  2172. INIT_SYSTEMROOT_LINKNAME,
  2173. deviceNameBuffer );
  2174. } else {
  2175. sprintf( debugBuffer,
  2176. "INIT: unable to create %s => %s, Status == %X\n",
  2177. INIT_SYSTEMROOT_LINKNAME,
  2178. deviceNameBuffer,
  2179. status );
  2180. }
  2181. RtlInitAnsiString( &debugString, debugBuffer );
  2182. status = RtlAnsiStringToUnicodeString( &debugUnicodeString,
  2183. &debugString,
  2184. TRUE );
  2185. if (NT_SUCCESS( status )) {
  2186. ZwDisplayString( &debugUnicodeString );
  2187. RtlFreeUnicodeString( &debugUnicodeString );
  2188. }
  2189. #endif // DBG
  2190. return TRUE;
  2191. }
  2192. VOID
  2193. IopStoreSystemPartitionInformation(
  2194. IN PUNICODE_STRING NtSystemPartitionDeviceName,
  2195. IN OUT PUNICODE_STRING OsLoaderPathName
  2196. )
  2197. /*++
  2198. Routine Description:
  2199. This routine writes two values to the registry (under HKLM\SYSTEM\Setup)--one
  2200. containing the NT device name of the system partition and the other containing
  2201. the path to the OS loader. These values will later be migrated into a
  2202. Win95-compatible registry location (NT path converted to DOS path), so that
  2203. installation programs (including our own setup) have a rock-solid way of knowing
  2204. what the system partition is, on both ARC and x86.
  2205. ERRORS ENCOUNTERED IN THIS ROUTINE ARE NOT CONSIDERED FATAL.
  2206. Arguments:
  2207. NtSystemPartitionDeviceName - supplies the NT device name of the system partition.
  2208. This is the \Device\Harddisk<n>\Partition<m> name, which used to be the actual
  2209. device name, but now is a symbolic link to a name of the form \Device\Volume<x>.
  2210. We open up this symbolic link, and retrieve the name that it points to. The
  2211. target name is the one we store away in the registry.
  2212. OsLoaderPathName - supplies the path (on the partition specified in the 1st parameter)
  2213. where the OS loader is located. Upon return, this path will have had its trailing
  2214. backslash removed (if present, and path isn't root).
  2215. Return Value:
  2216. None.
  2217. --*/
  2218. {
  2219. NTSTATUS status;
  2220. HANDLE linkHandle;
  2221. OBJECT_ATTRIBUTES objectAttributes;
  2222. HANDLE systemHandle, setupHandle;
  2223. UNICODE_STRING nameString, volumeNameString;
  2224. WCHAR voumeNameStringBuffer[256];
  2225. //
  2226. // Declare a unicode buffer big enough to contain the longest string we'll be using.
  2227. // (ANSI string in 'sizeof()' below on purpose--we want the number of chars here.)
  2228. //
  2229. WCHAR nameBuffer[sizeof("SystemPartition")];
  2230. //
  2231. // Both UNICODE_STRING buffers should be NULL-terminated.
  2232. //
  2233. ASSERT( NtSystemPartitionDeviceName->MaximumLength >= NtSystemPartitionDeviceName->Length + sizeof(WCHAR) );
  2234. ASSERT( NtSystemPartitionDeviceName->Buffer[NtSystemPartitionDeviceName->Length / sizeof(WCHAR)] == L'\0' );
  2235. ASSERT( OsLoaderPathName->MaximumLength >= OsLoaderPathName->Length + sizeof(WCHAR) );
  2236. ASSERT( OsLoaderPathName->Buffer[OsLoaderPathName->Length / sizeof(WCHAR)] == L'\0' );
  2237. //
  2238. // Open the NtSystemPartitionDeviceName symbolic link, and find out the volume device
  2239. // it points to.
  2240. //
  2241. InitializeObjectAttributes(&objectAttributes,
  2242. NtSystemPartitionDeviceName,
  2243. OBJ_CASE_INSENSITIVE,
  2244. NULL,
  2245. NULL
  2246. );
  2247. status = NtOpenSymbolicLinkObject(&linkHandle,
  2248. SYMBOLIC_LINK_QUERY,
  2249. &objectAttributes
  2250. );
  2251. if (!NT_SUCCESS(status)) {
  2252. #if DBG
  2253. DbgPrint("IopStoreSystemPartitionInformation: couldn't open symbolic link %wZ - %x\n",
  2254. NtSystemPartitionDeviceName,
  2255. status
  2256. );
  2257. #endif // DBG
  2258. return;
  2259. }
  2260. volumeNameString.Buffer = voumeNameStringBuffer;
  2261. volumeNameString.Length = 0;
  2262. //
  2263. // Leave room at the end of the buffer for a terminating null, in case we need to add one.
  2264. //
  2265. volumeNameString.MaximumLength = sizeof(voumeNameStringBuffer) - sizeof(WCHAR);
  2266. status = NtQuerySymbolicLinkObject(linkHandle,
  2267. &volumeNameString,
  2268. NULL
  2269. );
  2270. //
  2271. // We don't need the handle to the symbolic link any longer.
  2272. //
  2273. NtClose(linkHandle);
  2274. if (!NT_SUCCESS(status)) {
  2275. #if DBG
  2276. DbgPrint("IopStoreSystemPartitionInformation: couldn't query symbolic link %wZ - %x\n",
  2277. NtSystemPartitionDeviceName,
  2278. status
  2279. );
  2280. #endif // DBG
  2281. return;
  2282. }
  2283. //
  2284. // Make sure the volume name string is null-terminated.
  2285. //
  2286. volumeNameString.Buffer[volumeNameString.Length / sizeof(WCHAR)] = L'\0';
  2287. //
  2288. // Open HKLM\SYSTEM key.
  2289. //
  2290. status = IopOpenRegistryKeyEx( &systemHandle,
  2291. NULL,
  2292. &CmRegistryMachineSystemName,
  2293. KEY_ALL_ACCESS
  2294. );
  2295. if (!NT_SUCCESS(status)) {
  2296. #if DBG
  2297. DbgPrint("IopStoreSystemPartitionInformation: couldn't open \\REGISTRY\\MACHINE\\SYSTEM - %x\n", status);
  2298. #endif // DBG
  2299. return;
  2300. }
  2301. //
  2302. // Now open/create the setup subkey.
  2303. //
  2304. ASSERT( sizeof(L"Setup") <= sizeof(nameBuffer) );
  2305. nameBuffer[0] = L'S';
  2306. nameBuffer[1] = L'e';
  2307. nameBuffer[2] = L't';
  2308. nameBuffer[3] = L'u';
  2309. nameBuffer[4] = L'p';
  2310. nameBuffer[5] = L'\0';
  2311. nameString.MaximumLength = sizeof(L"Setup");
  2312. nameString.Length = sizeof(L"Setup") - sizeof(WCHAR);
  2313. nameString.Buffer = nameBuffer;
  2314. status = IopCreateRegistryKeyEx( &setupHandle,
  2315. systemHandle,
  2316. &nameString,
  2317. KEY_ALL_ACCESS,
  2318. REG_OPTION_NON_VOLATILE,
  2319. NULL
  2320. );
  2321. NtClose(systemHandle); // Don't need the handle to the HKLM\System key anymore.
  2322. if (!NT_SUCCESS(status)) {
  2323. #if DBG
  2324. DbgPrint("IopStoreSystemPartitionInformation: couldn't open Setup subkey - %x\n", status);
  2325. #endif // DBG
  2326. return;
  2327. }
  2328. ASSERT( sizeof(L"SystemPartition") <= sizeof(nameBuffer) );
  2329. nameBuffer[0] = L'S';
  2330. nameBuffer[1] = L'y';
  2331. nameBuffer[2] = L's';
  2332. nameBuffer[3] = L't';
  2333. nameBuffer[4] = L'e';
  2334. nameBuffer[5] = L'm';
  2335. nameBuffer[6] = L'P';
  2336. nameBuffer[7] = L'a';
  2337. nameBuffer[8] = L'r';
  2338. nameBuffer[9] = L't';
  2339. nameBuffer[10] = L'i';
  2340. nameBuffer[11] = L't';
  2341. nameBuffer[12] = L'i';
  2342. nameBuffer[13] = L'o';
  2343. nameBuffer[14] = L'n';
  2344. nameBuffer[15] = L'\0';
  2345. nameString.MaximumLength = sizeof(L"SystemPartition");
  2346. nameString.Length = sizeof(L"SystemPartition") - sizeof(WCHAR);
  2347. status = NtSetValueKey(setupHandle,
  2348. &nameString,
  2349. TITLE_INDEX_VALUE,
  2350. REG_SZ,
  2351. volumeNameString.Buffer,
  2352. volumeNameString.Length + sizeof(WCHAR)
  2353. );
  2354. #if DBG
  2355. if (!NT_SUCCESS(status)) {
  2356. DbgPrint("IopStoreSystemPartitionInformation: couldn't write SystemPartition value - %x\n", status);
  2357. }
  2358. #endif // DBG
  2359. ASSERT( sizeof(L"OsLoaderPath") <= sizeof(nameBuffer) );
  2360. nameBuffer[0] = L'O';
  2361. nameBuffer[1] = L's';
  2362. nameBuffer[2] = L'L';
  2363. nameBuffer[3] = L'o';
  2364. nameBuffer[4] = L'a';
  2365. nameBuffer[5] = L'd';
  2366. nameBuffer[6] = L'e';
  2367. nameBuffer[7] = L'r';
  2368. nameBuffer[8] = L'P';
  2369. nameBuffer[9] = L'a';
  2370. nameBuffer[10] = L't';
  2371. nameBuffer[11] = L'h';
  2372. nameBuffer[12] = L'\0';
  2373. nameString.MaximumLength = sizeof(L"OsLoaderPath");
  2374. nameString.Length = sizeof(L"OsLoaderPath") - sizeof(WCHAR);
  2375. //
  2376. // Strip off the trailing backslash from the path (unless, of course, the path is a
  2377. // single backslash).
  2378. //
  2379. if ((OsLoaderPathName->Length > sizeof(WCHAR)) &&
  2380. (*(PWCHAR)((PCHAR)OsLoaderPathName->Buffer + OsLoaderPathName->Length - sizeof(WCHAR)) == L'\\')) {
  2381. OsLoaderPathName->Length -= sizeof(WCHAR);
  2382. *(PWCHAR)((PCHAR)OsLoaderPathName->Buffer + OsLoaderPathName->Length) = L'\0';
  2383. }
  2384. status = NtSetValueKey(setupHandle,
  2385. &nameString,
  2386. TITLE_INDEX_VALUE,
  2387. REG_SZ,
  2388. OsLoaderPathName->Buffer,
  2389. OsLoaderPathName->Length + sizeof(WCHAR)
  2390. );
  2391. #if DBG
  2392. if (!NT_SUCCESS(status)) {
  2393. DbgPrint("IopStoreSystemPartitionInformation: couldn't write OsLoaderPath value - %x\n", status);
  2394. }
  2395. #endif // DBG
  2396. NtClose(setupHandle);
  2397. }
  2398. NTSTATUS
  2399. IopLogErrorEvent(
  2400. IN ULONG SequenceNumber,
  2401. IN ULONG UniqueErrorValue,
  2402. IN NTSTATUS FinalStatus,
  2403. IN NTSTATUS SpecificIOStatus,
  2404. IN ULONG LengthOfInsert1,
  2405. IN PWCHAR Insert1,
  2406. IN ULONG LengthOfInsert2,
  2407. IN PWCHAR Insert2
  2408. )
  2409. /*++
  2410. Routine Description:
  2411. This routine allocates an error log entry, copies the supplied data
  2412. to it, and requests that it be written to the error log file.
  2413. Arguments:
  2414. SequenceNumber - A value that is unique to an IRP over the life of the irp in
  2415. this driver. - 0 generally means an error not associated with an IRP
  2416. UniqueErrorValue - A unique long word that identifies the particular
  2417. call to this function.
  2418. FinalStatus - The final status given to the irp that was associated
  2419. with this error. If this log entry is being made during one of
  2420. the retries this value will be STATUS_SUCCESS.
  2421. SpecificIOStatus - The IO status for a particular error.
  2422. LengthOfInsert1 - The length in bytes (including the terminating NULL)
  2423. of the first insertion string.
  2424. Insert1 - The first insertion string.
  2425. LengthOfInsert2 - The length in bytes (including the terminating NULL)
  2426. of the second insertion string. NOTE, there must
  2427. be a first insertion string for their to be
  2428. a second insertion string.
  2429. Insert2 - The second insertion string.
  2430. Return Value:
  2431. STATUS_SUCCESS - Success
  2432. STATUS_INVALID_HANDLE - Uninitialized error log device object
  2433. STATUS_NO_DATA_DETECTED - NULL Error log entry
  2434. --*/
  2435. {
  2436. PIO_ERROR_LOG_PACKET errorLogEntry;
  2437. PUCHAR ptrToFirstInsert;
  2438. PUCHAR ptrToSecondInsert;
  2439. if (!IopErrorLogObject) {
  2440. return(STATUS_INVALID_HANDLE);
  2441. }
  2442. errorLogEntry = IoAllocateErrorLogEntry(
  2443. IopErrorLogObject,
  2444. (UCHAR)( sizeof(IO_ERROR_LOG_PACKET) +
  2445. LengthOfInsert1 +
  2446. LengthOfInsert2) );
  2447. if ( errorLogEntry != NULL ) {
  2448. errorLogEntry->ErrorCode = SpecificIOStatus;
  2449. errorLogEntry->SequenceNumber = SequenceNumber;
  2450. errorLogEntry->MajorFunctionCode = 0;
  2451. errorLogEntry->RetryCount = 0;
  2452. errorLogEntry->UniqueErrorValue = UniqueErrorValue;
  2453. errorLogEntry->FinalStatus = FinalStatus;
  2454. errorLogEntry->DumpDataSize = 0;
  2455. ptrToFirstInsert = (PUCHAR)&errorLogEntry->DumpData[0];
  2456. ptrToSecondInsert = ptrToFirstInsert + LengthOfInsert1;
  2457. if (LengthOfInsert1) {
  2458. errorLogEntry->NumberOfStrings = 1;
  2459. errorLogEntry->StringOffset = (USHORT)(ptrToFirstInsert -
  2460. (PUCHAR)errorLogEntry);
  2461. RtlCopyMemory(
  2462. ptrToFirstInsert,
  2463. Insert1,
  2464. LengthOfInsert1
  2465. );
  2466. if (LengthOfInsert2) {
  2467. errorLogEntry->NumberOfStrings = 2;
  2468. RtlCopyMemory(
  2469. ptrToSecondInsert,
  2470. Insert2,
  2471. LengthOfInsert2
  2472. );
  2473. } //LenghtOfInsert2
  2474. } // LenghtOfInsert1
  2475. IoWriteErrorLogEntry(errorLogEntry);
  2476. return(STATUS_SUCCESS);
  2477. } // errorLogEntry != NULL
  2478. return(STATUS_NO_DATA_DETECTED);
  2479. } //IopLogErrorEvent
  2480. BOOLEAN
  2481. IopInitializeReserveIrp(
  2482. PIOP_RESERVE_IRP_ALLOCATOR Allocator
  2483. )
  2484. /*++
  2485. Routine Description:
  2486. This routine initializes the reserve IRP allocator for paging reads.
  2487. Arguments:
  2488. Allocator - Pointer to the reserve IRP allocator structure.
  2489. created by the OS Loader.
  2490. Return Value:
  2491. The function value is a BOOLEAN indicating whether or not the reserver allocator
  2492. was successfully initialized.
  2493. --*/
  2494. {
  2495. Allocator->ReserveIrpStackSize = MAX_RESERVE_IRP_STACK_SIZE;
  2496. Allocator->ReserveIrp = IoAllocateIrp(MAX_RESERVE_IRP_STACK_SIZE, FALSE);
  2497. if (Allocator->ReserveIrp == NULL) {
  2498. return FALSE;
  2499. }
  2500. Allocator->IrpAllocated = FALSE;
  2501. KeInitializeEvent(&Allocator->Event, SynchronizationEvent, FALSE);
  2502. return TRUE;
  2503. }