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.

757 lines
21 KiB

  1. /*++
  2. Copyright (c) 2000-2000 Microsoft Corporation
  3. Module Name:
  4. Init.c
  5. Abstract:
  6. This module implements Initialization routines
  7. the PGM Transport and other routines that are specific to the
  8. NT implementation of a driver.
  9. Author:
  10. Mohammad Shabbir Alam (MAlam) 3-30-2000
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. #include <ntddtcp.h>
  15. //******************* Pageable Routine Declarations ****************
  16. #ifdef ALLOC_PRAGMA
  17. #pragma alloc_text(PAGE, InitPgm)
  18. #pragma alloc_text(PAGE, InitStaticPgmConfig)
  19. #pragma alloc_text(PAGE, InitDynamicPgmConfig)
  20. #pragma alloc_text(PAGE, PgmReadRegistryParameters)
  21. #pragma alloc_text(PAGE, AllocateInitialPgmStructures)
  22. #pragma alloc_text(PAGE, PgmCreateDevice)
  23. #pragma alloc_text(PAGE, PgmDereferenceDevice)
  24. #endif
  25. //******************* Pageable Routine Declarations ****************
  26. //----------------------------------------------------------------------------
  27. NTSTATUS
  28. InitStaticPgmConfig(
  29. IN PDRIVER_OBJECT DriverObject,
  30. IN PUNICODE_STRING RegistryPath
  31. )
  32. /*++
  33. Routine Description:
  34. This routine initializes the static values used by Pgm
  35. Arguments:
  36. IN DriverObject - Pointer to driver object created by the system.
  37. IN RegistryPath - Pgm driver's registry location
  38. Return Value:
  39. NTSTATUS - Final status of the operation
  40. --*/
  41. {
  42. NTSTATUS status;
  43. PAGED_CODE();
  44. //
  45. // Initialize the Static Configuration data structure
  46. //
  47. PgmZeroMemory (&PgmStaticConfig, sizeof(tPGM_STATIC_CONFIG));
  48. //
  49. // get the file system process since we need to know this for
  50. // allocating and freeing handles
  51. //
  52. PgmStaticConfig.FspProcess = PsGetCurrentProcess();
  53. PgmStaticConfig.DriverObject = DriverObject; // save the driver object for event logging purposes
  54. //
  55. // save the registry path for later use (to read the registry)
  56. //
  57. PgmStaticConfig.RegistryPath.MaximumLength = (USHORT) RegistryPath->MaximumLength;
  58. if (PgmStaticConfig.RegistryPath.Buffer = PgmAllocMem (RegistryPath->MaximumLength, PGM_TAG('0')))
  59. {
  60. RtlCopyUnicodeString(&PgmStaticConfig.RegistryPath, RegistryPath);
  61. }
  62. else
  63. {
  64. PgmLog (PGM_LOG_ERROR, DBG_INIT_PGM, "InitStaticPgmConfig",
  65. "INSUFFICIENT_RESOURCES <%d> bytes\n", PgmStaticConfig.RegistryPath.MaximumLength);
  66. return (STATUS_INSUFFICIENT_RESOURCES);
  67. }
  68. ExInitializeNPagedLookasideList(&PgmStaticConfig.TdiLookasideList,
  69. NULL,
  70. NULL,
  71. 0,
  72. sizeof (tTDI_SEND_CONTEXT),
  73. PGM_TAG('2'),
  74. TDI_LOOKASIDE_DEPTH);
  75. ExInitializeNPagedLookasideList(&PgmStaticConfig.DebugMessagesLookasideList,
  76. NULL,
  77. NULL,
  78. 0,
  79. (MAX_DEBUG_MESSAGE_LENGTH + 1),
  80. PGM_TAG('3'),
  81. DEBUG_MESSAGES_LOOKASIDE_DEPTH);
  82. status = FECInitGlobals ();
  83. if (!NT_SUCCESS (status))
  84. {
  85. ExDeleteNPagedLookasideList (&PgmStaticConfig.DebugMessagesLookasideList);
  86. ExDeleteNPagedLookasideList (&PgmStaticConfig.TdiLookasideList);
  87. PgmFreeMem (PgmStaticConfig.RegistryPath.Buffer);
  88. }
  89. PgmLog (PGM_LOG_INFORM_ALL_FUNCS, DBG_INIT_PGM, "InitStaticPgmConfig",
  90. "FECInitGlobals returned <%x>\n", status);
  91. return (status);
  92. }
  93. //----------------------------------------------------------------------------
  94. NTSTATUS
  95. InitDynamicPgmConfig(
  96. )
  97. /*++
  98. Routine Description:
  99. This routine initializes the dynamic values used by Pgm
  100. Arguments:
  101. Return Value:
  102. NTSTATUS - Final status of the operation
  103. --*/
  104. {
  105. ULONG i;
  106. PAGED_CODE();
  107. //
  108. // Initialize the Static Configuration data structure
  109. //
  110. PgmZeroMemory (&PgmDynamicConfig, sizeof(tPGM_DYNAMIC_CONFIG));
  111. //
  112. // Initialize the list heads before doing anything else since
  113. // we can access them anytime later
  114. //
  115. InitializeListHead (&PgmDynamicConfig.SenderAddressHead);
  116. InitializeListHead (&PgmDynamicConfig.ReceiverAddressHead);
  117. InitializeListHead (&PgmDynamicConfig.CurrentReceivers);
  118. InitializeListHead (&PgmDynamicConfig.CleanedUpAddresses);
  119. InitializeListHead (&PgmDynamicConfig.ClosedConnections);
  120. InitializeListHead (&PgmDynamicConfig.ConnectionsCreated);
  121. InitializeListHead (&PgmDynamicConfig.CleanedUpConnections);
  122. InitializeListHead (&PgmDynamicConfig.LocalInterfacesList);
  123. InitializeListHead (&PgmDynamicConfig.WorkerQList);
  124. PgmDynamicConfig.ReceiversTimerTickCount = 1; // Init
  125. PgmDynamicConfig.SourcePort = (USHORT) GetRandomInteger (2000, 20000);
  126. #if DBG
  127. for (i=0; i<MAXIMUM_PROCESSORS; i++)
  128. {
  129. PgmDynamicConfig.CurrentLockNumber[i] = 0;
  130. }
  131. #endif
  132. PgmInitLock (&PgmDynamicConfig, DCONFIG_LOCK);
  133. KeInitializeEvent (&PgmDynamicConfig.LastWorkerItemEvent, NotificationEvent, TRUE);
  134. PgmLog (PGM_LOG_INFORM_ALL_FUNCS, DBG_INIT_PGM, "InitDynamicPgmConfig",
  135. "STATUS_SUCCESS\n");
  136. return (STATUS_SUCCESS);
  137. }
  138. //----------------------------------------------------------------------------
  139. NTSTATUS
  140. PgmOpenRegistryParameters(
  141. IN PUNICODE_STRING RegistryPath,
  142. OUT HANDLE *pConfigHandle,
  143. OUT HANDLE *pParametersHandle
  144. )
  145. /*++
  146. Routine Description:
  147. This routine reads any required registry parameters
  148. Arguments:
  149. OUT ppPgmDynamic -- non-NULL only if we have any registry valuies to read
  150. Return Value:
  151. NTSTATUS - Final status of the operation
  152. --*/
  153. {
  154. OBJECT_ATTRIBUTES TmpObjectAttributes;
  155. NTSTATUS status;
  156. ULONG Disposition;
  157. UNICODE_STRING KeyName;
  158. PWSTR ParametersString = L"Parameters";
  159. PAGED_CODE();
  160. InitializeObjectAttributes (&TmpObjectAttributes,
  161. RegistryPath, // name
  162. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, // attributes
  163. NULL, // root
  164. NULL); // security descriptor
  165. status = ZwCreateKey (pConfigHandle,
  166. KEY_READ,
  167. &TmpObjectAttributes,
  168. 0, // title index
  169. NULL, // class
  170. 0, // create options
  171. &Disposition); // disposition
  172. if (!NT_SUCCESS(status))
  173. {
  174. PgmLog (PGM_LOG_ERROR, DBG_INIT_PGM, "PgmOpenRegistryParameters",
  175. "ZwCreateKey returned <%x>\n", status);
  176. return (status);
  177. }
  178. //
  179. // Open the Pgm key.
  180. //
  181. RtlInitUnicodeString (&KeyName, ParametersString);
  182. InitializeObjectAttributes (&TmpObjectAttributes,
  183. &KeyName, // name
  184. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, // attributes
  185. *pConfigHandle, // root
  186. NULL); // security descriptor
  187. status = ZwOpenKey (pParametersHandle, KEY_READ, &TmpObjectAttributes);
  188. if (!NT_SUCCESS(status))
  189. {
  190. PgmLog (PGM_LOG_ERROR, DBG_INIT_PGM, "PgmOpenRegistryParameters",
  191. "ZwOpenKey returned <%x>\n", status);
  192. ZwClose(*pConfigHandle);
  193. }
  194. return (status);
  195. }
  196. //----------------------------------------------------------------------------
  197. NTSTATUS
  198. ReadRegistryElement(
  199. IN HANDLE HandleToKey,
  200. IN PWSTR pwsValueName,
  201. OUT PUNICODE_STRING pucString
  202. )
  203. /*++
  204. Routine Description:
  205. This routine is will read a string value given by pwsValueName, under a
  206. given Key (which must be open) - given by HandleToKey. This routine
  207. allocates memory for the buffer in the returned pucString, so the caller
  208. must deallocate that.
  209. Arguments:
  210. pwsValueName- the name of the value to read (i.e. IPAddress)
  211. Return Value:
  212. pucString - the string returns the string read from the registry
  213. --*/
  214. {
  215. ULONG BytesRead;
  216. NTSTATUS Status;
  217. UNICODE_STRING TempString;
  218. PKEY_VALUE_FULL_INFORMATION ReadValue = NULL;
  219. PAGED_CODE();
  220. //
  221. // First, get the sizeof the string
  222. //
  223. RtlInitUnicodeString(&TempString, pwsValueName); // initilize the name of the value to read
  224. Status = ZwQueryValueKey (HandleToKey,
  225. &TempString, // string to retrieve
  226. KeyValueFullInformation,
  227. NULL,
  228. 0,
  229. &BytesRead); // get bytes to be read
  230. if (((!NT_SUCCESS (Status)) &&
  231. (Status != STATUS_BUFFER_OVERFLOW) &&
  232. (Status != STATUS_BUFFER_TOO_SMALL)) ||
  233. (BytesRead == 0))
  234. {
  235. return (STATUS_UNSUCCESSFUL);
  236. }
  237. if (ReadValue = (PKEY_VALUE_FULL_INFORMATION) PgmAllocMem (BytesRead, PGM_TAG('R')))
  238. {
  239. Status = ZwQueryValueKey (HandleToKey,
  240. &TempString, // string to retrieve
  241. KeyValueFullInformation,
  242. (PVOID)ReadValue, // returned info
  243. BytesRead,
  244. &BytesRead); // # of bytes returned
  245. if ((NT_SUCCESS (Status)) &&
  246. (ReadValue->DataLength))
  247. {
  248. // move the read in data to the front of the buffer
  249. RtlMoveMemory ((PVOID) ReadValue, (((PUCHAR)ReadValue) + ReadValue->DataOffset), ReadValue->DataLength);
  250. RtlInitUnicodeString (pucString, (PWSTR) ReadValue);
  251. }
  252. else
  253. {
  254. PgmFreeMem (ReadValue);
  255. Status = STATUS_UNSUCCESSFUL;
  256. }
  257. }
  258. else
  259. {
  260. Status = STATUS_INSUFFICIENT_RESOURCES;
  261. }
  262. return(Status);
  263. }
  264. //----------------------------------------------------------------------------
  265. NTSTATUS
  266. PgmReadRegistryParameters(
  267. IN PUNICODE_STRING RegistryPath,
  268. OUT tPGM_REGISTRY_CONFIG **ppPgmRegistryConfig
  269. )
  270. /*++
  271. Routine Description:
  272. This routine reads any required registry parameters
  273. Arguments:
  274. OUT ppPgmDynamic -- non-NULL only if we have any registry valuies to read
  275. Return Value:
  276. NTSTATUS - Final status of the operation
  277. --*/
  278. {
  279. HANDLE PgmConfigHandle;
  280. HANDLE ParametersHandle;
  281. NTSTATUS status;
  282. tPGM_REGISTRY_CONFIG *pRegistryConfig;
  283. PAGED_CODE();
  284. if (!(pRegistryConfig = PgmAllocMem (sizeof (tPGM_REGISTRY_CONFIG), PGM_TAG('0'))))
  285. {
  286. return (STATUS_INSUFFICIENT_RESOURCES);
  287. }
  288. status = PgmOpenRegistryParameters (RegistryPath, &PgmConfigHandle, &ParametersHandle);
  289. if (!NT_SUCCESS(status))
  290. {
  291. PgmLog (PGM_LOG_ERROR, DBG_INIT_PGM, "PgmReadRegistryParameters",
  292. "ZwOpenKey returned <%x>\n", status);
  293. PgmFreeMem (pRegistryConfig);
  294. return STATUS_UNSUCCESSFUL;
  295. }
  296. //
  297. // zero out the Registry fields
  298. //
  299. PgmZeroMemory (pRegistryConfig, sizeof(tPGM_REGISTRY_CONFIG));
  300. //
  301. // ***************************************
  302. // Now read all the registry needs we need
  303. //
  304. status = ReadRegistryElement (ParametersHandle,
  305. PARAM_SENDER_FILE_LOCATION,
  306. &pRegistryConfig->ucSenderFileLocation);
  307. if (NT_SUCCESS (status))
  308. {
  309. pRegistryConfig->Flags |= PGM_REGISTRY_SENDER_FILE_SPECIFIED;
  310. }
  311. //
  312. // End of list of entries to be read
  313. // ***************************************
  314. //
  315. ZwClose(ParametersHandle);
  316. ZwClose(PgmConfigHandle);
  317. PgmLog (PGM_LOG_INFORM_ALL_FUNCS, DBG_INIT_PGM, "PgmReadRegistryParameters",
  318. "STATUS_SUCCESS\n");
  319. *ppPgmRegistryConfig = pRegistryConfig;
  320. return (STATUS_SUCCESS);
  321. }
  322. //----------------------------------------------------------------------------
  323. NTSTATUS
  324. AllocateInitialPgmStructures(
  325. )
  326. /*++
  327. Routine Description:
  328. This routine allocates any initial structures that may be required
  329. Arguments:
  330. Return Value:
  331. NTSTATUS - Final status of the operation
  332. --*/
  333. {
  334. PAGED_CODE();
  335. PgmLog (PGM_LOG_INFORM_ALL_FUNCS, DBG_INIT_PGM, "AllocateInitialPgmStructures",
  336. "STATUS_SUCCESS\n");
  337. return (STATUS_SUCCESS);
  338. }
  339. //----------------------------------------------------------------------------
  340. NTSTATUS
  341. PgmCreateDevice(
  342. )
  343. /*++
  344. Routine Description:
  345. This routine allocates the Pgm device for clients to
  346. call into the Pgm driver.
  347. Arguments:
  348. IN
  349. Return Value:
  350. NTSTATUS - Final status of the CreateDevice operation
  351. --*/
  352. {
  353. NTSTATUS Status;
  354. tPGM_DEVICE *pPgmDevice = NULL;
  355. UNICODE_STRING ucPgmDeviceExportName;
  356. UNICODE_STRING ucProtocolNumber;
  357. WCHAR wcProtocolNumber[10];
  358. USHORT PgmBindDeviceNameLength;
  359. PAGED_CODE();
  360. RtlInitUnicodeString (&ucPgmDeviceExportName, WC_PGM_DEVICE_EXPORT_NAME);
  361. PgmBindDeviceNameLength = sizeof(DD_RAW_IP_DEVICE_NAME) + 10;
  362. Status = IoCreateDevice (PgmStaticConfig.DriverObject, // Driver Object
  363. sizeof(tPGM_DEVICE)+PgmBindDeviceNameLength, // Device Extension
  364. &ucPgmDeviceExportName, // Device Name
  365. FILE_DEVICE_NETWORK, // Device type 0x12
  366. FILE_DEVICE_SECURE_OPEN, // Device Characteristics
  367. FALSE, // Exclusive
  368. &pPgmDeviceObject);
  369. if (!NT_SUCCESS (Status))
  370. {
  371. PgmLog (PGM_LOG_ERROR, DBG_INIT_PGM, "PgmCreateDevice",
  372. "FAILed <%x> ExportDevice=%wZ\n", Status, &ucPgmDeviceExportName);
  373. pgPgmDevice = NULL;
  374. return Status;
  375. }
  376. pPgmDevice = (tPGM_DEVICE *) pPgmDeviceObject->DeviceExtension;
  377. //
  378. // zero out the DeviceExtension
  379. //
  380. PgmZeroMemory (pPgmDevice, sizeof(tPGM_DEVICE)+PgmBindDeviceNameLength);
  381. // put a verifier value into the structure so that we can check that
  382. // we are operating on the right data
  383. PgmInitLock (pPgmDevice, DEVICE_LOCK);
  384. pPgmDevice->Verify = PGM_VERIFY_DEVICE;
  385. PGM_REFERENCE_DEVICE (pPgmDevice, REF_DEV_CREATE, TRUE);
  386. pPgmDevice->pPgmDeviceObject = pPgmDeviceObject;
  387. //
  388. // Save the raw IP device name as a counted string. The device
  389. // name is followed by a path separator then the protocol number
  390. // of interest.
  391. //
  392. pPgmDevice->ucBindName.Buffer = (PWSTR) &pPgmDevice->BindNameBuffer;
  393. pPgmDevice->ucBindName.Length = 0;
  394. pPgmDevice->ucBindName.MaximumLength = PgmBindDeviceNameLength;
  395. RtlAppendUnicodeToString (&pPgmDevice->ucBindName, DD_RAW_IP_DEVICE_NAME);
  396. pPgmDevice->ucBindName.Buffer[pPgmDevice->ucBindName.Length / sizeof(WCHAR)] = OBJ_NAME_PATH_SEPARATOR;
  397. pPgmDevice->ucBindName.Length += sizeof(WCHAR);
  398. ucProtocolNumber.Buffer = wcProtocolNumber;
  399. ucProtocolNumber.MaximumLength = sizeof (wcProtocolNumber);
  400. RtlIntegerToUnicodeString ((ULONG) IPPROTO_RM, 10, &ucProtocolNumber);
  401. RtlAppendUnicodeStringToString (&pPgmDevice->ucBindName, &ucProtocolNumber);
  402. //
  403. // Initialize the event that will be used to signal the Device is ready to be deleted
  404. //
  405. KeInitializeEvent (&pPgmDevice->DeviceCleanedupEvent, NotificationEvent, FALSE);
  406. //
  407. // Now open a control channel on top of Ip
  408. //
  409. Status = PgmTdiOpenControl (pPgmDevice);
  410. if (!NT_SUCCESS (Status))
  411. {
  412. PgmLog (PGM_LOG_ERROR, DBG_INIT_PGM, "PgmCreateDevice",
  413. "PgmTdiOpenControl FAILed <%x>\n", Status);
  414. IoDeleteDevice (pPgmDeviceObject);
  415. return (Status);
  416. }
  417. // increase the stack size of our device object, over that of the transport
  418. // so that clients create Irps large enough
  419. // to pass on to the transport below.
  420. // In theory, we should just add 1 here, to account for our presence in the
  421. // driver chain.
  422. //
  423. pPgmDeviceObject->StackSize = pPgmDevice->pControlDeviceObject->StackSize + 1;
  424. pPgmDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  425. pgPgmDevice = pPgmDevice;
  426. PgmLog (PGM_LOG_INFORM_STATUS, DBG_INIT_PGM, "PgmCreateDevice",
  427. "Status=<%x> ExportDevice=%wZ\n", Status, &ucPgmDeviceExportName);
  428. return (Status);
  429. }
  430. //----------------------------------------------------------------------------
  431. VOID
  432. PgmDereferenceDevice(
  433. IN OUT tPGM_DEVICE **ppPgmDevice,
  434. IN ULONG RefContext
  435. )
  436. /*++
  437. Routine Description:
  438. This routine dereferences the RefCount on the Pgm
  439. device extension and deletes the device if the RefCount
  440. goes down to 0.
  441. Arguments:
  442. IN ppPgmDevice -- ptr to PgmDevice Extension
  443. IN RefContext -- the context for which this device extension was
  444. referenced earlier
  445. Return Value:
  446. NTSTATUS - Final status of the set event operation
  447. --*/
  448. {
  449. tPGM_DEVICE *pPgmDevice = *ppPgmDevice;
  450. KAPC_STATE ApcState;
  451. BOOLEAN fAttached;
  452. PAGED_CODE();
  453. ASSERT (PGM_VERIFY_HANDLE (pPgmDevice, PGM_VERIFY_DEVICE));
  454. ASSERT (pPgmDevice->RefCount); // Check for too many derefs
  455. ASSERT (pPgmDevice->ReferenceContexts[RefContext]--);
  456. if (--pPgmDevice->RefCount)
  457. {
  458. return;
  459. }
  460. if (pPgmDevice->hControl)
  461. {
  462. //
  463. // This is only done at Load/Unload time, so we should
  464. // be currently in the System Process Context!
  465. //
  466. PgmAttachFsp (&ApcState, &fAttached, REF_FSP_DESTROY_DEVICE);
  467. ObDereferenceObject (pPgmDevice->pControlFileObject);
  468. ZwClose (pPgmDevice->hControl);
  469. pPgmDevice->pControlFileObject = NULL;
  470. pPgmDevice->hControl = NULL;
  471. PgmDetachFsp (&ApcState, &fAttached, REF_FSP_DESTROY_DEVICE);
  472. }
  473. PgmLog (PGM_LOG_INFORM_STATUS, DBG_INIT_PGM, "PgmDereferenceDevice",
  474. "Deleting pgPgmDevice=%x ...\n", pgPgmDevice);
  475. IoDeleteDevice (pPgmDevice->pPgmDeviceObject);
  476. *ppPgmDevice = NULL;
  477. return;
  478. }
  479. //----------------------------------------------------------------------------
  480. NTSTATUS
  481. InitPgm(
  482. IN PDRIVER_OBJECT DriverObject,
  483. IN PUNICODE_STRING RegistryPath
  484. )
  485. /*++
  486. Routine Description:
  487. This routine is called at DriverEntry to initialize all the
  488. Pgm parameters
  489. Arguments:
  490. IN DriverObject - Pointer to driver object created by the system.
  491. IN RegistryPath - Pgm driver's registry location
  492. Return Value:
  493. NTSTATUS - Final status of the set event operation
  494. --*/
  495. {
  496. NTSTATUS status;
  497. tPGM_REGISTRY_CONFIG *pPgmRegistry = NULL;
  498. PAGED_CODE();
  499. status = InitStaticPgmConfig (DriverObject, RegistryPath);
  500. if (!NT_SUCCESS (status))
  501. {
  502. PgmLog (PGM_LOG_ERROR, DBG_INIT_PGM, "InitPgm",
  503. "InitStaticPgmConfig returned <%x>\n", status);
  504. return (status);
  505. }
  506. //---------------------------------------------------------------------------------------
  507. status = InitDynamicPgmConfig ();
  508. if (!NT_SUCCESS (status))
  509. {
  510. PgmLog (PGM_LOG_ERROR, DBG_INIT_PGM, "InitPgm",
  511. "InitDynamicPgmConfig returned <%x>\n", status);
  512. CleanupInit (E_CLEANUP_STATIC_CONFIG);
  513. return (status);
  514. }
  515. //---------------------------------------------------------------------------------------
  516. //
  517. // Read Registry configuration data
  518. //
  519. status = PgmReadRegistryParameters (RegistryPath, &pPgmRegistry);
  520. if (!NT_SUCCESS(status))
  521. {
  522. //
  523. // There must have been some major problems with the registry read, so we will not load!
  524. //
  525. PgmLog (PGM_LOG_ERROR, DBG_INIT_PGM, "InitPgm",
  526. "FAILed to read registry, status = <%x>\n", status);
  527. CleanupInit (E_CLEANUP_DYNAMIC_CONFIG);
  528. return (status);
  529. }
  530. ASSERT (pPgmRegistry);
  531. pPgmRegistryConfig = pPgmRegistry;
  532. //---------------------------------------------------------------------------------------
  533. //
  534. // Allocate the data structures we need at Init time
  535. //
  536. status = AllocateInitialPgmStructures ();
  537. if (!NT_SUCCESS(status))
  538. {
  539. //
  540. // There must have been some major problems with the registry read, so we will not load!
  541. //
  542. PgmLog (PGM_LOG_ERROR, DBG_INIT_PGM, "InitPgm",
  543. "FAILed to allocate initial structures = <%x>\n", status);
  544. CleanupInit (E_CLEANUP_REGISTRY_PARAMETERS);
  545. return (status);
  546. }
  547. //---------------------------------------------------------------------------------------
  548. //
  549. // Create the Pgm Device to be exported
  550. //
  551. status = PgmCreateDevice ();
  552. if (!NT_SUCCESS(status))
  553. {
  554. //
  555. // There must have been some major problems with the registry read, so we will not load!
  556. //
  557. PgmLog (PGM_LOG_ERROR, DBG_INIT_PGM, "InitPgm",
  558. "FAILed to create PgmDevice, status=<%x>\n", status);
  559. CleanupInit (E_CLEANUP_STRUCTURES);
  560. return (status);
  561. }
  562. PgmLog (PGM_LOG_INFORM_ALL_FUNCS, DBG_INIT_PGM, "InitPgm",
  563. "SUCCEEDed!\n");
  564. return (status);
  565. }