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.

1214 lines
35 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. pxntinit.c
  5. Abstract:
  6. The module contains the NT-specific init code forthe NDIS Proxy.
  7. Author:
  8. Richard Machin (RMachin)
  9. Revision History:
  10. Who When What
  11. -------- -------- ----------------------------------------------
  12. RMachin 10-3-96 created
  13. TonyBe 02-21-99 re-work/re-write
  14. Notes:
  15. --*/
  16. #include "ntddk.h"
  17. //#include <cxport.h>
  18. #include <precomp.h>
  19. #define MODULE_NUMBER MODULE_NTINIT
  20. #define _FILENUMBER 'NITN'
  21. PPX_DEVICE_EXTENSION DeviceExtension;
  22. NPAGED_LOOKASIDE_LIST ProviderEventLookaside;
  23. NPAGED_LOOKASIDE_LIST VcLookaside;
  24. TAPI_TSP_CB TspCB;
  25. VC_TABLE VcTable;
  26. TAPI_LINE_TABLE LineTable;
  27. TSP_EVENT_LIST TspEventList;
  28. //
  29. // Local funcion prototypes
  30. //
  31. NTSTATUS
  32. DriverEntry(
  33. IN PDRIVER_OBJECT DriverObject,
  34. IN PUNICODE_STRING RegistryPath
  35. );
  36. VOID
  37. PxUnload(
  38. IN PDRIVER_OBJECT DriverObject
  39. );
  40. NTSTATUS
  41. PxIOCreate(
  42. IN PDEVICE_OBJECT DeviceObject,
  43. IN PIRP Irp
  44. );
  45. NTSTATUS
  46. PxIOClose(
  47. IN PDEVICE_OBJECT DeviceObject,
  48. IN PIRP Irp
  49. );
  50. NTSTATUS
  51. PxIODispatch(
  52. IN PDEVICE_OBJECT DeviceObject,
  53. IN PIRP Irp
  54. );
  55. NTSTATUS
  56. PxIOCleanup(
  57. IN PDEVICE_OBJECT DeviceObject,
  58. IN PIRP Irp
  59. );
  60. VOID
  61. PxCancelGetEvents(
  62. IN PDEVICE_OBJECT DeviceObject,
  63. IN PIRP Irp
  64. );
  65. //
  66. // All of the init code can be discarded.
  67. //
  68. #ifdef ALLOC_PRAGMA
  69. #pragma alloc_text(INIT, DriverEntry)
  70. #endif // ALLOC_PRAGMA
  71. //
  72. // Tapi OIDs that the Proxy supports
  73. //
  74. OID_DISPATCH TapiOids[] =
  75. {
  76. {OID_TAPI_ACCEPT,sizeof (NDIS_TAPI_ACCEPT), PxTapiAccept},
  77. {OID_TAPI_ANSWER, sizeof (NDIS_TAPI_ANSWER), PxTapiAnswer},
  78. {OID_TAPI_CLOSE, sizeof (NDIS_TAPI_CLOSE), PxTapiClose},
  79. {OID_TAPI_CLOSE_CALL, sizeof (NDIS_TAPI_CLOSE_CALL), PxTapiCloseCall},
  80. {OID_TAPI_CONDITIONAL_MEDIA_DETECTION, sizeof (NDIS_TAPI_CONDITIONAL_MEDIA_DETECTION), PxTapiConditionalMediaDetection},
  81. {OID_TAPI_CONFIG_DIALOG, sizeof (NDIS_TAPI_CONFIG_DIALOG), PxTapiConfigDialog},
  82. {OID_TAPI_DEV_SPECIFIC, sizeof (NDIS_TAPI_DEV_SPECIFIC), PxTapiDevSpecific},
  83. {OID_TAPI_DIAL, sizeof (NDIS_TAPI_DIAL), PxTapiDial},
  84. {OID_TAPI_DROP, sizeof (NDIS_TAPI_DROP), PxTapiDrop},
  85. {OID_TAPI_GET_ADDRESS_CAPS, sizeof (NDIS_TAPI_GET_ADDRESS_CAPS), PxTapiGetAddressCaps},
  86. {OID_TAPI_GET_ADDRESS_ID, sizeof (NDIS_TAPI_GET_ADDRESS_ID), PxTapiGetAddressID},
  87. {OID_TAPI_GET_ADDRESS_STATUS, sizeof (NDIS_TAPI_GET_ADDRESS_STATUS), PxTapiGetAddressStatus},
  88. {OID_TAPI_GET_CALL_ADDRESS_ID, sizeof (NDIS_TAPI_GET_CALL_ADDRESS_ID), PxTapiGetCallAddressID},
  89. {OID_TAPI_GET_CALL_INFO, sizeof (NDIS_TAPI_GET_CALL_INFO), PxTapiGetCallInfo},
  90. {OID_TAPI_GET_CALL_STATUS, sizeof (NDIS_TAPI_GET_CALL_STATUS), PxTapiGetCallStatus},
  91. {OID_TAPI_GET_DEV_CAPS, sizeof (NDIS_TAPI_GET_DEV_CAPS), PxTapiGetDevCaps},
  92. {OID_TAPI_GET_DEV_CONFIG, sizeof (NDIS_TAPI_GET_DEV_CONFIG), PxTapiGetDevConfig},
  93. {OID_TAPI_GET_EXTENSION_ID, sizeof (NDIS_TAPI_GET_EXTENSION_ID), PxTapiGetExtensionID},
  94. {OID_TAPI_GET_ID, sizeof (NDIS_TAPI_GET_ID), PxTapiLineGetID},
  95. {OID_TAPI_GET_LINE_DEV_STATUS, sizeof (NDIS_TAPI_GET_LINE_DEV_STATUS), PxTapiGetLineDevStatus},
  96. {OID_TAPI_MAKE_CALL, sizeof (NDIS_TAPI_MAKE_CALL), PxTapiMakeCall},
  97. {OID_TAPI_NEGOTIATE_EXT_VERSION, sizeof (NDIS_TAPI_NEGOTIATE_EXT_VERSION), PxTapiNegotiateExtVersion},
  98. {OID_TAPI_OPEN, sizeof (NDIS_TAPI_OPEN) + sizeof(NDISTAPI_OPENDATA), PxTapiOpen},
  99. {OID_TAPI_PROVIDER_INITIALIZE, sizeof (NDIS_TAPI_PROVIDER_INITIALIZE), PxTapiProviderInit},
  100. {OID_TAPI_PROVIDER_SHUTDOWN, sizeof (NDIS_TAPI_PROVIDER_SHUTDOWN), PxTapiProviderShutdown},
  101. {OID_TAPI_SECURE_CALL, sizeof (NDIS_TAPI_SECURE_CALL), PxTapiSecureCall},
  102. {OID_TAPI_SELECT_EXT_VERSION, sizeof (NDIS_TAPI_SELECT_EXT_VERSION), PxTapiSelectExtVersion},
  103. {OID_TAPI_SEND_USER_USER_INFO, sizeof (NDIS_TAPI_SEND_USER_USER_INFO), PxTapiSendUserUserInfo},
  104. {OID_TAPI_SET_APP_SPECIFIC, sizeof (NDIS_TAPI_SET_APP_SPECIFIC), PxTapiSetAppSpecific},
  105. {OID_TAPI_SET_CALL_PARAMS, sizeof (NDIS_TAPI_SET_CALL_PARAMS), PxTapiSetCallParams},
  106. {OID_TAPI_SET_DEFAULT_MEDIA_DETECTION, sizeof (NDIS_TAPI_SET_DEFAULT_MEDIA_DETECTION), PxTapiSetDefaultMediaDetection},
  107. {OID_TAPI_SET_DEV_CONFIG, sizeof (NDIS_TAPI_SET_DEV_CONFIG), PxTapiSetDevConfig},
  108. {OID_TAPI_SET_MEDIA_MODE, sizeof (NDIS_TAPI_SET_MEDIA_MODE), PxTapiSetMediaMode},
  109. {OID_TAPI_SET_STATUS_MESSAGES, sizeof (NDIS_TAPI_SET_STATUS_MESSAGES), PxTapiSetStatusMessages},
  110. {OID_TAPI_GATHER_DIGITS, sizeof (NDIS_TAPI_GATHER_DIGITS), PxTapiGatherDigits},
  111. {OID_TAPI_MONITOR_DIGITS, sizeof (NDIS_TAPI_MONITOR_DIGITS), PxTapiMonitorDigits}
  112. };
  113. //
  114. // TAPI OIDs that do not map to NDIS5, and are passed-through to CallManagers:
  115. //
  116. #define MAX_TAPI_SUPPORTED_OIDS (sizeof(TapiOids)/sizeof(OID_DISPATCH))
  117. NTSTATUS
  118. DriverEntry(
  119. IN PDRIVER_OBJECT DriverObject,
  120. IN PUNICODE_STRING RegistryPath
  121. )
  122. /*++
  123. Routine Description:
  124. Initialization routine for the NDIS Proxy.
  125. Arguments:
  126. DriverObject - Pointer to the driver object created by the system.
  127. RegistryPath - Points to global registry path
  128. Return Value:
  129. The final status from the initialization operation.
  130. --*/
  131. {
  132. NTSTATUS Status;
  133. UNICODE_STRING deviceName;
  134. USHORT i;
  135. UINT initStatus;
  136. PDEVICE_OBJECT DeviceObject;
  137. ULONG SizeNeeded;
  138. PXDEBUGP(PXD_INFO, PXM_INIT, ("NDIS Proxy DriverEntry; built %s, %s\n", __DATE__, __TIME__));
  139. ExInitializeNPagedLookasideList(&ProviderEventLookaside,
  140. NULL,
  141. NULL,
  142. 0,
  143. sizeof(PROVIDER_EVENT),
  144. PX_EVENT_TAG,
  145. 0);
  146. ExInitializeNPagedLookasideList(&VcLookaside,
  147. NULL,
  148. NULL,
  149. 0,
  150. sizeof(PX_VC),
  151. PX_VC_TAG,
  152. 0);
  153. NdisZeroMemory(&TspCB, sizeof(TspCB));
  154. NdisZeroMemory(&TspEventList, sizeof(TspEventList));
  155. NdisZeroMemory(&VcTable, sizeof(VcTable));
  156. NdisZeroMemory(&LineTable, sizeof(LineTable));
  157. //
  158. // Create the device objects. IoCreateDevice zeroes the memory
  159. // occupied by the object.
  160. //
  161. RtlInitUnicodeString(&deviceName, DD_PROXY_DEVICE_NAME);
  162. Status = IoCreateDevice(DriverObject,
  163. sizeof (PX_DEVICE_EXTENSION),
  164. &deviceName,
  165. FILE_DEVICE_NETWORK,
  166. 0,
  167. FALSE,
  168. &DeviceObject);
  169. if(!NT_SUCCESS(Status)) {
  170. return STATUS_UNSUCCESSFUL;
  171. }
  172. //
  173. // Initialize the driver object
  174. //
  175. DeviceExtension =
  176. (PPX_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
  177. NdisZeroMemory(DeviceExtension,
  178. sizeof (PX_DEVICE_EXTENSION));
  179. DeviceExtension->pDriverObject = DriverObject;
  180. NdisAllocateSpinLock(&DeviceExtension->Lock);
  181. InitializeListHead(&DeviceExtension->AdapterList);
  182. GetRegistryParameters (RegistryPath);
  183. NdisAllocateSpinLock(&TspCB.Lock);
  184. TspCB.Status = NDISTAPI_STATUS_DISCONNECTED;
  185. TspCB.NdisTapiNumDevices = 0;
  186. TspCB.htCall = 1;
  187. InitializeListHead(&TspCB.ProviderList);
  188. NdisAllocateSpinLock(&TspEventList.Lock);
  189. InitializeListHead(&TspEventList.List);
  190. //
  191. // Intialize the VcTable
  192. //
  193. NdisInitializeReadWriteLock(&VcTable.Lock);
  194. VcTable.Size = VC_TABLE_SIZE;
  195. InitializeListHead(&VcTable.List);
  196. SizeNeeded = (VC_TABLE_SIZE * sizeof(PPX_VC));
  197. PxAllocMem(VcTable.Table, SizeNeeded, PX_VCTABLE_TAG);
  198. if (VcTable.Table == NULL) {
  199. PXDEBUGP(PXD_WARNING, PXM_INIT, ("DriverEntry: ExAllocPool for VcTable\n"));
  200. Status = STATUS_UNSUCCESSFUL;
  201. goto DriverEntry_err;
  202. }
  203. NdisZeroMemory(VcTable.Table, SizeNeeded);
  204. //
  205. // Initialize the LineTable
  206. //
  207. NdisInitializeReadWriteLock(&LineTable.Lock);
  208. LineTable.Size = LINE_TABLE_SIZE;
  209. SizeNeeded = (LINE_TABLE_SIZE * sizeof(PPX_TAPI_LINE));
  210. PxAllocMem(LineTable.Table, SizeNeeded, PX_LINETABLE_TAG);
  211. if (LineTable.Table == NULL) {
  212. PXDEBUGP(PXD_WARNING, PXM_INIT, ("DriverEntry: ExAllocPool for VcTable\n"));
  213. Status = STATUS_UNSUCCESSFUL;
  214. goto DriverEntry_err;
  215. }
  216. NdisZeroMemory(LineTable.Table, SizeNeeded);
  217. DeviceExtension->pDeviceObject = DeviceObject;
  218. DriverObject->DriverUnload = PxUnload;
  219. DriverObject->FastIoDispatch = NULL;
  220. DriverObject->MajorFunction[IRP_MJ_CREATE] = PxIOCreate;
  221. DriverObject->MajorFunction[IRP_MJ_CLOSE] = PxIOClose;
  222. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PxIODispatch;
  223. DriverObject->MajorFunction[IRP_MJ_CLEANUP] = PxIOCleanup;
  224. //
  225. // Intialize the device objects.
  226. //
  227. DeviceObject->Flags |= DO_DIRECT_IO;
  228. DeviceExtension->pDeviceObject = DeviceObject;
  229. //
  230. // Finally, initialize the stack.
  231. //
  232. initStatus = InitNDISProxy();
  233. if (initStatus == TRUE) {
  234. return(STATUS_SUCCESS);
  235. }
  236. DriverEntry_err:
  237. Status = STATUS_UNSUCCESSFUL;
  238. while (!(IsListEmpty(&TspEventList.List))) {
  239. PPROVIDER_EVENT ProviderEvent;
  240. ProviderEvent = (PPROVIDER_EVENT)
  241. RemoveHeadList(&TspEventList.List);
  242. ExFreeToNPagedLookasideList(&ProviderEventLookaside, ProviderEvent);
  243. }
  244. if (VcTable.Table != NULL) {
  245. PxFreeMem(VcTable.Table);
  246. VcTable.Table = NULL;
  247. }
  248. if (LineTable.Table != NULL) {
  249. PxFreeMem(LineTable.Table);
  250. LineTable.Table = NULL;
  251. }
  252. if(DeviceObject != NULL) {
  253. IoDeleteDevice(DeviceObject);
  254. DeviceExtension->pDeviceObject = NULL;
  255. }
  256. ExDeleteNPagedLookasideList(&ProviderEventLookaside);
  257. ExDeleteNPagedLookasideList(&VcLookaside);
  258. return(Status);
  259. }
  260. VOID
  261. PxUnload(
  262. IN PDRIVER_OBJECT DriverObject
  263. )
  264. /*++
  265. Routine Description:
  266. Free all the allocated resources, etc.
  267. Arguments:
  268. DriverObject - pointer to a driver object
  269. Return Value:
  270. --*/
  271. {
  272. PXDEBUGP(PXD_LOUD, PXM_INIT, ("PxUnload: enter\n"));
  273. //
  274. // Call our unload handler
  275. //
  276. PxCoUnloadProtocol();
  277. NdisAcquireSpinLock(&TspEventList.Lock);
  278. while (!(IsListEmpty(&TspEventList.List))) {
  279. PPROVIDER_EVENT ProviderEvent;
  280. ProviderEvent = (PPROVIDER_EVENT)
  281. RemoveHeadList(&TspEventList.List);
  282. ExFreeToNPagedLookasideList(&ProviderEventLookaside, ProviderEvent);
  283. }
  284. NdisReleaseSpinLock(&TspEventList.Lock);
  285. ExDeleteNPagedLookasideList(&ProviderEventLookaside);
  286. ExDeleteNPagedLookasideList(&VcLookaside);
  287. if (DeviceExtension->pDeviceObject != NULL) {
  288. IoDeleteDevice (DeviceExtension->pDeviceObject);
  289. }
  290. //
  291. // Free Vc table memory
  292. //
  293. ASSERT(VcTable.Count == 0);
  294. PxFreeMem(VcTable.Table);
  295. //
  296. // Free the allocated tapi resources
  297. // (TapiProviders, TapiLines, TapiAddrs)
  298. //
  299. NdisAcquireSpinLock(&TspCB.Lock);
  300. while (!IsListEmpty(&TspCB.ProviderList)) {
  301. PPX_TAPI_PROVIDER tp;
  302. tp = (PPX_TAPI_PROVIDER)
  303. RemoveHeadList(&TspCB.ProviderList);
  304. NdisReleaseSpinLock(&TspCB.Lock);
  305. FreeTapiProvider(tp);
  306. NdisAcquireSpinLock(&TspCB.Lock);
  307. }
  308. NdisReleaseSpinLock(&TspCB.Lock);
  309. NdisFreeSpinLock(&TspCB.Lock);
  310. //
  311. // Free the line table
  312. //
  313. ASSERT(LineTable.Count == 0);
  314. PxFreeMem(LineTable.Table);
  315. NdisFreeSpinLock(&(DeviceExtension->Lock));
  316. PXDEBUGP (PXD_LOUD, PXM_INIT, ("PxUnload: exit\n"));
  317. }
  318. NTSTATUS
  319. PxIOCreate(
  320. IN PDEVICE_OBJECT DeviceObject,
  321. IN PIRP Irp
  322. )
  323. {
  324. PXDEBUGP(PXD_LOUD, PXM_INIT, ("IRP_MJ_CREATE, Irp=%p", Irp));
  325. Irp->IoStatus.Status = STATUS_SUCCESS;
  326. Irp->IoStatus.Information = 0;
  327. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  328. return (STATUS_SUCCESS);
  329. }
  330. NTSTATUS
  331. PxIOClose(
  332. IN PDEVICE_OBJECT DeviceObject,
  333. IN PIRP Irp
  334. )
  335. {
  336. PPX_TAPI_PROVIDER Provider;
  337. PXDEBUGP(PXD_LOUD, PXM_INIT, ("IRP_MJ_CLOSE, Entry\n"));
  338. Irp->IoStatus.Status = STATUS_SUCCESS;
  339. Irp->IoStatus.Information = 0;
  340. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  341. return (STATUS_SUCCESS);
  342. }
  343. NTSTATUS
  344. PxIODispatch(
  345. IN PDEVICE_OBJECT DeviceObject,
  346. IN PIRP Irp
  347. )
  348. /*++
  349. Routine Description:
  350. This is the generic dispatch routine for the Proxy. Irps come from the
  351. usermode TSP component.
  352. Arguments:
  353. DeviceObject - Pointer to device object for target device
  354. Irp - Pointer to I/O request packet
  355. Return Value:
  356. NTSTATUS -- Indicates whether the request was successfully queued.
  357. --*/
  358. {
  359. PVOID ioBuffer;
  360. ULONG inputBufferLength;
  361. ULONG outputBufferLength;
  362. ULONG ioControlCode;
  363. ULONG InfoSize = 0;
  364. NTSTATUS ntStatus = STATUS_PENDING;
  365. PIO_STACK_LOCATION IrpStack;
  366. ULONG RequestId;
  367. //
  368. // Get a pointer to the current location in the Irp. This is where
  369. // the function codes and parameters are located.
  370. //
  371. IrpStack = IoGetCurrentIrpStackLocation (Irp);
  372. //
  373. // Get the pointer to the input/output buffer and its length
  374. //
  375. ioBuffer =
  376. Irp->AssociatedIrp.SystemBuffer;
  377. inputBufferLength =
  378. IrpStack->Parameters.DeviceIoControl.InputBufferLength;
  379. outputBufferLength =
  380. IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
  381. if ((IrpStack->MajorFunction != IRP_MJ_DEVICE_CONTROL) ||
  382. (DeviceObject != DeviceExtension->pDeviceObject)) {
  383. Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  384. Irp->IoStatus.Information = 0;
  385. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  386. return (STATUS_NOT_SUPPORTED);
  387. }
  388. ioControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
  389. // PxAssert((ioControlCode & (METHOD_BUFFERED | METHOD_IN_DIRECT | METHOD_OUT_DIRECT | METHOD_NEITHER)) == METHOD_BUFFERED);
  390. switch(ioControlCode)
  391. {
  392. case IOCTL_NDISTAPI_CONNECT:
  393. {
  394. PPX_TAPI_PROVIDER Provider;
  395. PXDEBUGP(PXD_INFO, PXM_INIT, ("IOCTL_NDISTAPI_CONNECT, Irp=%p\n", Irp));
  396. //
  397. // Someone's connecting. Make sure they passed us a valid
  398. // info buffer.
  399. //
  400. if ((inputBufferLength < 2*sizeof(ULONG)) ||
  401. (outputBufferLength < sizeof(ULONG))) {
  402. PXDEBUGP (PXD_WARNING, PXM_INIT, ("IOCTL_NDISTAPI_CONNECT: buffer too small\n"));
  403. ntStatus = STATUS_BUFFER_TOO_SMALL;
  404. break;
  405. }
  406. NdisAcquireSpinLock(&TspCB.Lock);
  407. //
  408. // Return the number of line devs
  409. //
  410. PxAssert(outputBufferLength >= sizeof(ULONG));
  411. *((ULONG *) ioBuffer)= TspCB.NdisTapiNumDevices;
  412. TspCB.Status = NDISTAPI_STATUS_CONNECTED;
  413. Provider = (PPX_TAPI_PROVIDER)TspCB.ProviderList.Flink;
  414. while ((PVOID)Provider != (PVOID)&TspCB.ProviderList) {
  415. NdisAcquireSpinLock(&Provider->Lock);
  416. if (Provider->Status == PROVIDER_STATUS_ONLINE) {
  417. MarkProviderConnected(Provider);
  418. }
  419. NdisReleaseSpinLock(&Provider->Lock);
  420. Provider = (PPX_TAPI_PROVIDER)Provider->Linkage.Flink;
  421. }
  422. ntStatus = STATUS_SUCCESS;
  423. InfoSize = sizeof (ULONG);
  424. NdisReleaseSpinLock(&TspCB.Lock);
  425. break;
  426. }
  427. case IOCTL_NDISTAPI_DISCONNECT:
  428. {
  429. PPX_TAPI_PROVIDER Provider;
  430. NdisAcquireSpinLock(&TspCB.Lock);
  431. //
  432. // If no one is talking then set state to
  433. // disconnected.
  434. //
  435. TspCB.Status = NDISTAPI_STATUS_DISCONNECTING;
  436. Provider = (PPX_TAPI_PROVIDER)TspCB.ProviderList.Flink;
  437. while ((PVOID)Provider != (PVOID)&TspCB.ProviderList) {
  438. NdisAcquireSpinLock(&Provider->Lock);
  439. if (Provider->Status == PROVIDER_STATUS_ONLINE) {
  440. MarkProviderDisconnected(Provider);
  441. }
  442. NdisReleaseSpinLock(&Provider->Lock);
  443. Provider =
  444. (PPX_TAPI_PROVIDER)Provider->Linkage.Flink;
  445. }
  446. NdisReleaseSpinLock (&TspCB.Lock);
  447. ntStatus = STATUS_SUCCESS;
  448. InfoSize = 0;
  449. break;
  450. }
  451. case IOCTL_NDISTAPI_QUERY_INFO:
  452. case IOCTL_NDISTAPI_SET_INFO:
  453. {
  454. ULONG targetDeviceID;
  455. NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS;
  456. NDIS_HANDLE providerHandle = NULL;
  457. PNDISTAPI_REQUEST ndisTapiRequest;
  458. KIRQL oldIrql;
  459. KIRQL cancelIrql;
  460. PPX_TAPI_LINE TapiLine = NULL;
  461. INT n=0;
  462. PKDEVICE_QUEUE_ENTRY packet;
  463. //
  464. // All the following OIDs come in here as query/set IOCTls:
  465. //Init
  466. //Accept
  467. //Answer
  468. //Close
  469. //CloseCall
  470. //ConditionalMediaDetection
  471. //ConfigDialog
  472. //DevSpecific
  473. //Dial
  474. //Drop
  475. //GetAddressCaps
  476. //GetAddressID
  477. //GetAddressStatus
  478. //GetCallAddressID
  479. //GetCallInfo
  480. //GetCallStatus
  481. //GetDevCaps
  482. //GetDevConfig
  483. //GetExtensionID
  484. //GetID
  485. //GetLineDevStatus
  486. //MakeCall
  487. //NegotiateExtVersion
  488. //Open
  489. //ProviderInitialize
  490. //ProviderShutdown
  491. //SecureCall
  492. //SelectExtVersion
  493. //SendUserUserInfo
  494. //SetAppSpecific
  495. //SetCallParams
  496. //SetDefaultMediaDetection
  497. //SetDevConfig
  498. //SetMediaMode
  499. //SetStatusMessages
  500. //
  501. //
  502. // Verify we're connected, then check the device ID of the
  503. // incoming request against our list of online devices
  504. //
  505. //
  506. // Something other then pending was returned so complete
  507. // the irp
  508. //
  509. if (inputBufferLength < sizeof (NDISTAPI_REQUEST) ||
  510. outputBufferLength < sizeof(NDISTAPI_REQUEST)) {
  511. PXDEBUGP(PXD_WARNING, PXM_INIT, ("IOCTL_SET/QUERY: Invalid BufferLength! len %d needed %d\n",
  512. inputBufferLength, sizeof(NDISTAPI_REQUEST)));
  513. ntStatus = STATUS_INFO_LENGTH_MISMATCH;
  514. break;
  515. }
  516. ndisTapiRequest = ioBuffer;
  517. targetDeviceID = ndisTapiRequest->ulDeviceID;
  518. InfoSize = sizeof(NDISTAPI_REQUEST);
  519. PXDEBUGP(PXD_LOUD, PXM_INIT, (
  520. "NdisTapiRequest: Irp: %p Oid: %x, devID: %d, reqID: %x\n",
  521. Irp,
  522. ndisTapiRequest->Oid,
  523. ndisTapiRequest->ulDeviceID,
  524. *((ULONG *)ndisTapiRequest->Data)));
  525. n = ndisTapiRequest->Oid - OID_TAPI_ACCEPT;
  526. if (n > MAX_TAPI_SUPPORTED_OIDS) {
  527. PXDEBUGP(PXD_WARNING,PXM_INIT, ("IOCTL_SET/QUERY: Invalid OID %x index %d\n",
  528. ndisTapiRequest->Oid, n));
  529. ndisTapiRequest->ulReturnValue = NDIS_STATUS_TAPI_INVALPARAM;
  530. ntStatus = STATUS_SUCCESS;
  531. break; // out of switch
  532. }
  533. //
  534. // defensive check that data buffer size is not bad
  535. //
  536. if (ndisTapiRequest->ulDataSize < TapiOids[n].SizeofStruct) {
  537. PXDEBUGP(PXD_WARNING, PXM_INIT, ("IOCTL_SET/QUERY: Invalid BufferLength2! len %d needed %d\n",
  538. ndisTapiRequest->ulDataSize, TapiOids[n].SizeofStruct));
  539. ndisTapiRequest->ulReturnValue = NDIS_STATUS_TAPI_STRUCTURETOOSMALL;
  540. ntStatus = STATUS_SUCCESS;
  541. break;
  542. }
  543. //
  544. // Make sure the IRP contained sufficient data.
  545. //
  546. if (ndisTapiRequest->ulDataSize >
  547. inputBufferLength - FIELD_OFFSET(NDISTAPI_REQUEST, Data[0])) {
  548. PXDEBUGP(PXD_WARNING, PXM_INIT, ("IOCTL_SET/QUERY: Invalid BufferLength3! len %d needed %d\n",
  549. ndisTapiRequest->ulDataSize, inputBufferLength - FIELD_OFFSET(NDISTAPI_REQUEST, Data[0])));
  550. ndisTapiRequest->ulReturnValue = NDIS_STATUS_TAPI_STRUCTURETOOSMALL;
  551. ntStatus = STATUS_SUCCESS;
  552. break;
  553. }
  554. NdisAcquireSpinLock (&TspCB.Lock);
  555. //
  556. // Are we initialized with TAPI?
  557. //
  558. if (TspCB.Status != NDISTAPI_STATUS_CONNECTED) {
  559. PXDEBUGP(PXD_WARNING, PXM_INIT, ("TAPI not connected, returning err\n"));
  560. NdisReleaseSpinLock(&TspCB.Lock);
  561. ndisTapiRequest->ulReturnValue = NDISTAPIERR_UNINITIALIZED;
  562. ntStatus = STATUS_SUCCESS;
  563. break;
  564. }
  565. //
  566. // Get a unique ID for this request -- value between 1 and fffffffe.
  567. // (Can't use the TAPI ID in case it's spoofed)
  568. //
  569. if (++TspCB.ulUniqueId > 0xfffffffe) {
  570. TspCB.ulUniqueId = 0x80000001;
  571. }
  572. RequestId =
  573. ndisTapiRequest->ulUniqueRequestId =
  574. TspCB.ulUniqueId;
  575. ndisTapiRequest->Irp = Irp;
  576. NdisReleaseSpinLock (&TspCB.Lock);
  577. //
  578. // Mark the TAPI request pending
  579. //
  580. IoMarkIrpPending(Irp);
  581. ntStatus = STATUS_PENDING;
  582. //
  583. // Dispatch the request
  584. //
  585. ndisStatus =
  586. (*TapiOids[n].FuncPtr)(ndisTapiRequest);
  587. if (ndisStatus == NDIS_STATUS_PENDING) {
  588. PXDEBUGP (PXD_LOUD, PXM_INIT, ("IOCTL_TAPI_SET/QUERY_INFO: reqProc returning PENDING\n" ));
  589. return (STATUS_PENDING);
  590. }
  591. //
  592. // Something other then pending was returned so complete
  593. // the irp
  594. //
  595. InfoSize = MIN (outputBufferLength,
  596. sizeof(NDISTAPI_REQUEST)+ndisTapiRequest->ulDataSize);
  597. //
  598. // Set the TAPI return status
  599. //
  600. ndisTapiRequest->ulReturnValue = ndisStatus;
  601. IoSetCancelRoutine(Irp, NULL);
  602. ntStatus = STATUS_SUCCESS;
  603. break;
  604. }
  605. case IOCTL_NDISTAPI_GET_LINE_EVENTS:
  606. {
  607. KIRQL oldIrql;
  608. KIRQL cancelIrql;
  609. PNDISTAPI_EVENT_DATA ndisTapiEventData = ioBuffer;
  610. PXDEBUGP(PXD_VERY_LOUD, PXM_INIT, ("IOCTL_NDISTAPI_GET_LINE_EVENTS\n"));
  611. //
  612. // Defensive check that the input buffer is at least
  613. // the size of the request,
  614. // and that we can move at least one event
  615. //
  616. if (inputBufferLength < sizeof (NDISTAPI_EVENT_DATA)) {
  617. ntStatus = STATUS_BUFFER_TOO_SMALL;
  618. InfoSize = sizeof (ULONG);
  619. PXDEBUGP(PXD_WARNING, PXM_INIT, ("IOCTL_NDISTAPI_GET_LINE_EVENTS: buffer too small\n"));
  620. break;
  621. }
  622. if (outputBufferLength - sizeof(NDISTAPI_EVENT_DATA) + 1 < ndisTapiEventData->ulTotalSize) {
  623. ntStatus = STATUS_BUFFER_TOO_SMALL;
  624. InfoSize = sizeof (ULONG);
  625. PXDEBUGP(PXD_WARNING, PXM_INIT, ("IOCTL_NDISTAPI_GET_LINE_EVENTS: buffer too small\n"));
  626. break;
  627. }
  628. //
  629. // Sync event buf access by acquiring EventSpinLock
  630. //
  631. NdisAcquireSpinLock(&TspEventList.Lock);
  632. //
  633. // Is there any data available?
  634. //
  635. if (TspEventList.Count != 0) {
  636. //
  637. // There's line event data queued in our ring buffer. Grab as
  638. // much as we can & complete the request.
  639. //
  640. PXDEBUGP(PXD_VERY_LOUD, PXM_INIT,
  641. ("IOCTL_NDISTAPI_GET_LINE_EVENTS: event count = x%x, IoBuffer->TotalSize = %x\n",
  642. TspEventList.Count, ndisTapiEventData->ulTotalSize));
  643. ndisTapiEventData->ulUsedSize =
  644. GetLineEvents(ndisTapiEventData->Data,
  645. ndisTapiEventData->ulTotalSize);
  646. ntStatus = STATUS_SUCCESS;
  647. InfoSize =
  648. MIN (outputBufferLength, ((ndisTapiEventData->ulUsedSize) + sizeof(NDISTAPI_EVENT_DATA) - 1));
  649. } else {
  650. PXDEBUGP(PXD_VERY_LOUD, PXM_INIT, ("IOCTL_NDISTAPI_GET_LINE_EVENTS: no events in queue\n"));
  651. //
  652. // Hold the request pending. It remains in the cancelable
  653. // state. When new line event input is received or generated (i.e.
  654. // LINEDEVSTATE_REINIT) the data will get copied & the
  655. // request completed.
  656. //
  657. if (NULL == TspEventList.RequestIrp) {
  658. IoSetCancelRoutine (Irp, PxCancelGetEvents);
  659. IoMarkIrpPending (Irp);
  660. Irp->IoStatus.Status = STATUS_PENDING;
  661. Irp->IoStatus.Information = 0;
  662. TspEventList.RequestIrp = Irp;
  663. ntStatus = STATUS_PENDING;
  664. } else {
  665. ntStatus = STATUS_UNSUCCESSFUL;
  666. InfoSize = sizeof (ULONG);
  667. }
  668. }
  669. NdisReleaseSpinLock(&TspEventList.Lock);
  670. break;
  671. }
  672. case IOCTL_NDISTAPI_SET_DEVICEID_BASE:
  673. {
  674. ULONG BaseId;
  675. PXDEBUGP(PXD_INFO, PXM_INIT, ("IOCTL_NDISTAPI_SET_DEVICEID_BASE, Irp=x%x, inputBufLen = %x\n", Irp, inputBufferLength ));
  676. //
  677. // Someone's connecting. Make sure they passed us a valid
  678. // info buffer
  679. //
  680. if ((inputBufferLength < sizeof(ULONG))) {
  681. PXDEBUGP (PXD_WARNING, PXM_INIT, ("IOCTL_NDISTAPI_SET_DEVICEID_BASE: buffer too small\n"));
  682. ntStatus = STATUS_BUFFER_TOO_SMALL;
  683. break;
  684. }
  685. NdisAcquireSpinLock(&TspCB.Lock);
  686. if (TspCB.Status != NDISTAPI_STATUS_CONNECTED) {
  687. PXDEBUGP (PXD_WARNING, PXM_INIT, ("IOCTL_NDISTAPI_SET_DEVICEID_BASE: Disconnected\n"));
  688. ntStatus = STATUS_UNSUCCESSFUL;
  689. NdisReleaseSpinLock(&TspCB.Lock);
  690. break;
  691. }
  692. //
  693. // Set the base ID
  694. //
  695. BaseId = *((ULONG *) ioBuffer);
  696. PXDEBUGP(PXD_LOUD, PXM_INIT, ("BaseID %d\n", BaseId));
  697. NdisReleaseSpinLock(&TspCB.Lock);
  698. {
  699. LOCK_STATE LockState;
  700. ULONG i;
  701. //
  702. // Update the deviceId's for each line on the provider
  703. //
  704. NdisAcquireReadWriteLock(&LineTable.Lock, FALSE, &LockState);
  705. for (i = 0; i < LineTable.Size; i++) {
  706. PPX_TAPI_LINE TapiLine;
  707. TapiLine = LineTable.Table[i];
  708. if ((TapiLine != NULL)) {
  709. TapiLine->ulDeviceID = BaseId++;
  710. }
  711. }
  712. NdisReleaseReadWriteLock(&LineTable.Lock, &LockState);
  713. }
  714. InfoSize = 0;
  715. ntStatus = STATUS_SUCCESS;
  716. break;
  717. }
  718. case IOCTL_NDISTAPI_CREATE:
  719. {
  720. PPX_TAPI_PROVIDER Provider;
  721. PNDISTAPI_CREATE_INFO CreateInfo;
  722. PPX_TAPI_LINE TapiLine;
  723. InfoSize = 0;
  724. if (inputBufferLength < sizeof(CreateInfo)) {
  725. PXDEBUGP(PXD_WARNING, PXM_INIT, ("IOCTL_NDISTAPI_CREATE: buffer too small\n"));
  726. ntStatus = STATUS_BUFFER_TOO_SMALL;
  727. break;
  728. }
  729. CreateInfo = (PNDISTAPI_CREATE_INFO)ioBuffer;
  730. if (!IsTapiLineValid(CreateInfo->TempID, &TapiLine)) {
  731. PXDEBUGP(PXD_WARNING, PXM_INIT,
  732. ("IOCTL_NDISTAPI_CREATE: Failed to find Id %d\n",
  733. CreateInfo->TempID));
  734. ntStatus = STATUS_INVALID_PARAMETER;
  735. break;
  736. }
  737. PXDEBUGP(PXD_LOUD, PXM_INIT,
  738. ("IOCTL_NDISTAPI_CREATE: Created new Line %p Id %d\n",
  739. TapiLine, CreateInfo->DeviceID));
  740. TapiLine->ulDeviceID = CreateInfo->DeviceID;
  741. ntStatus = STATUS_SUCCESS;
  742. break;
  743. }
  744. default:
  745. ntStatus = STATUS_INVALID_PARAMETER;
  746. PXDEBUGP(PXD_WARNING, PXM_INIT, ("unknown IRP_MJ_DEVICE_CONTROL\n"));
  747. break;
  748. } // switch
  749. //
  750. // Complete this IRP synchronously if we are done.
  751. //
  752. if (ntStatus != STATUS_PENDING) {
  753. PIO_STACK_LOCATION IrpSp;
  754. Irp->IoStatus.Status = ntStatus;
  755. Irp->IoStatus.Information = InfoSize;
  756. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  757. IrpSp->Control &= ~SL_PENDING_RETURNED;
  758. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  759. }
  760. PXDEBUGP(PXD_VERY_LOUD, PXM_INIT, ("PxDispatch: Completing Irp %p (Status %x) synchronously\n", Irp, ntStatus));
  761. return ntStatus;
  762. }
  763. NTSTATUS
  764. PxIOCleanup(
  765. IN PDEVICE_OBJECT DeviceObject,
  766. IN PIRP Irp
  767. )
  768. /*++
  769. Routine Description:
  770. This routine is the dispatch routine for cleanup requests.
  771. All requests queued are completed with STATUS_CANCELLED.
  772. Arguments:
  773. DeviceObject - Pointer to device object.
  774. Irp - Pointer to the request packet.
  775. Return Value:
  776. Status is returned.
  777. --*/
  778. {
  779. PIRP MyIrp;
  780. PXDEBUGP(PXD_LOUD, PXM_INIT, ("PxIOCleanup: enter\n"));
  781. NdisAcquireSpinLock (&TspEventList.Lock);
  782. //
  783. // Cancel the EventRequest Irp
  784. //
  785. MyIrp = TspEventList.RequestIrp;
  786. if ((MyIrp != NULL) &&
  787. (MyIrp->Tail.Overlay.OriginalFileObject ==
  788. Irp->Tail.Overlay.OriginalFileObject)) {
  789. if (IoSetCancelRoutine(MyIrp, NULL) != NULL) {
  790. TspEventList.RequestIrp = NULL;
  791. MyIrp->IoStatus.Status = STATUS_CANCELLED;
  792. MyIrp->IoStatus.Information = 0;
  793. NdisReleaseSpinLock(&TspEventList.Lock);
  794. IoCompleteRequest(MyIrp, IO_NO_INCREMENT);
  795. NdisAcquireSpinLock(&TspEventList.Lock);
  796. }
  797. }
  798. //
  799. // Cancel any Set/Query Irp's
  800. //
  801. NdisReleaseSpinLock(&TspEventList.Lock);
  802. //
  803. // Complete the cleanup request with STATUS_SUCCESS.
  804. //
  805. Irp->IoStatus.Status = STATUS_SUCCESS;
  806. Irp->IoStatus.Information = 0;
  807. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  808. PXDEBUGP (PXD_LOUD, PXM_INIT, ("PxIOCleanup: exit\n"));
  809. return(STATUS_SUCCESS);
  810. }
  811. VOID
  812. PxCancelGetEvents(
  813. IN PDEVICE_OBJECT DeviceObject,
  814. IN PIRP Irp
  815. )
  816. {
  817. PIRP MyIrp;
  818. PXDEBUGP(PXD_LOUD, PXM_INIT,
  819. ("PxCancelGetEvents: enter. Irp = %x\n", Irp));
  820. IoReleaseCancelSpinLock(Irp->CancelIrql);
  821. //
  822. // Acquire the EventSpinLock & check to see if we're canceling a
  823. // pending get-events Irp
  824. //
  825. NdisAcquireSpinLock (&TspEventList.Lock);
  826. MyIrp = TspEventList.RequestIrp;
  827. TspEventList.RequestIrp = NULL;
  828. NdisReleaseSpinLock(&TspEventList.Lock);
  829. if (MyIrp != NULL) {
  830. ASSERT(MyIrp == Irp);
  831. //
  832. // Don't let it get cancelled again
  833. //
  834. IoSetCancelRoutine (MyIrp, NULL);
  835. MyIrp->IoStatus.Status = STATUS_CANCELLED;
  836. MyIrp->IoStatus.Information = 0;
  837. IoCompleteRequest (MyIrp, IO_NO_INCREMENT);
  838. }
  839. }
  840. VOID
  841. PxCancelSetQuery(
  842. IN PDEVICE_OBJECT DeviceObject,
  843. IN PIRP Irp
  844. )
  845. {
  846. BOOLEAN Found = FALSE;
  847. LOCK_STATE LockState;
  848. PPX_VC pVc;
  849. PIRP MyIrp;
  850. PXDEBUGP(PXD_LOUD, PXM_INIT,
  851. ("PxCancelSetQuery: enter. Irp = %x\n", Irp));
  852. IoReleaseCancelSpinLock(Irp->CancelIrql);
  853. //
  854. // We must search through the Vc's in the Vc table
  855. // and find the pending ndisrequest!
  856. //
  857. NdisAcquireReadWriteLock(&VcTable.Lock, FALSE, &LockState);
  858. pVc = (PPX_VC)VcTable.List.Flink;
  859. while ((PVOID)pVc != (PVOID)&VcTable.List) {
  860. PLIST_ENTRY Entry;
  861. PNDISTAPI_REQUEST Request;
  862. NdisAcquireSpinLock(&pVc->Lock);
  863. Entry = pVc->PendingDropReqs.Flink;
  864. while (Entry != &pVc->PendingDropReqs) {
  865. Request =
  866. CONTAINING_RECORD(Entry, NDISTAPI_REQUEST, Linkage);
  867. MyIrp = Request->Irp;
  868. if (MyIrp->Cancel) {
  869. Found = TRUE;
  870. RemoveEntryList(&Request->Linkage);
  871. break;
  872. }
  873. Entry = Entry->Flink;
  874. }
  875. if (!Found) {
  876. if (pVc->PendingGatherDigits != NULL) {
  877. MyIrp = pVc->PendingGatherDigits->Irp;
  878. if (MyIrp->Cancel) {
  879. Found = TRUE;
  880. pVc->PendingGatherDigits = NULL;
  881. }
  882. }
  883. }
  884. NdisReleaseSpinLock(&pVc->Lock);
  885. if (Found) {
  886. break;
  887. }
  888. pVc = (PPX_VC)pVc->Linkage.Flink;
  889. }
  890. NdisReleaseReadWriteLock(&VcTable.Lock, &LockState);
  891. if (Found) {
  892. //
  893. // Don't let it get cancelled again
  894. //
  895. IoSetCancelRoutine (MyIrp, NULL);
  896. MyIrp->IoStatus.Status = STATUS_CANCELLED;
  897. MyIrp->IoStatus.Information = 0;
  898. IoCompleteRequest (MyIrp, IO_NO_INCREMENT);
  899. }
  900. PXDEBUGP(PXD_INFO, PXM_INIT, ("PxIOCancel: completing Irp=%p\n", Irp));
  901. }