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.

908 lines
25 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. ntdisp.c
  5. Abstract:
  6. NT Entry points and dispatch routines for NDISPROT.
  7. Environment:
  8. Kernel mode only.
  9. Revision History:
  10. arvindm 4/6/2000 Created
  11. --*/
  12. #include "precomp.h"
  13. #define __FILENUMBER 'PSID'
  14. #ifdef ALLOC_PRAGMA
  15. #pragma alloc_text(INIT, DriverEntry)
  16. #pragma alloc_text(PAGE, NdisProtUnload)
  17. #pragma alloc_text(PAGE, NdisProtOpen)
  18. #pragma alloc_text(PAGE, NdisProtClose)
  19. #pragma alloc_text(PAGE, NdisProtIoControl)
  20. #endif // ALLOC_PRAGMA
  21. //
  22. // Globals:
  23. //
  24. NDISPROT_GLOBALS Globals = {0};
  25. NTSTATUS
  26. DriverEntry(
  27. IN PDRIVER_OBJECT pDriverObject,
  28. IN PUNICODE_STRING pRegistryPath
  29. )
  30. /*++
  31. Routine Description:
  32. Called on loading. We create a device object to handle user-mode requests
  33. on, and register ourselves as a protocol with NDIS.
  34. Arguments:
  35. pDriverObject - Pointer to driver object created by system.
  36. pRegistryPath - Pointer to the Unicode name of the registry path
  37. for this driver.
  38. Return Value:
  39. NT Status code
  40. --*/
  41. {
  42. NDIS_PROTOCOL_CHARACTERISTICS protocolChar;
  43. NTSTATUS status = STATUS_SUCCESS;
  44. NDIS_STRING protoName = NDIS_STRING_CONST("NdisProt");
  45. UNICODE_STRING ntDeviceName;
  46. UNICODE_STRING win32DeviceName;
  47. BOOLEAN fSymbolicLink = FALSE;
  48. PDEVICE_OBJECT deviceObject = NULL;
  49. UNREFERENCED_PARAMETER(pRegistryPath);
  50. DEBUGP(DL_LOUD, ("DriverEntry\n"));
  51. Globals.pDriverObject = pDriverObject;
  52. NPROT_INIT_EVENT(&Globals.BindsComplete);
  53. do
  54. {
  55. //
  56. // Create our device object using which an application can
  57. // access NDIS devices.
  58. //
  59. RtlInitUnicodeString(&ntDeviceName, NT_DEVICE_NAME);
  60. #ifndef WIN9X
  61. status = IoCreateDeviceSecure(pDriverObject,
  62. 0,
  63. &ntDeviceName,
  64. FILE_DEVICE_NETWORK,
  65. FILE_DEVICE_SECURE_OPEN,
  66. FALSE,
  67. &SDDL_DEVOBJ_SYS_ALL_ADM_ALL,
  68. NULL,
  69. &deviceObject);
  70. #elif
  71. status = IoCreateDevice(pDriverObject,
  72. 0,
  73. &ntDeviceName,
  74. FILE_DEVICE_NETWORK,
  75. FILE_DEVICE_SECURE_OPEN,
  76. FALSE,
  77. &deviceObject);
  78. #endif
  79. if (!NT_SUCCESS (status))
  80. {
  81. //
  82. // Either not enough memory to create a deviceobject or another
  83. // deviceobject with the same name exits. This could happen
  84. // if you install another instance of this device.
  85. //
  86. break;
  87. }
  88. RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME);
  89. status = IoCreateSymbolicLink(&win32DeviceName, &ntDeviceName);
  90. if (!NT_SUCCESS(status))
  91. {
  92. break;
  93. }
  94. fSymbolicLink = TRUE;
  95. deviceObject->Flags |= DO_DIRECT_IO;
  96. Globals.ControlDeviceObject = deviceObject;
  97. NPROT_INIT_LIST_HEAD(&Globals.OpenList);
  98. NPROT_INIT_LOCK(&Globals.GlobalLock);
  99. //
  100. // Initialize the protocol characterstic structure
  101. //
  102. NdisZeroMemory(&protocolChar,sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
  103. protocolChar.MajorNdisVersion = 5;
  104. protocolChar.MinorNdisVersion = 0;
  105. protocolChar.Name = protoName;
  106. protocolChar.OpenAdapterCompleteHandler = NdisProtOpenAdapterComplete;
  107. protocolChar.CloseAdapterCompleteHandler = NdisProtCloseAdapterComplete;
  108. protocolChar.SendCompleteHandler = NdisProtSendComplete;
  109. protocolChar.TransferDataCompleteHandler = NdisProtTransferDataComplete;
  110. protocolChar.ResetCompleteHandler = NdisProtResetComplete;
  111. protocolChar.RequestCompleteHandler = NdisProtRequestComplete;
  112. protocolChar.ReceiveHandler = NdisProtReceive;
  113. protocolChar.ReceiveCompleteHandler = NdisProtReceiveComplete;
  114. protocolChar.StatusHandler = NdisProtStatus;
  115. protocolChar.StatusCompleteHandler = NdisProtStatusComplete;
  116. protocolChar.BindAdapterHandler = NdisProtBindAdapter;
  117. protocolChar.UnbindAdapterHandler = NdisProtUnbindAdapter;
  118. protocolChar.UnloadHandler = NULL;
  119. protocolChar.ReceivePacketHandler = NdisProtReceivePacket;
  120. protocolChar.PnPEventHandler = NdisProtPnPEventHandler;
  121. //
  122. // Register as a protocol driver
  123. //
  124. NdisRegisterProtocol(
  125. (PNDIS_STATUS)&status,
  126. &Globals.NdisProtocolHandle,
  127. &protocolChar,
  128. sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
  129. if (status != NDIS_STATUS_SUCCESS)
  130. {
  131. DEBUGP(DL_WARN, ("Failed to register protocol with NDIS\n"));
  132. status = STATUS_UNSUCCESSFUL;
  133. break;
  134. }
  135. #ifdef NDIS51
  136. Globals.PartialCancelId = NdisGeneratePartialCancelId();
  137. Globals.PartialCancelId <<= ((sizeof(PVOID) - 1) * 8);
  138. DEBUGP(DL_LOUD, ("DriverEntry: CancelId %lx\n", Globals.PartialCancelId));
  139. #endif
  140. //
  141. // Now set only the dispatch points we would like to handle.
  142. //
  143. pDriverObject->MajorFunction[IRP_MJ_CREATE] = NdisProtOpen;
  144. pDriverObject->MajorFunction[IRP_MJ_CLOSE] = NdisProtClose;
  145. pDriverObject->MajorFunction[IRP_MJ_READ] = NdisProtRead;
  146. pDriverObject->MajorFunction[IRP_MJ_WRITE] = NdisProtWrite;
  147. pDriverObject->MajorFunction[IRP_MJ_CLEANUP] = NdisProtCleanup;
  148. pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = NdisProtIoControl;
  149. pDriverObject->DriverUnload = NdisProtUnload;
  150. status = STATUS_SUCCESS;
  151. }
  152. while (FALSE);
  153. if (!NT_SUCCESS(status))
  154. {
  155. if (deviceObject)
  156. {
  157. IoDeleteDevice(deviceObject);
  158. Globals.ControlDeviceObject = NULL;
  159. }
  160. if (fSymbolicLink)
  161. {
  162. IoDeleteSymbolicLink(&win32DeviceName);
  163. }
  164. }
  165. return status;
  166. }
  167. VOID
  168. NdisProtUnload(
  169. IN PDRIVER_OBJECT DriverObject
  170. )
  171. /*++
  172. Routine Description:
  173. Free all the allocated resources, etc.
  174. Arguments:
  175. DriverObject - pointer to a driver object.
  176. Return Value:
  177. VOID.
  178. --*/
  179. {
  180. UNICODE_STRING win32DeviceName;
  181. UNREFERENCED_PARAMETER(DriverObject);
  182. DEBUGP(DL_LOUD, ("Unload Enter\n"));
  183. ndisprotUnregisterExCallBack();
  184. //
  185. // First delete the Control deviceobject and the corresponding
  186. // symbolicLink
  187. //
  188. RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME);
  189. IoDeleteSymbolicLink(&win32DeviceName);
  190. if (Globals.ControlDeviceObject)
  191. {
  192. IoDeleteDevice(Globals.ControlDeviceObject);
  193. Globals.ControlDeviceObject = NULL;
  194. }
  195. ndisprotDoProtocolUnload();
  196. #if DBG
  197. ndisprotAuditShutdown();
  198. #endif
  199. DEBUGP(DL_LOUD, ("Unload Exit\n"));
  200. }
  201. NTSTATUS
  202. NdisProtOpen(
  203. IN PDEVICE_OBJECT pDeviceObject,
  204. IN PIRP pIrp
  205. )
  206. /*++
  207. Routine Description:
  208. This is the dispatch routine for handling IRP_MJ_CREATE.
  209. We simply succeed this.
  210. Arguments:
  211. pDeviceObject - Pointer to the device object.
  212. pIrp - Pointer to the request packet.
  213. Return Value:
  214. Status is returned.
  215. --*/
  216. {
  217. PIO_STACK_LOCATION pIrpSp;
  218. NTSTATUS NtStatus = STATUS_SUCCESS;
  219. UNREFERENCED_PARAMETER(pDeviceObject);
  220. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  221. pIrpSp->FileObject->FsContext = NULL;
  222. DEBUGP(DL_INFO, ("Open: FileObject %p\n", pIrpSp->FileObject));
  223. pIrp->IoStatus.Information = 0;
  224. pIrp->IoStatus.Status = NtStatus;
  225. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  226. return NtStatus;
  227. }
  228. NTSTATUS
  229. NdisProtClose(
  230. IN PDEVICE_OBJECT pDeviceObject,
  231. IN PIRP pIrp
  232. )
  233. /*++
  234. Routine Description:
  235. This is the dispatch routine for handling IRP_MJ_CLOSE.
  236. We simply succeed this.
  237. Arguments:
  238. pDeviceObject - Pointer to the device object.
  239. pIrp - Pointer to the request packet.
  240. Return Value:
  241. Status is returned.
  242. --*/
  243. {
  244. NTSTATUS NtStatus;
  245. PIO_STACK_LOCATION pIrpSp;
  246. PNDISPROT_OPEN_CONTEXT pOpenContext;
  247. UNREFERENCED_PARAMETER(pDeviceObject);
  248. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  249. pOpenContext = pIrpSp->FileObject->FsContext;
  250. DEBUGP(DL_INFO, ("Close: FileObject %p\n",
  251. IoGetCurrentIrpStackLocation(pIrp)->FileObject));
  252. if (pOpenContext != NULL)
  253. {
  254. NPROT_STRUCT_ASSERT(pOpenContext, oc);
  255. //
  256. // Deref the endpoint
  257. //
  258. NPROT_DEREF_OPEN(pOpenContext); // Close
  259. }
  260. pIrpSp->FileObject->FsContext = NULL;
  261. NtStatus = STATUS_SUCCESS;
  262. pIrp->IoStatus.Information = 0;
  263. pIrp->IoStatus.Status = NtStatus;
  264. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  265. return NtStatus;
  266. }
  267. NTSTATUS
  268. NdisProtCleanup(
  269. IN PDEVICE_OBJECT pDeviceObject,
  270. IN PIRP pIrp
  271. )
  272. /*++
  273. Routine Description:
  274. This is the dispatch routine for handling IRP_MJ_CLEANUP.
  275. Arguments:
  276. pDeviceObject - Pointer to the device object.
  277. pIrp - Pointer to the request packet.
  278. Return Value:
  279. Status is returned.
  280. --*/
  281. {
  282. PIO_STACK_LOCATION pIrpSp;
  283. NTSTATUS NtStatus;
  284. NDIS_STATUS NdisStatus;
  285. PNDISPROT_OPEN_CONTEXT pOpenContext;
  286. ULONG PacketFilter;
  287. ULONG BytesProcessed;
  288. UNREFERENCED_PARAMETER(pDeviceObject);
  289. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  290. pOpenContext = pIrpSp->FileObject->FsContext;
  291. DEBUGP(DL_VERY_LOUD, ("Cleanup: FileObject %p, Open %p\n",
  292. pIrpSp->FileObject, pOpenContext));
  293. if (pOpenContext != NULL)
  294. {
  295. NPROT_STRUCT_ASSERT(pOpenContext, oc);
  296. //
  297. // Mark this endpoint.
  298. //
  299. NPROT_ACQUIRE_LOCK(&pOpenContext->Lock);
  300. NPROT_SET_FLAGS(pOpenContext->Flags, NUIOO_OPEN_FLAGS, NUIOO_OPEN_IDLE);
  301. pOpenContext->pFileObject = NULL;
  302. NPROT_RELEASE_LOCK(&pOpenContext->Lock);
  303. //
  304. // Set the packet filter to 0, telling NDIS that we aren't
  305. // interested in any more receives.
  306. //
  307. PacketFilter = 0;
  308. NdisStatus = ndisprotValidateOpenAndDoRequest(
  309. pOpenContext,
  310. NdisRequestSetInformation,
  311. OID_GEN_CURRENT_PACKET_FILTER,
  312. &PacketFilter,
  313. sizeof(PacketFilter),
  314. &BytesProcessed,
  315. FALSE // Don't wait for device to be powered on
  316. );
  317. if (NdisStatus != NDIS_STATUS_SUCCESS)
  318. {
  319. DEBUGP(DL_INFO, ("Cleanup: Open %p, set packet filter (%x) failed: %x\n",
  320. pOpenContext, PacketFilter, NdisStatus));
  321. //
  322. // Ignore the result. If this failed, we may continue
  323. // to get indicated receives, which will be handled
  324. // appropriately.
  325. //
  326. NdisStatus = NDIS_STATUS_SUCCESS;
  327. }
  328. //
  329. // Cancel any pending reads.
  330. //
  331. ndisprotCancelPendingReads(pOpenContext);
  332. //
  333. // Clean up the receive packet queue
  334. //
  335. ndisprotFlushReceiveQueue(pOpenContext);
  336. }
  337. NtStatus = STATUS_SUCCESS;
  338. pIrp->IoStatus.Information = 0;
  339. pIrp->IoStatus.Status = NtStatus;
  340. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  341. DEBUGP(DL_INFO, ("Cleanup: OpenContext %p\n", pOpenContext));
  342. return (NtStatus);
  343. }
  344. NTSTATUS
  345. NdisProtIoControl(
  346. IN PDEVICE_OBJECT pDeviceObject,
  347. IN PIRP pIrp
  348. )
  349. /*++
  350. Routine Description:
  351. This is the dispatch routine for handling device ioctl requests.
  352. Arguments:
  353. pDeviceObject - Pointer to the device object.
  354. pIrp - Pointer to the request packet.
  355. Return Value:
  356. Status is returned.
  357. --*/
  358. {
  359. PIO_STACK_LOCATION pIrpSp;
  360. ULONG FunctionCode;
  361. NTSTATUS NtStatus;
  362. NDIS_STATUS Status;
  363. PNDISPROT_OPEN_CONTEXT pOpenContext;
  364. ULONG BytesReturned;
  365. USHORT EthType;
  366. #if !DBG
  367. UNREFERENCED_PARAMETER(pDeviceObject);
  368. #endif
  369. DEBUGP(DL_LOUD, ("IoControl: DevObj %p, Irp %p\n", pDeviceObject, pIrp));
  370. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  371. FunctionCode = pIrpSp->Parameters.DeviceIoControl.IoControlCode;
  372. pOpenContext = (PNDISPROT_OPEN_CONTEXT)pIrpSp->FileObject->FsContext;
  373. BytesReturned = 0;
  374. switch (FunctionCode)
  375. {
  376. case IOCTL_NDISPROT_BIND_WAIT:
  377. //
  378. // Block until we have seen a NetEventBindsComplete event,
  379. // meaning that we have finished binding to all running
  380. // adapters that we are supposed to bind to.
  381. //
  382. // If we don't get this event in 5 seconds, time out.
  383. //
  384. NPROT_ASSERT((FunctionCode & 0x3) == METHOD_BUFFERED);
  385. if (NPROT_WAIT_EVENT(&Globals.BindsComplete, 5000))
  386. {
  387. NtStatus = STATUS_SUCCESS;
  388. }
  389. else
  390. {
  391. NtStatus = STATUS_TIMEOUT;
  392. }
  393. DEBUGP(DL_INFO, ("IoControl: BindWait returning %x\n", NtStatus));
  394. break;
  395. case IOCTL_NDISPROT_QUERY_BINDING:
  396. NPROT_ASSERT((FunctionCode & 0x3) == METHOD_BUFFERED);
  397. Status = ndisprotQueryBinding(
  398. pIrp->AssociatedIrp.SystemBuffer,
  399. pIrpSp->Parameters.DeviceIoControl.InputBufferLength,
  400. pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
  401. &BytesReturned
  402. );
  403. NDIS_STATUS_TO_NT_STATUS(Status, &NtStatus);
  404. DEBUGP(DL_LOUD, ("IoControl: QueryBinding returning %x\n", NtStatus));
  405. break;
  406. case IOCTL_NDISPROT_OPEN_DEVICE:
  407. NPROT_ASSERT((FunctionCode & 0x3) == METHOD_BUFFERED);
  408. if (pOpenContext != NULL)
  409. {
  410. NPROT_STRUCT_ASSERT(pOpenContext, oc);
  411. DEBUGP(DL_WARN, ("IoControl: OPEN_DEVICE: FileObj %p already"
  412. " associated with open %p\n", pIrpSp->FileObject, pOpenContext));
  413. NtStatus = STATUS_DEVICE_BUSY;
  414. break;
  415. }
  416. NtStatus = ndisprotOpenDevice(
  417. pIrp->AssociatedIrp.SystemBuffer,
  418. pIrpSp->Parameters.DeviceIoControl.InputBufferLength,
  419. pIrpSp->FileObject,
  420. &pOpenContext
  421. );
  422. if (NT_SUCCESS(NtStatus))
  423. {
  424. DEBUGP(DL_VERY_LOUD, ("IoControl OPEN_DEVICE: Open %p <-> FileObject %p\n",
  425. pOpenContext, pIrpSp->FileObject));
  426. }
  427. break;
  428. case IOCTL_NDISPROT_QUERY_OID_VALUE:
  429. NPROT_ASSERT((FunctionCode & 0x3) == METHOD_BUFFERED);
  430. if (pOpenContext != NULL)
  431. {
  432. Status = ndisprotQueryOidValue(
  433. pOpenContext,
  434. pIrp->AssociatedIrp.SystemBuffer,
  435. pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,
  436. &BytesReturned
  437. );
  438. NDIS_STATUS_TO_NT_STATUS(Status, &NtStatus);
  439. }
  440. else
  441. {
  442. NtStatus = STATUS_DEVICE_NOT_CONNECTED;
  443. }
  444. break;
  445. case IOCTL_NDISPROT_SET_OID_VALUE:
  446. NPROT_ASSERT((FunctionCode & 0x3) == METHOD_BUFFERED);
  447. if (pOpenContext != NULL)
  448. {
  449. Status = ndisprotSetOidValue(
  450. pOpenContext,
  451. pIrp->AssociatedIrp.SystemBuffer,
  452. pIrpSp->Parameters.DeviceIoControl.InputBufferLength
  453. );
  454. BytesReturned = 0;
  455. NDIS_STATUS_TO_NT_STATUS(Status, &NtStatus);
  456. }
  457. else
  458. {
  459. NtStatus = STATUS_DEVICE_NOT_CONNECTED;
  460. }
  461. break;
  462. default:
  463. NtStatus = STATUS_NOT_SUPPORTED;
  464. break;
  465. }
  466. if (NtStatus != STATUS_PENDING)
  467. {
  468. pIrp->IoStatus.Information = BytesReturned;
  469. pIrp->IoStatus.Status = NtStatus;
  470. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  471. }
  472. return NtStatus;
  473. }
  474. NTSTATUS
  475. ndisprotOpenDevice(
  476. IN PUCHAR pDeviceName,
  477. IN ULONG DeviceNameLength,
  478. IN PFILE_OBJECT pFileObject,
  479. OUT PNDISPROT_OPEN_CONTEXT * ppOpenContext
  480. )
  481. /*++
  482. Routine Description:
  483. Helper routine called to process IOCTL_NDISPROT_OPEN_DEVICE. Check if
  484. there is a binding to the specified device, and is not associated with
  485. a file object already. If so, make an association between the binding
  486. and this file object.
  487. Arguments:
  488. pDeviceName - pointer to device name string
  489. DeviceNameLength - length of above
  490. pFileObject - pointer to file object being associated with the device binding
  491. Return Value:
  492. Status is returned.
  493. --*/
  494. {
  495. PNDISPROT_OPEN_CONTEXT pOpenContext;
  496. NTSTATUS NtStatus;
  497. ULONG PacketFilter;
  498. NDIS_STATUS NdisStatus;
  499. ULONG BytesProcessed;
  500. PNDISPROT_OPEN_CONTEXT pCurrentOpenContext = NULL;
  501. pOpenContext = NULL;
  502. do
  503. {
  504. pOpenContext = ndisprotLookupDevice(
  505. pDeviceName,
  506. DeviceNameLength
  507. );
  508. if (pOpenContext == NULL)
  509. {
  510. DEBUGP(DL_WARN, ("ndisprotOpenDevice: couldn't find device\n"));
  511. NtStatus = STATUS_OBJECT_NAME_NOT_FOUND;
  512. break;
  513. }
  514. //
  515. // else ndisprotLookupDevice would have addref'ed the open.
  516. //
  517. NPROT_ACQUIRE_LOCK(&pOpenContext->Lock);
  518. if (!NPROT_TEST_FLAGS(pOpenContext->Flags, NUIOO_OPEN_FLAGS, NUIOO_OPEN_IDLE))
  519. {
  520. NPROT_ASSERT(pOpenContext->pFileObject != NULL);
  521. DEBUGP(DL_WARN, ("ndisprotOpenDevice: Open %p/%x already associated"
  522. " with another FileObject %p\n",
  523. pOpenContext, pOpenContext->Flags, pOpenContext->pFileObject));
  524. NPROT_RELEASE_LOCK(&pOpenContext->Lock);
  525. NPROT_DEREF_OPEN(pOpenContext); // ndisprotOpenDevice failure
  526. NtStatus = STATUS_DEVICE_BUSY;
  527. break;
  528. }
  529. //
  530. // This InterlockedXXX function performs an atomic operation: First it compare
  531. // pFileObject->FsContext with NULL, if they are equal, the function puts pOpenContext
  532. // into FsContext, and return NULL. Otherwise, it return pFileObject->FsContext without
  533. // changing anything.
  534. //
  535. if ((pCurrentOpenContext = InterlockedCompareExchangePointer (& (pFileObject->FsContext), pOpenContext, NULL)) != NULL)
  536. {
  537. //
  538. // pFileObject->FsContext already is used by other open
  539. //
  540. DEBUGP(DL_WARN, ("ndisprotOpenDevice: FileObject %p already associated"
  541. " with another Open %p/%x\n",
  542. pFileObject, pCurrentOpenContext, pCurrentOpenContext->Flags)); //BUG
  543. NPROT_RELEASE_LOCK(&pOpenContext->Lock);
  544. NPROT_DEREF_OPEN(pOpenContext); // ndisprotOpenDevice failure
  545. NtStatus = STATUS_INVALID_DEVICE_REQUEST;
  546. break;
  547. }
  548. pOpenContext->pFileObject = pFileObject;
  549. NPROT_SET_FLAGS(pOpenContext->Flags, NUIOO_OPEN_FLAGS, NUIOO_OPEN_ACTIVE);
  550. NPROT_RELEASE_LOCK(&pOpenContext->Lock);
  551. //
  552. // Set the packet filter now.
  553. //
  554. PacketFilter = NUIOO_PACKET_FILTER;
  555. NdisStatus = ndisprotValidateOpenAndDoRequest(
  556. pOpenContext,
  557. NdisRequestSetInformation,
  558. OID_GEN_CURRENT_PACKET_FILTER,
  559. &PacketFilter,
  560. sizeof(PacketFilter),
  561. &BytesProcessed,
  562. TRUE // Do wait for power on
  563. );
  564. if (NdisStatus != NDIS_STATUS_SUCCESS)
  565. {
  566. DEBUGP(DL_WARN, ("openDevice: Open %p: set packet filter (%x) failed: %x\n",
  567. pOpenContext, PacketFilter, NdisStatus));
  568. //
  569. // Undo all that we did above.
  570. //
  571. NPROT_ACQUIRE_LOCK(&pOpenContext->Lock);
  572. //
  573. // Need to set pFileObject->FsContext to NULL again, so others can open a device
  574. // for this file object later
  575. //
  576. pCurrentOpenContext = InterlockedCompareExchangePointer (& (pFileObject->FsContext), NULL, pOpenContext);
  577. NPROT_ASSERT(pCurrentOpenContext == pOpenContext);
  578. NPROT_SET_FLAGS(pOpenContext->Flags, NUIOO_OPEN_FLAGS, NUIOO_OPEN_IDLE);
  579. pOpenContext->pFileObject = NULL;
  580. NPROT_RELEASE_LOCK(&pOpenContext->Lock);
  581. NPROT_DEREF_OPEN(pOpenContext); // ndisprotOpenDevice failure
  582. NDIS_STATUS_TO_NT_STATUS(NdisStatus, &NtStatus);
  583. break;
  584. }
  585. *ppOpenContext = pOpenContext;
  586. NtStatus = STATUS_SUCCESS;
  587. }
  588. while (FALSE);
  589. return (NtStatus);
  590. }
  591. VOID
  592. ndisprotRefOpen(
  593. IN PNDISPROT_OPEN_CONTEXT pOpenContext
  594. )
  595. /*++
  596. Routine Description:
  597. Reference the given open context.
  598. NOTE: Can be called with or without holding the opencontext lock.
  599. Arguments:
  600. pOpenContext - pointer to open context
  601. Return Value:
  602. None
  603. --*/
  604. {
  605. NdisInterlockedIncrement((PLONG)&pOpenContext->RefCount);
  606. }
  607. VOID
  608. ndisprotDerefOpen(
  609. IN PNDISPROT_OPEN_CONTEXT pOpenContext
  610. )
  611. /*++
  612. Routine Description:
  613. Dereference the given open context. If the ref count goes to zero,
  614. free it.
  615. NOTE: called without holding the opencontext lock
  616. Arguments:
  617. pOpenContext - pointer to open context
  618. Return Value:
  619. None
  620. --*/
  621. {
  622. if (NdisInterlockedDecrement((PLONG)&pOpenContext->RefCount) == 0)
  623. {
  624. DEBUGP(DL_INFO, ("DerefOpen: Open %p, Flags %x, ref count is zero!\n",
  625. pOpenContext, pOpenContext->Flags));
  626. NPROT_ASSERT(pOpenContext->BindingHandle == NULL);
  627. NPROT_ASSERT(pOpenContext->RefCount == 0);
  628. NPROT_ASSERT(pOpenContext->pFileObject == NULL);
  629. pOpenContext->oc_sig++;
  630. //
  631. // Free it.
  632. //
  633. NPROT_FREE_MEM(pOpenContext);
  634. }
  635. }
  636. #if DBG
  637. VOID
  638. ndisprotDbgRefOpen(
  639. IN PNDISPROT_OPEN_CONTEXT pOpenContext,
  640. IN ULONG FileNumber,
  641. IN ULONG LineNumber
  642. )
  643. {
  644. DEBUGP(DL_VERY_LOUD, (" RefOpen: Open %p, old ref %d, File %c%c%c%c, line %d\n",
  645. pOpenContext,
  646. pOpenContext->RefCount,
  647. (CHAR)(FileNumber),
  648. (CHAR)(FileNumber >> 8),
  649. (CHAR)(FileNumber >> 16),
  650. (CHAR)(FileNumber >> 24),
  651. LineNumber));
  652. ndisprotRefOpen(pOpenContext);
  653. }
  654. VOID
  655. ndisprotDbgDerefOpen(
  656. IN PNDISPROT_OPEN_CONTEXT pOpenContext,
  657. IN ULONG FileNumber,
  658. IN ULONG LineNumber
  659. )
  660. {
  661. DEBUGP(DL_VERY_LOUD, ("DerefOpen: Open %p, old ref %d, File %c%c%c%c, line %d\n",
  662. pOpenContext,
  663. pOpenContext->RefCount,
  664. (CHAR)(FileNumber),
  665. (CHAR)(FileNumber >> 8),
  666. (CHAR)(FileNumber >> 16),
  667. (CHAR)(FileNumber >> 24),
  668. LineNumber));
  669. ndisprotDerefOpen(pOpenContext);
  670. }
  671. #endif // DBG