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.

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