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.

1252 lines
32 KiB

  1. /*++
  2. Copyright (c) 2000-2000 Microsoft Corporation
  3. Module Name:
  4. Driver.c
  5. Abstract:
  6. This module implements the DRIVER_INITIALIZATION routine for
  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. // ULONG PgmDebugFlags = DBG_ENABLE_DBGPRINT;
  15. // ULONG PgmDebugFlags = 0xffffffff;
  16. #if DBG
  17. enum eSEVERITY_LEVEL PgmDebuggerSeverity = PGM_LOG_INFORM_STATUS;
  18. #else
  19. enum eSEVERITY_LEVEL PgmDebuggerSeverity = PGM_LOG_DISABLED;
  20. #endif // DBG
  21. ULONG PgmDebuggerPath = 0xffffffff;
  22. enum eSEVERITY_LEVEL PgmLogFileSeverity = PGM_LOG_DISABLED;
  23. ULONG PgmLogFilePath = 0x0;
  24. tPGM_STATIC_CONFIG PgmStaticConfig;
  25. tPGM_DYNAMIC_CONFIG PgmDynamicConfig;
  26. tPGM_REGISTRY_CONFIG *pPgmRegistryConfig = NULL;
  27. tPGM_DEVICE *pgPgmDevice = NULL;
  28. DEVICE_OBJECT *pPgmDeviceObject = NULL;
  29. //******************* Pageable Routine Declarations ****************
  30. #ifdef ALLOC_PRAGMA
  31. #pragma alloc_text(INIT, DriverEntry)
  32. #pragma alloc_text(PAGE, PgmUnload)
  33. #endif
  34. //******************* Pageable Routine Declarations ****************
  35. //----------------------------------------------------------------------------
  36. //
  37. // Internal routines
  38. //
  39. FILE_FULL_EA_INFORMATION *
  40. FindEA(
  41. IN PFILE_FULL_EA_INFORMATION StartEA,
  42. IN CHAR *pTargetName,
  43. IN USHORT TargetNameLength
  44. );
  45. VOID
  46. CompleteDispatchIrp(
  47. IN PIRP pIrp,
  48. IN NTSTATUS status
  49. );
  50. //----------------------------------------------------------------------------
  51. NTSTATUS
  52. DriverEntry(
  53. IN PDRIVER_OBJECT DriverObject,
  54. IN PUNICODE_STRING RegistryPath
  55. )
  56. /*++
  57. Routine Description:
  58. This is the initialization routine for the PGM device driver.
  59. This routine creates the device object for the PGM
  60. device and does other driver initialization.
  61. Arguments:
  62. IN DriverObject - Pointer to driver object created by the system.
  63. IN RegistryPath - Pgm driver's registry location
  64. Return Value:
  65. NTSTATUS - The function value is the final status from the initialization
  66. operation.
  67. --*/
  68. {
  69. NTSTATUS status;
  70. PAGED_CODE();
  71. //---------------------------------------------------------------------------------------
  72. status = InitPgm (DriverObject, RegistryPath);
  73. if (!NT_SUCCESS (status))
  74. {
  75. PgmLog (PGM_LOG_ERROR, DBG_DRIVER_ENTRY, "DriverEntry",
  76. "InitPgm returned <%x>\n", status);
  77. return (status);
  78. }
  79. //---------------------------------------------------------------------------------------
  80. //
  81. // Initialize the driver object with this driver's entry points.
  82. //
  83. DriverObject->MajorFunction[IRP_MJ_CREATE] = (PDRIVER_DISPATCH)PgmDispatch;
  84. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = (PDRIVER_DISPATCH)PgmDispatch;
  85. DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = (PDRIVER_DISPATCH)PgmDispatch;
  86. DriverObject->MajorFunction[IRP_MJ_CLEANUP] = (PDRIVER_DISPATCH)PgmDispatch;
  87. DriverObject->MajorFunction[IRP_MJ_CLOSE] = (PDRIVER_DISPATCH)PgmDispatch;
  88. DriverObject->MajorFunction[IRP_MJ_PNP] = (PDRIVER_DISPATCH)PgmDispatch;
  89. DriverObject->DriverUnload = PgmUnload;
  90. //---------------------------------------------------------------------------------------
  91. status = SetTdiHandlers ();
  92. if (!NT_SUCCESS (status))
  93. {
  94. PgmLog (PGM_LOG_ERROR, DBG_DRIVER_ENTRY, "DriverEntry",
  95. "SetTdiHandlers returned <%x>\n", status);
  96. CleanupInit (E_CLEANUP_DEVICE);
  97. return (status);
  98. }
  99. //---------------------------------------------------------------------------------------
  100. //
  101. // Return to the caller.
  102. //
  103. PgmLog (PGM_LOG_INFORM_STATUS, DBG_DRIVER_ENTRY, "DriverEntry",
  104. "Succeeded! ...\n");
  105. return (status);
  106. }
  107. //----------------------------------------------------------------------------
  108. NTSTATUS
  109. PgmDispatch(
  110. IN PDEVICE_OBJECT pDeviceObject,
  111. IN PIRP pIrp
  112. )
  113. /*++
  114. Routine Description:
  115. This is the PGM driver's primary dispatch function for all Irp requests.
  116. Arguments:
  117. IN pDeviceObject - ptr to device object for target device
  118. IN pIrp - ptr to I/O request packet
  119. Return Value:
  120. STATUS_SUCCESS
  121. --*/
  122. {
  123. NTSTATUS status = STATUS_UNSUCCESSFUL;
  124. tPGM_DEVICE *pPgmDevice = pDeviceObject->DeviceExtension;
  125. PIO_STACK_LOCATION pIrpSp;
  126. UCHAR IrpFlags;
  127. UCHAR IrpMajorFunction;
  128. UCHAR IrpMinorFunction;
  129. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  130. IrpFlags = pIrpSp->Control;
  131. IrpMajorFunction = pIrpSp->MajorFunction;
  132. IrpMinorFunction = pIrpSp->MinorFunction;
  133. pIrp->IoStatus.Information = 0;
  134. pIrp->IoStatus.Status = STATUS_PENDING;
  135. IoMarkIrpPending(pIrp);
  136. ASSERT (pDeviceObject == pPgmDeviceObject);
  137. switch (IrpMajorFunction)
  138. {
  139. case IRP_MJ_CREATE:
  140. {
  141. status = PgmCreate (pPgmDevice, pIrp, pIrpSp);
  142. break;
  143. }
  144. case IRP_MJ_CLEANUP:
  145. {
  146. status = PgmCleanup (pPgmDevice, pIrp, pIrpSp);
  147. break;
  148. }
  149. case IRP_MJ_CLOSE:
  150. {
  151. status = PgmClose (pPgmDevice, pIrp, pIrpSp);
  152. break;
  153. }
  154. case IRP_MJ_DEVICE_CONTROL:
  155. {
  156. if (STATUS_SUCCESS != TdiMapUserRequest (pDeviceObject, pIrp, pIrpSp))
  157. {
  158. //
  159. // This is not a Tdi request!
  160. //
  161. status = PgmDispatchIoctls (pPgmDevice, pIrp, pIrpSp); // To handle Ioctls
  162. break;
  163. }
  164. //
  165. // Fall through for Internal Device Control!
  166. //
  167. }
  168. case IRP_MJ_INTERNAL_DEVICE_CONTROL:
  169. {
  170. status = PgmDispatchInternalDeviceControl (pPgmDevice, pIrp, pIrpSp);
  171. break;
  172. }
  173. case IRP_MJ_PNP:
  174. {
  175. PgmLog (PGM_LOG_ERROR, DBG_DRIVER_ENTRY, "PgmDispatch",
  176. "[IRP_MJ_PNP:%x]: pIrp=<%x> Unsupported!\n", pIrpSp->MinorFunction, pIrp);
  177. break;
  178. }
  179. default:
  180. {
  181. PgmLog (PGM_LOG_ERROR, DBG_DRIVER_ENTRY, "PgmDispatch",
  182. "pIrp=<%x>, Unsupported! [%x:%x]\n", pIrp, pIrpSp->MajorFunction, pIrpSp->MinorFunction);
  183. break;
  184. }
  185. }
  186. PgmLog (PGM_LOG_INFORM_ALL_FUNCS, DBG_DRIVER_ENTRY, "PgmDispatch",
  187. "pIrp=<%x>, status=<%x>, [%d-->%d]\n", pIrp, status, IrpMajorFunction, IrpMinorFunction);
  188. if (status != STATUS_PENDING)
  189. {
  190. // reset the pending returned bit, since we are NOT returning pending
  191. pIrpSp->Control = IrpFlags;
  192. CompleteDispatchIrp (pIrp, status);
  193. }
  194. return (status);
  195. } // PgmDispatch
  196. //----------------------------------------------------------------------------
  197. VOID
  198. CleanupInit(
  199. enum eCLEANUP_STAGE CleanupStage
  200. )
  201. /*++
  202. Routine Description:
  203. This routine is called either at DriverEntry or DriverUnload
  204. to cleanup (or do partial cleanup) of items initialized at Init-time
  205. Arguments:
  206. IN CleanupStage -- determines the stage to which we had initialized
  207. settings
  208. Return Value:
  209. NONE
  210. --*/
  211. {
  212. NTSTATUS status;
  213. LIST_ENTRY *pEntry;
  214. PGMLockHandle OldIrq;
  215. PGM_WORKER_CONTEXT *pWorkerContext;
  216. PPGM_WORKER_ROUTINE pDelayedWorkerRoutine;
  217. tLOCAL_INTERFACE *pLocalInterface = NULL;
  218. tADDRESS_ON_INTERFACE *pLocalAddress = NULL;
  219. PgmLog (PGM_LOG_INFORM_ALL_FUNCS, DBG_DRIVER_ENTRY, "CleanupInit",
  220. "CleanupStage=<%d>\n", CleanupStage);
  221. switch (CleanupStage)
  222. {
  223. case (E_CLEANUP_UNLOAD):
  224. {
  225. //
  226. // Ensure that there are no more worker threads to be cleaned up
  227. //
  228. //
  229. // See if there are any worker threads currently executing, and if so, wait for
  230. // them to complete
  231. //
  232. KeClearEvent (&PgmDynamicConfig.LastWorkerItemEvent);
  233. PgmLock (&PgmDynamicConfig, OldIrq);
  234. if (PgmDynamicConfig.NumWorkerThreadsQueued)
  235. {
  236. PgmUnlock (&PgmDynamicConfig, OldIrq);
  237. status = KeWaitForSingleObject(&PgmDynamicConfig.LastWorkerItemEvent, // Object to wait on.
  238. Executive, // Reason for waiting
  239. KernelMode, // Processor mode
  240. FALSE, // Alertable
  241. NULL); // Timeout
  242. ASSERT (status == STATUS_SUCCESS);
  243. PgmLock (&PgmDynamicConfig, OldIrq);
  244. }
  245. ASSERT (!PgmDynamicConfig.NumWorkerThreadsQueued);
  246. //
  247. // Dequeue each of the requests in the Worker Queue and complete them
  248. //
  249. while (!IsListEmpty (&PgmDynamicConfig.WorkerQList))
  250. {
  251. pWorkerContext = CONTAINING_RECORD(PgmDynamicConfig.WorkerQList.Flink, PGM_WORKER_CONTEXT, PgmConfigLinkage);
  252. RemoveEntryList (&pWorkerContext->PgmConfigLinkage);
  253. PgmUnlock (&PgmDynamicConfig, OldIrq);
  254. pDelayedWorkerRoutine = pWorkerContext->WorkerRoutine;
  255. PgmLog (PGM_LOG_INFORM_ALL_FUNCS, DBG_DRIVER_ENTRY, "CleanupInit",
  256. "Completing Worker request <%x>\n", pDelayedWorkerRoutine);
  257. (*pDelayedWorkerRoutine) (pWorkerContext->Context1,
  258. pWorkerContext->Context2,
  259. pWorkerContext->Context3);
  260. PgmFreeMem ((PVOID) pWorkerContext);
  261. //
  262. // Acquire Lock again to check if we have completed all the requests
  263. //
  264. PgmLock (&PgmDynamicConfig, OldIrq);
  265. }
  266. PgmUnlock (&PgmDynamicConfig, OldIrq);
  267. }
  268. // no break -- Fall through!
  269. case (E_CLEANUP_PNP):
  270. {
  271. status = TdiDeregisterPnPHandlers (TdiClientHandle);
  272. while (!IsListEmpty (&PgmDynamicConfig.LocalInterfacesList))
  273. {
  274. pEntry = RemoveHeadList (&PgmDynamicConfig.LocalInterfacesList);
  275. pLocalInterface = CONTAINING_RECORD (pEntry, tLOCAL_INTERFACE, Linkage);
  276. while (!IsListEmpty (&pLocalInterface->Addresses))
  277. {
  278. pEntry = RemoveHeadList (&pLocalInterface->Addresses);
  279. pLocalAddress = CONTAINING_RECORD (pEntry, tADDRESS_ON_INTERFACE, Linkage);
  280. PgmFreeMem (pLocalAddress);
  281. }
  282. PgmFreeMem (pLocalInterface);
  283. }
  284. }
  285. // no break -- Fall through!
  286. case (E_CLEANUP_DEVICE):
  287. {
  288. PGM_DEREFERENCE_DEVICE (&pgPgmDevice, REF_DEV_CREATE);
  289. }
  290. // no break -- Fall through!
  291. case (E_CLEANUP_STRUCTURES):
  292. {
  293. // Nothing specific to cleanup
  294. }
  295. // no break -- Fall through!
  296. case (E_CLEANUP_REGISTRY_PARAMETERS):
  297. {
  298. if (pPgmRegistryConfig)
  299. {
  300. if (pPgmRegistryConfig->ucSenderFileLocation.Buffer)
  301. {
  302. PgmFreeMem (pPgmRegistryConfig->ucSenderFileLocation.Buffer);
  303. pPgmRegistryConfig->ucSenderFileLocation.Buffer = NULL;
  304. }
  305. PgmFreeMem (pPgmRegistryConfig);
  306. pPgmRegistryConfig = NULL;
  307. }
  308. }
  309. // no break -- Fall through!
  310. case (E_CLEANUP_DYNAMIC_CONFIG):
  311. {
  312. // Nothing specific to cleanup
  313. }
  314. // no break -- Fall through!
  315. case (E_CLEANUP_STATIC_CONFIG):
  316. {
  317. ExDeleteNPagedLookasideList(&PgmStaticConfig.DebugMessagesLookasideList);
  318. ExDeleteNPagedLookasideList(&PgmStaticConfig.TdiLookasideList);
  319. PgmFreeMem (PgmStaticConfig.RegistryPath.Buffer);
  320. }
  321. // no break -- Fall through!
  322. default:
  323. {
  324. break;
  325. }
  326. }
  327. }
  328. //----------------------------------------------------------------------------
  329. VOID
  330. PgmUnload(
  331. IN PDRIVER_OBJECT DriverObject
  332. )
  333. /*++
  334. Routine Description:
  335. This is the Pgm driver's function for Unload requests
  336. Arguments:
  337. IN DriverObject - Pointer to driver object created by the system.
  338. Return Value:
  339. None
  340. --*/
  341. {
  342. NTSTATUS status;
  343. PAGED_CODE();
  344. PgmDynamicConfig.GlobalFlags |= PGM_CONFIG_FLAG_UNLOADING;
  345. PgmLog (PGM_LOG_INFORM_STATUS, DBG_DRIVER_ENTRY, "PgmUnload",
  346. "Unloading ...\n");
  347. CleanupInit (E_CLEANUP_UNLOAD);
  348. }
  349. //----------------------------------------------------------------------------
  350. NTSTATUS
  351. PgmCreate(
  352. IN tPGM_DEVICE *pPgmDevice,
  353. IN PIRP pIrp,
  354. IN PIO_STACK_LOCATION pIrpSp
  355. )
  356. /*++
  357. Routine Description:
  358. Dispatch function for creating Pgm objects
  359. Arguments:
  360. IN pPgmDevice - Pointer to the Pgm device extension for this request.
  361. IN Irp - Pointer to I/O request packet
  362. IN IrpSp - Pointer to the current stack location in the Irp.
  363. Return Value:
  364. NTSTATUS - Final status of the create request
  365. --*/
  366. {
  367. tCONTROL_CONTEXT *pControlContext = NULL;
  368. FILE_FULL_EA_INFORMATION *ea = (PFILE_FULL_EA_INFORMATION) pIrp->AssociatedIrp.SystemBuffer;
  369. FILE_FULL_EA_INFORMATION *TargetEA;
  370. TRANSPORT_ADDRESS UNALIGNED *pTransportAddr;
  371. TA_ADDRESS *pAddress;
  372. NTSTATUS status;
  373. PAGED_CODE();
  374. //
  375. // See if this is a Control Channel open.
  376. //
  377. if (!ea)
  378. {
  379. PgmLog (PGM_LOG_INFORM_STATUS, DBG_DRIVER_ENTRY, "PGMCreate",
  380. "Opening control channel for file object %lx\n", pIrpSp->FileObject);
  381. if (pControlContext = PgmAllocMem (sizeof(tCONTROL_CONTEXT), PGM_TAG('0')))
  382. {
  383. PgmZeroMemory (pControlContext, sizeof (tCONTROL_CONTEXT));
  384. InitializeListHead (&pControlContext->Linkage);
  385. PgmInitLock (pControlContext, CONTROL_LOCK);
  386. pControlContext->Verify = PGM_VERIFY_CONTROL;
  387. PGM_REFERENCE_CONTROL (pControlContext, REF_CONTROL_CREATE, TRUE);
  388. pIrpSp->FileObject->FsContext = pControlContext;
  389. pIrpSp->FileObject->FsContext2 = (PVOID) TDI_CONTROL_CHANNEL_FILE;
  390. status = STATUS_SUCCESS;
  391. }
  392. else
  393. {
  394. status = STATUS_INSUFFICIENT_RESOURCES;
  395. }
  396. return (status);
  397. }
  398. //
  399. // See if this is a Connection Object open.
  400. //
  401. if (TargetEA = FindEA (ea, TdiConnectionContext, TDI_CONNECTION_CONTEXT_LENGTH))
  402. {
  403. status = PgmCreateConnection (pPgmDevice, pIrp, pIrpSp, TargetEA);
  404. PgmLog (PGM_LOG_INFORM_ALL_FUNCS, (DBG_DRIVER_ENTRY | DBG_CONNECT), "PGMCreate",
  405. "Open Connection, pIrp=<%x>, status=<%x>\n", pIrp, status);
  406. }
  407. //
  408. // See if this is an Address Object open.
  409. //
  410. else if (TargetEA = FindEA (ea, TdiTransportAddress, TDI_TRANSPORT_ADDRESS_LENGTH))
  411. {
  412. status = PgmCreateAddress (pPgmDevice, pIrp, pIrpSp, TargetEA);
  413. PgmLog (PGM_LOG_INFORM_ALL_FUNCS, (DBG_DRIVER_ENTRY | DBG_ADDRESS), "PGMCreate",
  414. "Open Address, pIrp=<%x>, status=<%x>\n", pIrp, status);
  415. }
  416. else
  417. {
  418. PgmLog (PGM_LOG_ERROR, DBG_DRIVER_ENTRY, "PGMCreate",
  419. "Unsupported EA!\n");
  420. status = STATUS_INVALID_EA_NAME;
  421. }
  422. return (status);
  423. }
  424. //----------------------------------------------------------------------------
  425. NTSTATUS
  426. PgmCleanup(
  427. IN tPGM_DEVICE *pPgmDevice,
  428. IN PIRP pIrp,
  429. IN PIO_STACK_LOCATION pIrpSp
  430. )
  431. /*++
  432. Routine Description:
  433. Dispatch function for cleaning-up Pgm objects
  434. Arguments:
  435. IN pPgmDevice - Pointer to the Pgm device extension for this request.
  436. IN Irp - Pointer to I/O request packet
  437. IN IrpSp - Pointer to the current stack location in the Irp.
  438. Return Value:
  439. NTSTATUS - Final status of the cleanup request
  440. --*/
  441. {
  442. NTSTATUS status = STATUS_SUCCESS;
  443. PVOID *pContext = pIrpSp->FileObject->FsContext;
  444. PAGED_CODE();
  445. switch (PtrToUlong (pIrpSp->FileObject->FsContext2))
  446. {
  447. case TDI_TRANSPORT_ADDRESS_FILE:
  448. {
  449. status = PgmCleanupAddress ((tADDRESS_CONTEXT *) pIrpSp->FileObject->FsContext, pIrp);
  450. PgmLog (PGM_LOG_INFORM_ALL_FUNCS, (DBG_DRIVER_ENTRY | DBG_ADDRESS), "PGMCleanup",
  451. "pConnect=<%x>, pIrp=<%x>, status=<%x>\n", pContext, pIrp, status);
  452. break;
  453. }
  454. case TDI_CONNECTION_FILE:
  455. {
  456. status = PgmCleanupConnection ((tCOMMON_SESSION_CONTEXT *) pIrpSp->FileObject->FsContext, pIrp);
  457. PgmLog (PGM_LOG_INFORM_ALL_FUNCS, (DBG_DRIVER_ENTRY | DBG_CONNECT), "PGMCleanup",
  458. "pConnect=<%x>, pIrp=<%x>, status=<%x>\n", pContext, pIrp, status);
  459. break;
  460. }
  461. case TDI_CONTROL_CHANNEL_FILE:
  462. {
  463. //
  464. // Nothing to Cleanup here!
  465. //
  466. PgmLog (PGM_LOG_INFORM_STATUS, DBG_DRIVER_ENTRY, "PGMCleanup",
  467. "pControl=<%x>, pIrp=<%x>, status=<%x>\n", pContext, pIrp, status);
  468. break;
  469. }
  470. default:
  471. {
  472. PgmLog (PGM_LOG_ERROR, DBG_DRIVER_ENTRY, "PGMCleanup",
  473. "pIrp=<%x>, Context=[%x:%d] ...\n",
  474. pIrp, pIrpSp->FileObject->FsContext, pIrpSp->FileObject->FsContext2);
  475. status = STATUS_INVALID_PARAMETER;
  476. break;
  477. }
  478. }
  479. return (status);
  480. }
  481. //----------------------------------------------------------------------------
  482. NTSTATUS
  483. PgmClose(
  484. IN tPGM_DEVICE *pPgmDevice,
  485. IN PIRP pIrp,
  486. IN PIO_STACK_LOCATION pIrpSp
  487. )
  488. /*++
  489. Routine Description:
  490. This routine completes the cleanup, closing handles, free'ing all
  491. memory associated with the object
  492. Arguments:
  493. IN pPgmDevice - Pointer to the Pgm device extension for this request.
  494. IN Irp - Pointer to I/O request packet
  495. IN IrpSp - Pointer to the current stack location in the Irp.
  496. Return Value:
  497. NTSTATUS - Final status of the close request
  498. --*/
  499. {
  500. NTSTATUS status = STATUS_SUCCESS;
  501. tCONTROL_CONTEXT *pControlContext = pIrpSp->FileObject->FsContext;
  502. PAGED_CODE();
  503. switch (PtrToUlong (pIrpSp->FileObject->FsContext2))
  504. {
  505. case TDI_TRANSPORT_ADDRESS_FILE:
  506. {
  507. status = PgmCloseAddress (pIrp, pIrpSp);
  508. PgmLog (PGM_LOG_INFORM_ALL_FUNCS, (DBG_DRIVER_ENTRY | DBG_ADDRESS), "PgmClose",
  509. "pAddress=<%x>, pIrp=<%x>, status=<%x>\n", pControlContext, pIrp, status);
  510. break;
  511. }
  512. case TDI_CONNECTION_FILE:
  513. {
  514. status = PgmCloseConnection (pIrp, pIrpSp);
  515. PgmLog (PGM_LOG_INFORM_ALL_FUNCS, (DBG_DRIVER_ENTRY | DBG_CONNECT), "PgmClose",
  516. "pConnect=<%x>, pIrp=<%x>, status=<%x>\n", pControlContext, pIrp, status);
  517. break;
  518. }
  519. case TDI_CONTROL_CHANNEL_FILE:
  520. {
  521. //
  522. // There is nothing special to do here so just dereference!
  523. //
  524. PgmLog (PGM_LOG_INFORM_STATUS, DBG_DRIVER_ENTRY, "PgmClose",
  525. "pControl=<%x>, pIrp=<%x>, status=<%x>\n", pIrpSp->FileObject->FsContext, pIrp, status);
  526. PGM_DEREFERENCE_CONTROL (pControlContext, REF_CONTROL_CREATE);
  527. break;
  528. }
  529. default:
  530. {
  531. PgmLog (PGM_LOG_ERROR, DBG_DRIVER_ENTRY, "PgmClose",
  532. "pIrp=<%x>, Context=[%x:%d] ...\n",
  533. pIrp, pIrpSp->FileObject->FsContext, pIrpSp->FileObject->FsContext2);
  534. status = STATUS_INVALID_PARAMETER;
  535. break;
  536. }
  537. }
  538. return (status);
  539. }
  540. //----------------------------------------------------------------------------
  541. NTSTATUS
  542. PgmDispatchInternalDeviceControl(
  543. IN tPGM_DEVICE *pPgmDevice,
  544. IN PIRP pIrp,
  545. IN PIO_STACK_LOCATION pIrpSp
  546. )
  547. /*++
  548. Routine Description:
  549. This routine primarily handles Tdi requests since we are a Tdi component
  550. Arguments:
  551. IN pPgmDevice - Pointer to the Pgm device extension for this request.
  552. IN Irp - Pointer to I/O request packet
  553. IN IrpSp - Pointer to the current stack location in the Irp.
  554. Return Value:
  555. NTSTATUS - Final status of the request
  556. --*/
  557. {
  558. NTSTATUS Status = STATUS_UNSUCCESSFUL;
  559. PgmLog (PGM_LOG_INFORM_ALL_FUNCS, DBG_DRIVER_ENTRY, "PgmDispatchInternalDeviceControl",
  560. "[%d] Context=<%x> ...\n", pIrpSp->MinorFunction, pIrpSp->FileObject->FsContext);
  561. switch (pIrpSp->MinorFunction)
  562. {
  563. case TDI_QUERY_INFORMATION:
  564. {
  565. Status = PgmQueryInformation (pPgmDevice, pIrp, pIrpSp);
  566. break;
  567. }
  568. case TDI_SET_EVENT_HANDLER:
  569. {
  570. Status = PgmSetEventHandler (pPgmDevice, pIrp, pIrpSp);
  571. break;
  572. }
  573. case TDI_ASSOCIATE_ADDRESS:
  574. {
  575. Status = PgmAssociateAddress (pPgmDevice, pIrp, pIrpSp);
  576. break;
  577. }
  578. case TDI_DISASSOCIATE_ADDRESS:
  579. {
  580. Status = PgmDisassociateAddress (pIrp, pIrpSp);
  581. break;
  582. }
  583. case TDI_CONNECT:
  584. {
  585. Status = PgmConnect (pPgmDevice, pIrp, pIrpSp);
  586. break;
  587. }
  588. case TDI_DISCONNECT:
  589. {
  590. Status = PgmDisconnect (pPgmDevice, pIrp, pIrpSp);
  591. break;
  592. }
  593. case TDI_SEND:
  594. {
  595. Status = PgmSendRequestFromClient (pPgmDevice, pIrp, pIrpSp);
  596. break;
  597. }
  598. case TDI_RECEIVE:
  599. {
  600. Status = PgmReceive (pPgmDevice, pIrp, pIrpSp);
  601. break;
  602. }
  603. /*
  604. case TDI_SEND_DATAGRAM:
  605. {
  606. Status = PgmSendDatagram (pPgmDevice, pIrp, pIrpSp);
  607. break;
  608. }
  609. */
  610. default:
  611. {
  612. PgmLog (PGM_LOG_ERROR, DBG_DRIVER_ENTRY, "PgmDispatchInternalDeviceControl",
  613. "[%x]: Context=<%x> ...\n", pIrpSp->MinorFunction, pIrpSp->FileObject->FsContext);
  614. return (STATUS_UNSUCCESSFUL);
  615. }
  616. }
  617. return (Status);
  618. }
  619. //----------------------------------------------------------------------------
  620. NTSTATUS
  621. PgmDispatchIoctls(
  622. IN tPGM_DEVICE *pPgmDevice,
  623. IN PIRP pIrp,
  624. IN PIO_STACK_LOCATION pIrpSp
  625. )
  626. /*++
  627. Routine Description:
  628. This routine handles private Ioctls into Pgm. These Ioctls are
  629. to be called only by the Pgm Winsock helper (WshPgm.dll)
  630. Arguments:
  631. IN pPgmDevice - Pointer to the Pgm device extension for this request.
  632. IN Irp - Pointer to I/O request packet
  633. IN IrpSp - Pointer to the current stack location in the Irp.
  634. Return Value:
  635. NTSTATUS - Final status of the request
  636. --*/
  637. {
  638. NTSTATUS status;
  639. switch (pIrpSp->Parameters.DeviceIoControl.IoControlCode)
  640. {
  641. case IOCTL_PGM_WSH_SET_WINDOW_SIZE_RATE:
  642. {
  643. status = PgmSetWindowSizeAndSendRate (pIrp, pIrpSp);
  644. break;
  645. }
  646. case IOCTL_PGM_WSH_QUERY_WINDOW_SIZE_RATE:
  647. {
  648. status = PgmQueryWindowSizeAndSendRate (pIrp, pIrpSp);
  649. break;
  650. }
  651. case IOCTL_PGM_WSH_SET_ADVANCE_WINDOW_RATE:
  652. {
  653. status = PgmSetWindowAdvanceRate (pIrp, pIrpSp);
  654. break;
  655. }
  656. case IOCTL_PGM_WSH_QUERY_ADVANCE_WINDOW_RATE:
  657. {
  658. status = PgmQueryWindowAdvanceRate (pIrp, pIrpSp);
  659. break;
  660. }
  661. case IOCTL_PGM_WSH_SET_LATE_JOINER_PERCENTAGE:
  662. {
  663. status = PgmSetLateJoinerPercentage (pIrp, pIrpSp);
  664. break;
  665. }
  666. case IOCTL_PGM_WSH_QUERY_LATE_JOINER_PERCENTAGE:
  667. {
  668. status = PgmQueryLateJoinerPercentage (pIrp, pIrpSp);
  669. break;
  670. }
  671. case IOCTL_PGM_WSH_SET_WINDOW_ADVANCE_METHOD:
  672. {
  673. status = PgmSetWindowAdvanceMethod (pIrp, pIrpSp);
  674. break;
  675. }
  676. case IOCTL_PGM_WSH_QUERY_WINDOW_ADVANCE_METHOD:
  677. {
  678. status = PgmQueryWindowAdvanceMethod (pIrp, pIrpSp);
  679. break;
  680. }
  681. case IOCTL_PGM_WSH_SET_NEXT_MESSAGE_BOUNDARY:
  682. {
  683. status = PgmSetNextMessageBoundary (pIrp, pIrpSp);
  684. break;
  685. }
  686. case IOCTL_PGM_WSH_SET_SEND_IF:
  687. {
  688. status = PgmSetMCastOutIf (pIrp, pIrpSp);
  689. break;
  690. }
  691. case IOCTL_PGM_WSH_ADD_RECEIVE_IF:
  692. case IOCTL_PGM_WSH_JOIN_MCAST_LEAF:
  693. {
  694. status = PgmAddMCastReceiveIf (pIrp, pIrpSp);
  695. break;
  696. }
  697. case IOCTL_PGM_WSH_DEL_RECEIVE_IF:
  698. {
  699. status = PgmDelMCastReceiveIf (pIrp, pIrpSp);
  700. break;
  701. }
  702. case IOCTL_PGM_WSH_SET_RCV_BUFF_LEN:
  703. {
  704. status = PgmSetRcvBufferLength (pIrp, pIrpSp);
  705. break;
  706. }
  707. case IOCTL_PGM_WSH_QUERY_SENDER_STATS:
  708. {
  709. status = PgmQuerySenderStats (pIrp, pIrpSp);
  710. break;
  711. }
  712. case IOCTL_PGM_WSH_QUERY_RECEIVER_STATS:
  713. {
  714. status = PgmQueryReceiverStats (pIrp, pIrpSp);
  715. break;
  716. }
  717. case IOCTL_PGM_WSH_USE_FEC:
  718. {
  719. status = PgmSetFECInfo (pIrp, pIrpSp);
  720. break;
  721. }
  722. case IOCTL_PGM_WSH_QUERY_FEC_INFO:
  723. {
  724. status = PgmQueryFecInfo (pIrp, pIrpSp);
  725. break;
  726. }
  727. case IOCTL_PGM_WSH_SET_MCAST_TTL:
  728. {
  729. status = PgmSetMCastTtl (pIrp, pIrpSp);
  730. break;
  731. }
  732. default:
  733. {
  734. PgmLog (PGM_LOG_INFORM_ALL_FUNCS, DBG_DRIVER_ENTRY, "PgmDispatchIoctls",
  735. "WARNING: Invalid Ioctl=[%x]: Context=<%x> ...\n",
  736. pIrpSp->Parameters.DeviceIoControl.IoControlCode,
  737. pIrpSp->FileObject->FsContext);
  738. return (STATUS_NOT_IMPLEMENTED);
  739. }
  740. }
  741. PgmLog (PGM_LOG_INFORM_ALL_FUNCS, DBG_DRIVER_ENTRY, "PgmDispatchIoctls",
  742. "[%d]: Context=<%x>, status=<%x>\n",
  743. pIrpSp->Parameters.DeviceIoControl.IoControlCode,
  744. pIrpSp->FileObject->FsContext, status);
  745. return (status);
  746. }
  747. //----------------------------------------------------------------------------
  748. //
  749. // Utility functions
  750. //
  751. //----------------------------------------------------------------------------
  752. FILE_FULL_EA_INFORMATION *
  753. FindEA(
  754. IN PFILE_FULL_EA_INFORMATION StartEA,
  755. IN CHAR *pTargetName,
  756. IN USHORT TargetNameLength
  757. )
  758. /*++
  759. Routine Description:
  760. Parses and extended attribute list for a given target attribute.
  761. Arguments:
  762. IN StartEA - the first extended attribute in the list.
  763. IN pTargetName - the name of the target attribute.
  764. IN TargetNameLength - the length of the name of the target attribute.
  765. Return Value:
  766. A pointer to the requested attribute or NULL if the target wasn't found.
  767. --*/
  768. {
  769. USHORT i;
  770. BOOLEAN found;
  771. FILE_FULL_EA_INFORMATION *CurrentEA;
  772. for (CurrentEA = StartEA;
  773. CurrentEA;
  774. CurrentEA = (PFILE_FULL_EA_INFORMATION) ((PUCHAR)CurrentEA + CurrentEA->NextEntryOffset))
  775. {
  776. if (strncmp (CurrentEA->EaName, pTargetName, CurrentEA->EaNameLength) == 0)
  777. {
  778. PgmLog (PGM_LOG_INFORM_ALL_FUNCS, DBG_DRIVER_ENTRY, "FindEA",
  779. "Found EA, Target=<%s>\n", pTargetName);
  780. return (CurrentEA);
  781. }
  782. if (CurrentEA->NextEntryOffset == 0)
  783. {
  784. break;
  785. }
  786. }
  787. PgmLog (PGM_LOG_INFORM_ALL_FUNCS, DBG_DRIVER_ENTRY, "FindEA",
  788. "FAILed to find EA, Target=<%s>\n", pTargetName);
  789. return (NULL);
  790. }
  791. //----------------------------------------------------------------------------
  792. VOID
  793. PgmIoComplete(
  794. IN PIRP pIrp,
  795. IN NTSTATUS Status,
  796. IN ULONG SentLength
  797. )
  798. /*++
  799. Routine Description:
  800. This routine
  801. Arguments:
  802. IN pIrp -- Pointer to I/O request packet
  803. IN Status -- the final status of the request
  804. IN SentLength -- the value to be set in the Information field
  805. Return Value:
  806. NONE
  807. --*/
  808. {
  809. pIrp->IoStatus.Status = Status;
  810. // use -1 as a flag to mean do not adjust the sent length since it is
  811. // already set
  812. if (SentLength != -1)
  813. {
  814. pIrp->IoStatus.Information = SentLength;
  815. }
  816. // set the Irps cancel routine to null or the system may bugcheck
  817. // with a bug code of CANCEL_STATE_IN_COMPLETED_IRP
  818. //
  819. // refer to IoCancelIrp() ..\ntos\io\iosubs.c
  820. //
  821. PgmCancelCancelRoutine (pIrp);
  822. PgmLog (PGM_LOG_INFORM_ALL_FUNCS, DBG_DRIVER_ENTRY, "PgmIoComplete",
  823. "pIrp=<%x>, Status=<%x>, SentLength=<%d>\n", pIrp, Status, SentLength);
  824. IoCompleteRequest (pIrp, IO_NETWORK_INCREMENT);
  825. }
  826. //----------------------------------------------------------------------------
  827. VOID
  828. CompleteDispatchIrp(
  829. IN PIRP pIrp,
  830. IN NTSTATUS status
  831. )
  832. /*++
  833. Routine Description:
  834. This function completes an IRP, and arranges for return parameters,
  835. if any, to be copied.
  836. Although somewhat a misnomer, this function is named after a similar
  837. function in the SpiderSTREAMS emulator.
  838. Arguments:
  839. IN pIrp - pointer to the IRP to complete
  840. IN status - completion status of the IRP
  841. Return Value:
  842. NONE
  843. --*/
  844. {
  845. CCHAR priboost;
  846. //
  847. // pIrp->IoStatus.Information is meaningful only for STATUS_SUCCESS
  848. //
  849. // set the Irps cancel routine to null or the system may bugcheck
  850. // with a bug code of CANCEL_STATE_IN_COMPLETED_IRP
  851. //
  852. // refer to IoCancelIrp() ..\ntos\io\iosubs.c
  853. //
  854. PgmCancelCancelRoutine (pIrp);
  855. pIrp->IoStatus.Status = status;
  856. priboost = (CCHAR) ((status == STATUS_SUCCESS) ? IO_NETWORK_INCREMENT : IO_NO_INCREMENT);
  857. PgmLog (PGM_LOG_INFORM_ALL_FUNCS, DBG_DRIVER_ENTRY, "CompleteDispatchIrp",
  858. "Completing pIrp=<%x>, status=<%x>\n", pIrp, status);
  859. IoCompleteRequest (pIrp, priboost);
  860. return;
  861. }
  862. //----------------------------------------------------------------------------
  863. NTSTATUS
  864. PgmCheckSetCancelRoutine(
  865. IN PIRP pIrp,
  866. IN PVOID CancelRoutine,
  867. IN BOOLEAN fLocked
  868. )
  869. /*++
  870. Routine Description:
  871. This Routine sets the cancel routine for an Irp.
  872. Arguments:
  873. status - a completion status for the Irp
  874. Return Value:
  875. NTSTATUS - status of the request
  876. --*/
  877. {
  878. NTSTATUS status;
  879. PGMLockHandle CancelIrql;
  880. //
  881. // Check if the irp was cancelled yet and if not, then set the
  882. // irp cancel routine.
  883. //
  884. if (!fLocked)
  885. {
  886. IoAcquireCancelSpinLock (&CancelIrql);
  887. }
  888. if (pIrp->Cancel)
  889. {
  890. pIrp->IoStatus.Status = STATUS_CANCELLED;
  891. status = STATUS_CANCELLED;
  892. }
  893. else
  894. {
  895. // setup the cancel routine
  896. IoMarkIrpPending (pIrp);
  897. IoSetCancelRoutine (pIrp, CancelRoutine);
  898. status = STATUS_SUCCESS;
  899. }
  900. if (!fLocked)
  901. {
  902. IoReleaseCancelSpinLock (CancelIrql);
  903. }
  904. return(status);
  905. }
  906. //----------------------------------------------------------------------------
  907. NTSTATUS
  908. PgmCancelCancelRoutine(
  909. IN PIRP pIrp
  910. )
  911. /*++
  912. Routine Description:
  913. This Routine sets the cancel routine for an Irp to NULL
  914. Arguments:
  915. status - a completion status for the Irp
  916. Return Value:
  917. NTSTATUS - status of the request
  918. --*/
  919. {
  920. NTSTATUS status = STATUS_SUCCESS;
  921. PGMLockHandle CancelIrql;
  922. //
  923. // Check if the irp was cancelled yet and if not, then set the
  924. // irp cancel routine.
  925. //
  926. IoAcquireCancelSpinLock (&CancelIrql);
  927. if (pIrp->Cancel)
  928. {
  929. status = STATUS_CANCELLED;
  930. }
  931. IoSetCancelRoutine (pIrp, NULL);
  932. IoReleaseCancelSpinLock (CancelIrql);
  933. return(status);
  934. }