Leaked source code of windows server 2003
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.

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