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.

1876 lines
63 KiB

  1. /***************************************************************************
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. USBSER.C
  5. Abstract:
  6. Main entry points for Legacy USB Modem Driver.
  7. All driver entry points here are called at
  8. IRQL = PASSIVE_LEVEL
  9. Environment:
  10. kernel mode only
  11. Notes:
  12. THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  13. KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14. IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  15. PURPOSE.
  16. Copyright (c) 1998 Microsoft Corporation. All Rights Reserved.
  17. Revision History:
  18. 12/23/97 : created
  19. Authors:
  20. Tom Green
  21. ****************************************************************************/
  22. #include <wdm.h>
  23. #include <ntddser.h>
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <usb.h>
  27. #include <usbdrivr.h>
  28. #include <usbdlib.h>
  29. #include <usbcomm.h>
  30. #ifdef WMI_SUPPORT
  31. #include <wmilib.h>
  32. #include <wmidata.h>
  33. #include <wmistr.h>
  34. #endif
  35. #include "usbser.h"
  36. #include "usbserpw.h"
  37. #include "serioctl.h"
  38. #include "utils.h"
  39. #include "debugwdm.h"
  40. #ifdef ALLOC_PRAGMA
  41. //
  42. // INIT - only needed during init and then can be disposed
  43. // PAGEUBS0 - always paged / never locked
  44. // PAGEUSBS - must be locked when a device is open, else paged
  45. //
  46. //
  47. // INIT is used for DriverEntry() specific code
  48. //
  49. // PAGEUBS0 is used for code that is not often called and has nothing
  50. // to do with I/O performance. An example, IRP_MJ_PNP/IRP_MN_START_DEVICE
  51. // support functions
  52. //
  53. // PAGEUSBS is used for code that needs to be locked after an open for both
  54. // performance and IRQL reasons.
  55. //
  56. #pragma alloc_text(INIT, DriverEntry)
  57. #pragma alloc_text(PAGEUSBS0, UsbSer_Unload)
  58. #pragma alloc_text(PAGEUSBS0, UsbSer_PnPAddDevice)
  59. #pragma alloc_text(PAGEUSBS0, UsbSer_PnP)
  60. #pragma alloc_text(PAGEUSBS0, UsbSerMajorNotSupported)
  61. #ifdef WMI_SUPPORT
  62. #pragma alloc_text(PAGEUSBS0, UsbSerSystemControlDispatch)
  63. #pragma alloc_text(PAGEUSBS0, UsbSerTossWMIRequest)
  64. #pragma alloc_text(PAGEUSBS0, UsbSerSetWmiDataItem)
  65. #pragma alloc_text(PAGEUSBS0, UsbSerSetWmiDataBlock)
  66. #pragma alloc_text(PAGEUSBS0, UsbSerQueryWmiDataBlock)
  67. #pragma alloc_text(PAGEUSBS0, UsbSerQueryWmiRegInfo)
  68. #else
  69. #pragma alloc_text(PAGEUSBS0, UsbSer_SystemControl)
  70. #endif
  71. //
  72. // PAGEUSBS is keyed off of UsbSer_Read, so UsbSer_Read must
  73. // remain in PAGEUSBS for things to work properly
  74. //
  75. #pragma alloc_text(PAGEUSBS, UsbSer_Cleanup)
  76. #pragma alloc_text(PAGEUSBS, UsbSer_Dispatch)
  77. #pragma alloc_text(PAGEUSBS, UsbSer_Create)
  78. #pragma alloc_text(PAGEUSBS, UsbSer_Close)
  79. #endif // ALLOC_PRAGMA
  80. UNICODE_STRING GlobalRegistryPath;
  81. #ifdef WMI_SUPPORT
  82. #define SERIAL_WMI_GUID_LIST_SIZE 1
  83. #define WMI_SERIAL_PORT_NAME_INFORMATION 0
  84. GUID SerialPortNameGuid = SERIAL_PORT_WMI_NAME_GUID;
  85. WMIGUIDREGINFO SerialWmiGuidList[SERIAL_WMI_GUID_LIST_SIZE] =
  86. {
  87. { &SerialPortNameGuid, 1, 0 }
  88. };
  89. #endif
  90. /************************************************************************/
  91. /* DriverEntry */
  92. /************************************************************************/
  93. /* */
  94. /* Routine Description: */
  95. /* */
  96. /* Installable driver initialization entry point. */
  97. /* This entry point is called directly by the I/O system. */
  98. /* */
  99. /* Arguments: */
  100. /* */
  101. /* DriverObject - pointer to the driver object */
  102. /* */
  103. /* RegistryPath - pointer to a unicode string representing the */
  104. /* path to driver-specific key in the registry */
  105. /* */
  106. /* Return Value: */
  107. /* */
  108. /* NTSTATUS */
  109. /* */
  110. /************************************************************************/
  111. NTSTATUS
  112. DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
  113. {
  114. NTSTATUS NtStatus;
  115. PVOID lockPtr = MmLockPagableCodeSection(UsbSer_Read);
  116. PAGED_CODE();
  117. // setup debug trace level
  118. #if 0
  119. Usbser_Debug_Trace_Level = 0;
  120. #else
  121. Usbser_Debug_Trace_Level = 0;
  122. #endif
  123. //
  124. // Serial portion
  125. #if DBG
  126. UsbSerSerialDebugLevel = 0x00000000;
  127. PAGEUSBSER_Count = 0;
  128. #else
  129. UsbSerSerialDebugLevel = 0;
  130. #endif
  131. PAGEUSBSER_Handle = lockPtr;
  132. PAGEUSBSER_Function = UsbSer_Read;
  133. // Create dispatch points for device control, create, close, etc.
  134. DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] =
  135. UsbSer_Dispatch;
  136. DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = UsbSer_Dispatch;
  137. DriverObject->MajorFunction[IRP_MJ_CREATE] = UsbSer_Create;
  138. DriverObject->MajorFunction[IRP_MJ_CLOSE] = UsbSer_Close;
  139. DriverObject->MajorFunction[IRP_MJ_WRITE] = UsbSer_Write;
  140. DriverObject->MajorFunction[IRP_MJ_READ] = UsbSer_Read;
  141. DriverObject->MajorFunction[IRP_MJ_CLEANUP] = UsbSer_Cleanup;
  142. DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION]
  143. = UsbSerMajorNotSupported;
  144. DriverObject->MajorFunction[IRP_MJ_SET_INFORMATION]
  145. = UsbSerMajorNotSupported;
  146. #ifdef WMI_SUPPORT
  147. DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = UsbSerSystemControlDispatch;
  148. #else
  149. DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = UsbSer_SystemControl;
  150. #endif
  151. DriverObject->MajorFunction[IRP_MJ_PNP] = UsbSer_PnP;
  152. DriverObject->MajorFunction[IRP_MJ_POWER] = UsbSer_ProcessPowerIrp;
  153. DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = UsbSerFlush;
  154. DriverObject->DriverExtension->AddDevice = UsbSer_PnPAddDevice;
  155. DriverObject->DriverUnload = UsbSer_Unload;
  156. KeInitializeSpinLock(&GlobalSpinLock);
  157. GlobalRegistryPath.MaximumLength = RegistryPath->MaximumLength;
  158. GlobalRegistryPath.Length = RegistryPath->Length;
  159. GlobalRegistryPath.Buffer
  160. = DEBUG_MEMALLOC(PagedPool, GlobalRegistryPath.MaximumLength);
  161. if (GlobalRegistryPath.Buffer == NULL)
  162. {
  163. MmUnlockPagableImageSection(lockPtr);
  164. return STATUS_INSUFFICIENT_RESOURCES;
  165. }
  166. RtlZeroMemory(GlobalRegistryPath.Buffer,
  167. GlobalRegistryPath.MaximumLength);
  168. RtlMoveMemory(GlobalRegistryPath.Buffer,
  169. RegistryPath->Buffer, RegistryPath->Length);
  170. // initialize diagnostic stuff (history, tracing, error logging)
  171. DriverName = "USBSER";
  172. DriverVersion = "0.99";
  173. NtStatus = DEBUG_OPEN();
  174. // log an error if we got one
  175. DEBUG_LOG_ERROR(NtStatus);
  176. DEBUG_LOG_PATH("exit DriverEntry");
  177. DEBUG_TRACE3(("status (%08X)\n", NtStatus));
  178. //
  179. // Unlock pageable text
  180. //
  181. MmUnlockPagableImageSection(lockPtr);
  182. return NtStatus;
  183. } // DriverEntry
  184. /************************************************************************/
  185. /* UsbSer_Dispatch */
  186. /************************************************************************/
  187. /* */
  188. /* Routine Description: */
  189. /* */
  190. /* Process the IRPs sent to this device. In this case IOCTLs and */
  191. /* PNP IOCTLs */
  192. /* */
  193. /* Arguments: */
  194. /* */
  195. /* DeviceObject - pointer to a device object */
  196. /* Irp - pointer to an I/O Request Packet */
  197. /* */
  198. /* Return Value: */
  199. /* */
  200. /* NTSTATUS */
  201. /* */
  202. /************************************************************************/
  203. NTSTATUS
  204. UsbSer_Dispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
  205. {
  206. NTSTATUS NtStatus;
  207. PIO_STACK_LOCATION IrpStack;
  208. PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
  209. PVOID IoBuffer;
  210. ULONG InputBufferLength;
  211. ULONG OutputBufferLength;
  212. ULONG IoControlCode;
  213. BOOLEAN NeedCompletion = TRUE;
  214. KIRQL oldIrql;
  215. USBSER_LOCKED_PAGED_CODE();
  216. DEBUG_LOG_PATH("enter UsbSer_Dispatch");
  217. // set return values to something known
  218. NtStatus = Irp->IoStatus.Status = STATUS_SUCCESS;
  219. Irp->IoStatus.Information = 0;
  220. ACQUIRE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, &oldIrql);
  221. if (DeviceExtension->CurrentDevicePowerState != PowerDeviceD0) {
  222. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, oldIrql);
  223. NtStatus = Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
  224. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  225. goto UsbSer_DispatchErr;
  226. }
  227. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, oldIrql);
  228. // Get a pointer to the current location in the Irp. This is where
  229. // the function codes and parameters are located.
  230. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  231. // Get the pointer to the input/output buffer and it's length
  232. IoBuffer = Irp->AssociatedIrp.SystemBuffer;
  233. InputBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
  234. OutputBufferLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
  235. // make entry in IRP history table
  236. DEBUG_LOG_IRP_HIST(DeviceObject, Irp, IrpStack->MajorFunction, IoBuffer,
  237. InputBufferLength);
  238. switch (IrpStack->MajorFunction) {
  239. case IRP_MJ_DEVICE_CONTROL:
  240. DEBUG_LOG_PATH("IRP_MJ_DEVICE_CONTROL");
  241. IoControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
  242. switch (IoControlCode) {
  243. #ifdef PROFILING_ENABLED
  244. case GET_DRIVER_LOG:
  245. DEBUG_LOG_PATH("GET_DRIVER_LOG");
  246. // make sure we have a buffer length and a buffer
  247. if (!OutputBufferLength || !IoBuffer)
  248. NtStatus = STATUS_BUFFER_TOO_SMALL;
  249. else {
  250. // make sure buffer contains null terminator
  251. ((PCHAR) IoBuffer)[0] = '\0';
  252. Irp->IoStatus.Information = Debug_DumpDriverLog(DeviceObject,
  253. IoBuffer,
  254. OutputBufferLength);
  255. }
  256. break;
  257. case GET_IRP_HIST:
  258. DEBUG_LOG_PATH("GET_IRP_HIST");
  259. // make sure we have a buffer length and a buffer
  260. if (!OutputBufferLength || !IoBuffer)
  261. NtStatus = STATUS_BUFFER_TOO_SMALL;
  262. else {
  263. // make sure buffer contains null terminator
  264. ((PCHAR) IoBuffer)[0] = '\0';
  265. Irp->IoStatus.Information
  266. = Debug_ExtractIRPHist(IoBuffer, OutputBufferLength);
  267. }
  268. break;
  269. case GET_PATH_HIST:
  270. DEBUG_LOG_PATH("GET_PATH_HIST");
  271. // make sure we have a buffer length and a buffer
  272. if (!OutputBufferLength || !IoBuffer)
  273. NtStatus = STATUS_BUFFER_TOO_SMALL;
  274. else {
  275. // make sure buffer contains null terminator
  276. ((PCHAR) IoBuffer)[0] = '\0';
  277. Irp->IoStatus.Information
  278. = Debug_ExtractPathHist(IoBuffer, OutputBufferLength);
  279. }
  280. break;
  281. case GET_ERROR_LOG:
  282. DEBUG_LOG_PATH("GET_ERROR_LOG");
  283. // make sure we have a buffer length and a buffer
  284. if (!OutputBufferLength || !IoBuffer)
  285. NtStatus = STATUS_BUFFER_TOO_SMALL;
  286. else {
  287. // make sure buffer contains null terminator
  288. ((PCHAR) IoBuffer)[0] = '\0';
  289. Irp->IoStatus.Information
  290. = Debug_ExtractErrorLog(IoBuffer, OutputBufferLength);
  291. }
  292. break;
  293. case GET_ATTACHED_DEVICES:
  294. DEBUG_LOG_PATH("GET_ATTACHED_DEVICES");
  295. // make sure we have a buffer length and a buffer
  296. if (!OutputBufferLength || !IoBuffer)
  297. NtStatus = STATUS_BUFFER_TOO_SMALL;
  298. else {
  299. // make sure buffer contains null terminator
  300. ((PCHAR) IoBuffer)[0] = '\0';
  301. Irp->IoStatus.Information
  302. = Debug_ExtractAttachedDevices(DeviceObject->DriverObject,
  303. IoBuffer, OutputBufferLength);
  304. }
  305. break;
  306. case GET_DRIVER_INFO:
  307. DEBUG_LOG_PATH("GET_DRIVER_INFO");
  308. // make sure we have a buffer length and a buffer
  309. if (!OutputBufferLength || !IoBuffer)
  310. NtStatus = STATUS_BUFFER_TOO_SMALL;
  311. else {
  312. // make sure buffer contains null terminator
  313. ((PCHAR) IoBuffer)[0] = '\0';
  314. Irp->IoStatus.Information
  315. = Debug_GetDriverInfo(IoBuffer, OutputBufferLength);
  316. }
  317. break;
  318. case SET_IRP_HIST_SIZE:
  319. DEBUG_LOG_PATH("SET_IRP_HIST_SIZE");
  320. // make sure we have a correct buffer length and a buffer
  321. if (InputBufferLength != sizeof(ULONG) || !IoBuffer)
  322. NtStatus = STATUS_BUFFER_TOO_SMALL;
  323. else
  324. NtStatus = Debug_SizeIRPHistoryTable(*((ULONG *) IoBuffer));
  325. break;
  326. case SET_PATH_HIST_SIZE:
  327. DEBUG_LOG_PATH("SET_PATH_HIST_SIZE");
  328. // make sure we have a correct buffer length and a buffer
  329. if (InputBufferLength != sizeof(ULONG) || !IoBuffer)
  330. NtStatus = STATUS_BUFFER_TOO_SMALL;
  331. else
  332. NtStatus = Debug_SizeDebugPathHist(*((ULONG *) IoBuffer));
  333. break;
  334. case SET_ERROR_LOG_SIZE:
  335. DEBUG_LOG_PATH("SET_ERROR_LOG_SIZE");
  336. // make sure we have a correct buffer length and a buffer
  337. if (InputBufferLength != sizeof(long) || !IoBuffer)
  338. NtStatus = STATUS_BUFFER_TOO_SMALL;
  339. else
  340. NtStatus = Debug_SizeErrorLog(*((ULONG *) IoBuffer));
  341. break;
  342. #endif // PROFILING_ENABLED
  343. case ENABLE_PERF_TIMING:
  344. DEBUG_LOG_PATH("ENABLE_PERF_TIMING");
  345. // enable perf timing
  346. DeviceExtension->PerfTimerEnabled = TRUE;
  347. // reset BytesXfered, ElapsedTime and TimerStart
  348. DeviceExtension->BytesXfered = RtlConvertUlongToLargeInteger(0L);
  349. DeviceExtension->ElapsedTime = RtlConvertUlongToLargeInteger(0L);
  350. DeviceExtension->TimerStart = RtlConvertUlongToLargeInteger(0L);
  351. break;
  352. case DISABLE_PERF_TIMING:
  353. DEBUG_LOG_PATH("DISABLE_PERF_TIMING");
  354. // disable perf timing
  355. DeviceExtension->PerfTimerEnabled = FALSE;
  356. break;
  357. case GET_PERF_DATA:
  358. DEBUG_LOG_PATH("GET_PERF_DATA");
  359. // make sure we have enough space to return perf info
  360. if (OutputBufferLength < sizeof(PERF_INFO) || !IoBuffer)
  361. NtStatus = Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
  362. else {
  363. PPERF_INFO Perf = (PPERF_INFO) IoBuffer;
  364. Perf->PerfModeEnabled = DeviceExtension->PerfTimerEnabled;
  365. Perf->BytesPerSecond = BytesPerSecond(DeviceExtension);
  366. Irp->IoStatus.Information = sizeof(PERF_INFO);
  367. }
  368. break;
  369. case SET_DEBUG_TRACE_LEVEL:
  370. // make sure we have a correct buffer length and a buffer
  371. if (InputBufferLength != sizeof(long) || !IoBuffer)
  372. NtStatus = STATUS_BUFFER_TOO_SMALL;
  373. else
  374. Usbser_Debug_Trace_Level = *((ULONG *) IoBuffer);
  375. break;
  376. // handle IOCTLs for a "serial" device
  377. case IOCTL_SERIAL_SET_BAUD_RATE:
  378. DEBUG_LOG_PATH("IOCTL_SERIAL_SET_BAUD_RATE");
  379. NtStatus = SetBaudRate(Irp, DeviceObject);
  380. break;
  381. case IOCTL_SERIAL_GET_BAUD_RATE:
  382. DEBUG_LOG_PATH("IOCTL_SERIAL_GET_BAUD_RATE");
  383. NtStatus = GetBaudRate(Irp, DeviceObject);
  384. break;
  385. case IOCTL_SERIAL_SET_LINE_CONTROL:
  386. DEBUG_LOG_PATH("IOCTL_SERIAL_SET_LINE_CONTROL");
  387. NtStatus = SetLineControl(Irp, DeviceObject);
  388. break;
  389. case IOCTL_SERIAL_GET_LINE_CONTROL:
  390. DEBUG_LOG_PATH("IOCTL_SERIAL_GET_LINE_CONTROL");
  391. NtStatus = GetLineControl(Irp, DeviceObject);
  392. break;
  393. case IOCTL_SERIAL_SET_TIMEOUTS:
  394. DEBUG_LOG_PATH("IOCTL_SERIAL_SET_TIMEOUTS");
  395. NtStatus = SetTimeouts(Irp, DeviceExtension);
  396. break;
  397. case IOCTL_SERIAL_GET_TIMEOUTS:
  398. DEBUG_LOG_PATH("IOCTL_SERIAL_GET_TIMEOUTS");
  399. NtStatus = GetTimeouts(Irp, DeviceExtension);
  400. break;
  401. case IOCTL_SERIAL_SET_CHARS:
  402. DEBUG_LOG_PATH("IOCTL_SERIAL_SET_CHARS");
  403. NtStatus = SetChars(Irp, DeviceExtension);
  404. break;
  405. case IOCTL_SERIAL_GET_CHARS:
  406. DEBUG_LOG_PATH("IOCTL_SERIAL_GET_CHARS");
  407. NtStatus = GetChars(Irp, DeviceExtension);
  408. break;
  409. case IOCTL_SERIAL_SET_DTR:
  410. DEBUG_LOG_PATH("IOCTL_SERIAL_SET_DTR");
  411. NtStatus = SetClrDtr(DeviceObject, TRUE);
  412. break;
  413. case IOCTL_SERIAL_CLR_DTR:
  414. DEBUG_LOG_PATH("IOCTL_SERIAL_CLR_DTR");
  415. NtStatus = SetClrDtr(DeviceObject, FALSE);
  416. break;
  417. case IOCTL_SERIAL_RESET_DEVICE:
  418. DEBUG_LOG_PATH("IOCTL_SERIAL_RESET_DEVICE");
  419. NtStatus = ResetDevice(Irp, DeviceObject);
  420. break;
  421. case IOCTL_SERIAL_SET_RTS:
  422. DEBUG_LOG_PATH("IOCTL_SERIAL_SET_RTS");
  423. NtStatus = SetRts(Irp, DeviceExtension);
  424. break;
  425. case IOCTL_SERIAL_CLR_RTS:
  426. DEBUG_LOG_PATH("IOCTL_SERIAL_CLR_RTS");
  427. NtStatus = ClrRts(Irp, DeviceExtension);
  428. break;
  429. case IOCTL_SERIAL_SET_BREAK_ON:
  430. DEBUG_LOG_PATH("IOCTL_SERIAL_SET_BREAK_ON");
  431. NtStatus = SetBreak(Irp, DeviceObject, 0xFFFF);
  432. break;
  433. case IOCTL_SERIAL_SET_BREAK_OFF:
  434. DEBUG_LOG_PATH("IOCTL_SERIAL_SET_BREAK_OFF");
  435. NtStatus = SetBreak(Irp, DeviceObject, 0);
  436. break;
  437. case IOCTL_SERIAL_SET_QUEUE_SIZE:
  438. DEBUG_LOG_PATH("IOCTL_SERIAL_SET_QUEUE_SIZE");
  439. NtStatus = SetQueueSize(Irp, DeviceExtension);
  440. break;
  441. case IOCTL_SERIAL_GET_WAIT_MASK:
  442. DEBUG_LOG_PATH("IOCTL_SERIAL_GET_WAIT_MASK");
  443. NtStatus = GetWaitMask(Irp, DeviceExtension);
  444. break;
  445. case IOCTL_SERIAL_SET_WAIT_MASK:
  446. DEBUG_LOG_PATH("IOCTL_SERIAL_SET_WAIT_MASK");
  447. NtStatus = SetWaitMask(Irp, DeviceExtension);
  448. break;
  449. case IOCTL_SERIAL_WAIT_ON_MASK:
  450. DEBUG_LOG_PATH("IOCTL_SERIAL_WAIT_ON_MASK");
  451. NtStatus = WaitOnMask(Irp, DeviceExtension);
  452. break;
  453. case IOCTL_SERIAL_IMMEDIATE_CHAR:
  454. DEBUG_LOG_PATH("IOCTL_SERIAL_IMMEDIATE_CHAR");
  455. NeedCompletion = FALSE;
  456. NtStatus = ImmediateChar(Irp, DeviceObject);
  457. if(NtStatus == STATUS_BUFFER_TOO_SMALL)
  458. NeedCompletion = TRUE;
  459. break;
  460. case IOCTL_SERIAL_PURGE:
  461. DEBUG_LOG_PATH("IOCTL_SERIAL_PURGE");
  462. NtStatus = Purge(DeviceObject, Irp, DeviceExtension);
  463. break;
  464. case IOCTL_SERIAL_GET_HANDFLOW:
  465. DEBUG_LOG_PATH("IOCTL_SERIAL_GET_HANDFLOW");
  466. NtStatus = GetHandflow(Irp, DeviceExtension);
  467. break;
  468. case IOCTL_SERIAL_SET_HANDFLOW:
  469. DEBUG_LOG_PATH("IOCTL_SERIAL_SET_HANDFLOW");
  470. NtStatus = SetHandflow(Irp, DeviceExtension);
  471. break;
  472. case IOCTL_SERIAL_GET_MODEMSTATUS:
  473. DEBUG_LOG_PATH("IOCTL_SERIAL_GET_MODEMSTATUS");
  474. NtStatus = GetModemStatus(Irp, DeviceExtension);
  475. break;
  476. case IOCTL_SERIAL_GET_DTRRTS:
  477. DEBUG_LOG_PATH("IOCTL_SERIAL_GET_DTRRTS");
  478. NtStatus = GetDtrRts(Irp, DeviceExtension);
  479. break;
  480. case IOCTL_SERIAL_GET_COMMSTATUS:
  481. DEBUG_LOG_PATH("IOCTL_SERIAL_GET_COMMSTATUS");
  482. NtStatus = GetCommStatus(Irp, DeviceExtension);
  483. break;
  484. case IOCTL_SERIAL_GET_PROPERTIES:
  485. DEBUG_LOG_PATH("IOCTL_SERIAL_GET_PROPERTIES");
  486. NtStatus = GetProperties(Irp, DeviceExtension);
  487. break;
  488. case IOCTL_SERIAL_LSRMST_INSERT:
  489. DEBUG_LOG_PATH("IOCTL_SERIAL_LSRMST_INSERT");
  490. NtStatus = LsrmstInsert(Irp, DeviceExtension);
  491. break;
  492. case IOCTL_SERIAL_CONFIG_SIZE:
  493. DEBUG_LOG_PATH("IOCTL_SERIAL_CONFIG_SIZE");
  494. NtStatus = ConfigSize(Irp, DeviceExtension);
  495. break;
  496. case IOCTL_SERIAL_GET_STATS:
  497. DEBUG_LOG_PATH("IOCTL_SERIAL_GET_STATS");
  498. NtStatus = GetStats(Irp, DeviceExtension);
  499. break;
  500. case IOCTL_SERIAL_CLEAR_STATS:
  501. DEBUG_LOG_PATH("IOCTL_SERIAL_CLEAR_STATS");
  502. NtStatus = ClearStats(Irp, DeviceExtension);
  503. break;
  504. default:
  505. NtStatus = STATUS_INVALID_PARAMETER;
  506. }
  507. break;
  508. // breaking out here will complete the Irp
  509. case IRP_MJ_INTERNAL_DEVICE_CONTROL:
  510. DEBUG_TRACE1(("IRP_MJ_INTERNAL_DEVICE_CONTROL\n"));
  511. switch (IrpStack->Parameters.DeviceIoControl.IoControlCode)
  512. {
  513. case IOCTL_SERIAL_INTERNAL_DO_WAIT_WAKE:
  514. DEBUG_TRACE1(("IOCTL_SERIAL_INTERNAL_DO_WAIT_WAKE\n"));
  515. DeviceExtension->SendWaitWake = TRUE;
  516. NtStatus = STATUS_SUCCESS;
  517. break;
  518. case IOCTL_SERIAL_INTERNAL_CANCEL_WAIT_WAKE:
  519. DEBUG_TRACE1(("IOCTL_SERIAL_INTERNAL_CANCEL_WAIT_WAKE\n"));
  520. DeviceExtension->SendWaitWake = FALSE;
  521. if (DeviceExtension->PendingWakeIrp != NULL) {
  522. IoCancelIrp(DeviceExtension->PendingWakeIrp);
  523. }
  524. NtStatus = STATUS_SUCCESS;
  525. break;
  526. default:
  527. // pass through to driver below
  528. DEBUG_LOG_PATH("IRP_MJ_INTERNAL_DEVICE_CONTROL");
  529. // since I dont have a completion routine use
  530. // IoCopyCurrentIrp
  531. IoCopyCurrentIrpStackLocationToNext(Irp);
  532. IoMarkIrpPending(Irp);
  533. NtStatus = IoCallDriver(DeviceExtension->StackDeviceObject,
  534. Irp);
  535. DEBUG_TRACE3(("Passed PnP Irp down, NtStatus = %08X\n",
  536. NtStatus));
  537. NeedCompletion = FALSE;
  538. break;
  539. }
  540. default:
  541. DEBUG_LOG_PATH("MAJOR IOCTL not handled");
  542. Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
  543. break;
  544. }
  545. if (NeedCompletion && NtStatus != STATUS_PENDING) {
  546. Irp->IoStatus.Status = NtStatus;
  547. CompleteIO(DeviceObject, Irp, IrpStack->MajorFunction,
  548. IoBuffer, Irp->IoStatus.Information);
  549. }
  550. UsbSer_DispatchErr:;
  551. // log an error if we got one
  552. DEBUG_LOG_ERROR(NtStatus);
  553. DEBUG_LOG_PATH("exit UsbSer_Dispatch");
  554. DEBUG_TRACE3(("status (%08X)\n", NtStatus));
  555. return NtStatus;
  556. } // UsbSer_Dispatch
  557. /************************************************************************/
  558. /* UsbSer_Create */
  559. /************************************************************************/
  560. /* */
  561. /* Routine Description: */
  562. /* */
  563. /* Process the IRPs sent to this device for Create calls */
  564. /* */
  565. /* Arguments: */
  566. /* */
  567. /* DeviceObject - pointer to a device object */
  568. /* Irp - pointer to an I/O Request Packet */
  569. /* */
  570. /* Return Value: */
  571. /* */
  572. /* NTSTATUS */
  573. /* */
  574. /************************************************************************/
  575. NTSTATUS
  576. UsbSer_Create(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
  577. {
  578. NTSTATUS NtStatus;
  579. PIO_STACK_LOCATION IrpStack;
  580. PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
  581. PVOID IoBuffer;
  582. ULONG InputBufferLength;
  583. KIRQL OldIrql;
  584. USBSER_LOCKED_PAGED_CODE();
  585. DEBUG_LOG_PATH("enter UsbSer_Create");
  586. DEBUG_TRACE1(("Open\n"));
  587. UsbSerSerialDump(USBSERTRACEOTH, (">UsbSer_Create(%08X)\n", Irp));
  588. // wakeup device from previous idle
  589. // UsbSerFdoRequestWake(DeviceExtension);
  590. // set return values to something known
  591. NtStatus = Irp->IoStatus.Status = STATUS_SUCCESS;
  592. Irp->IoStatus.Information = 0;
  593. // Get a pointer to the current location in the Irp. This is where
  594. // the function codes and parameters are located.
  595. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  596. // Get the pointer to the input/output buffer and it's length
  597. IoBuffer = Irp->AssociatedIrp.SystemBuffer;
  598. InputBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
  599. // make entry in IRP history table
  600. DEBUG_LOG_IRP_HIST(DeviceObject, Irp, IrpStack->MajorFunction, IoBuffer, 0);
  601. //
  602. // Serial devices do not allow multiple concurrent opens
  603. //
  604. if (InterlockedIncrement(&DeviceExtension->OpenCnt) != 1) {
  605. InterlockedDecrement(&DeviceExtension->OpenCnt);
  606. NtStatus = Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
  607. goto UsbSer_CreateErr;
  608. }
  609. //
  610. // Before we do anything, let's make sure they aren't trying
  611. // to create a directory.
  612. //
  613. if (IrpStack->Parameters.Create.Options & FILE_DIRECTORY_FILE) {
  614. InterlockedDecrement(&DeviceExtension->OpenCnt);
  615. NtStatus = Irp->IoStatus.Status = STATUS_NOT_A_DIRECTORY;
  616. Irp->IoStatus.Information = 0;
  617. goto UsbSer_CreateErr;
  618. }
  619. //
  620. // Lock down our code pages
  621. //
  622. PAGEUSBSER_Handle = UsbSerLockPagableCodeSection(UsbSer_Read);
  623. ASSERT(DeviceExtension->IsDevice);
  624. ACQUIRE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, &OldIrql);
  625. DeviceExtension->IsrWaitMask = 0;
  626. DeviceExtension->EscapeChar = 0;
  627. RtlZeroMemory(&DeviceExtension->PerfStats, sizeof(SERIALPERF_STATS));
  628. //
  629. // Purge the RX buffer
  630. //
  631. DeviceExtension->CharsInReadBuff = 0;
  632. DeviceExtension->CurrentReadBuffPtr = 0;
  633. DeviceExtension->HistoryMask = 0;
  634. DeviceExtension->EscapeChar = 0;
  635. DeviceExtension->SendWaitWake = FALSE;
  636. RELEASE_SPINLOCK(DeviceExtension, &DeviceExtension->ControlLock, OldIrql);
  637. //
  638. // Restart the read
  639. //
  640. RestartRead(DeviceExtension);
  641. UsbSer_CreateErr:;
  642. CompleteIO(DeviceObject, Irp, IrpStack->MajorFunction,
  643. IoBuffer, Irp->IoStatus.Information);
  644. // log an error if we got one
  645. DEBUG_LOG_ERROR(NtStatus);
  646. DEBUG_LOG_PATH("exit UsbSer_Create");
  647. DEBUG_TRACE3(("status (%08X)\n", NtStatus));
  648. UsbSerSerialDump(USBSERTRACEOTH, ("<UsbSer_Create %08X\n", NtStatus));
  649. return NtStatus;
  650. } // UsbSer_Create
  651. /************************************************************************/
  652. /* UsbSer_Close */
  653. /************************************************************************/
  654. /* */
  655. /* Routine Description: */
  656. /* */
  657. /* Process the IRPs sent to this device for Close calls */
  658. /* */
  659. /* Arguments: */
  660. /* */
  661. /* DeviceObject - pointer to a device object */
  662. /* Irp - pointer to an I/O Request Packet */
  663. /* */
  664. /* Return Value: */
  665. /* */
  666. /* NTSTATUS */
  667. /* */
  668. /************************************************************************/
  669. NTSTATUS
  670. UsbSer_Close(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
  671. {
  672. NTSTATUS NtStatus;
  673. PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
  674. PIO_STACK_LOCATION IrpStack;
  675. PVOID IoBuffer;
  676. ULONG InputBufferLength;
  677. ULONG openCount;
  678. PAGED_CODE();
  679. DEBUG_LOG_PATH("enter UsbSer_Close");
  680. DEBUG_TRACE1(("Close\n"));
  681. UsbSerSerialDump(USBSERTRACEOTH, (">UsbSer_Close(%08X)\n", Irp));
  682. // set return values to something known
  683. NtStatus = Irp->IoStatus.Status = STATUS_SUCCESS;
  684. Irp->IoStatus.Information = 0;
  685. // Get a pointer to the current location in the Irp. This is where
  686. // the function codes and parameters are located.
  687. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  688. // Get the pointer to the input/output buffer and it's length
  689. IoBuffer = Irp->AssociatedIrp.SystemBuffer;
  690. InputBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
  691. // clear DTR, this is what the serial driver does
  692. SetClrDtr(DeviceObject, FALSE);
  693. //
  694. // Stop waiting for wakeup
  695. //
  696. DeviceExtension->SendWaitWake = FALSE;
  697. if (DeviceExtension->PendingWakeIrp != NULL) {
  698. IoCancelIrp(DeviceExtension->PendingWakeIrp);
  699. }
  700. // make entry in IRP history table
  701. DEBUG_LOG_IRP_HIST(DeviceObject, Irp, IrpStack->MajorFunction, IoBuffer, 0);
  702. ASSERT(DeviceExtension->IsDevice);
  703. openCount = InterlockedDecrement(&DeviceExtension->OpenCnt);
  704. ASSERT(openCount == 0);
  705. CompleteIO(DeviceObject, Irp, IrpStack->MajorFunction,
  706. IoBuffer, Irp->IoStatus.Information);
  707. // try and idle the modem
  708. // UsbSerFdoSubmitIdleRequestIrp(DeviceExtension);
  709. // log an error if we got one
  710. DEBUG_LOG_ERROR(NtStatus);
  711. DEBUG_LOG_PATH("exit UsbSer_Close");
  712. DEBUG_TRACE3(("status (%08X)\n", NtStatus));
  713. UsbSerSerialDump(USBSERTRACEOTH, ("<UsbSer_Close %08X\n", NtStatus));
  714. UsbSerUnlockPagableImageSection(PAGEUSBSER_Handle);
  715. return NtStatus;
  716. } // UsbSer_Close
  717. /************************************************************************/
  718. /* UsbSer_Unload */
  719. /************************************************************************/
  720. /* */
  721. /* Routine Description: */
  722. /* */
  723. /* Process unloading driver */
  724. /* */
  725. /* Arguments: */
  726. /* */
  727. /* DriverObject - pointer to a driver object */
  728. /* */
  729. /* Return Value: */
  730. /* */
  731. /* VOID */
  732. /* */
  733. /************************************************************************/
  734. VOID
  735. UsbSer_Unload(IN PDRIVER_OBJECT DriverObject)
  736. {
  737. PAGED_CODE();
  738. DEBUG_LOG_PATH("enter UsbSer_Unload");
  739. // release global resources here
  740. if(GlobalRegistryPath.Buffer != NULL)
  741. {
  742. DEBUG_MEMFREE(GlobalRegistryPath.Buffer);
  743. GlobalRegistryPath.Buffer = NULL;
  744. }
  745. // shut down debugging and release resources
  746. DEBUG_CLOSE();
  747. DEBUG_LOG_PATH("exit UsbSer_Unload");
  748. } // UsbSer_Unload
  749. /************************************************************************/
  750. /* UsbSer_PnPAddDevice */
  751. /************************************************************************/
  752. /* */
  753. /* Routine Description: */
  754. /* */
  755. /* Attach new device to driver */
  756. /* */
  757. /* Arguments: */
  758. /* */
  759. /* DriverObject - pointer to the driver object */
  760. /* */
  761. /* PhysicalDeviceObject - pointer to the bus device object */
  762. /* */
  763. /* Return Value: */
  764. /* */
  765. /* NTSTATUS */
  766. /* */
  767. /************************************************************************/
  768. NTSTATUS
  769. UsbSer_PnPAddDevice(IN PDRIVER_OBJECT DriverObject,
  770. IN PDEVICE_OBJECT PhysicalDeviceObject)
  771. {
  772. NTSTATUS NtStatus;
  773. PDEVICE_OBJECT DeviceObject = NULL;
  774. PDEVICE_EXTENSION DeviceExtension;
  775. ULONG Index;
  776. PAGED_CODE();
  777. DEBUG_LOG_PATH("enter UsbSer_PnPAddDevice");
  778. NtStatus = CreateDeviceObject(DriverObject, &DeviceObject, DriverName);
  779. // make sure we have both a created device object and physical
  780. if ((DeviceObject != NULL) && (PhysicalDeviceObject != NULL)) {
  781. DeviceExtension = DeviceObject->DeviceExtension;
  782. // Attach to the PDO
  783. DeviceExtension->StackDeviceObject =
  784. IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject);
  785. DEBUG_TRACE3(("StackDeviceObject (%08X)\n",
  786. DeviceExtension->StackDeviceObject));
  787. // if we don't have a stack device object to attach to, bong it
  788. if (!DeviceExtension->StackDeviceObject) {
  789. IoDeleteDevice(DeviceObject);
  790. NtStatus = STATUS_NO_SUCH_DEVICE;
  791. } else {
  792. // do some device extension house keeping
  793. DeviceExtension->PerfTimerEnabled = FALSE;
  794. DeviceExtension->PhysDeviceObject = PhysicalDeviceObject;
  795. DeviceExtension->BytesXfered = RtlConvertUlongToLargeInteger(0L);
  796. DeviceExtension->ElapsedTime = RtlConvertUlongToLargeInteger(0L);
  797. DeviceExtension->TimerStart = RtlConvertUlongToLargeInteger(0L);
  798. DeviceExtension->CurrentDevicePowerState = PowerDeviceD0;
  799. // init selective suspend stuff
  800. DeviceExtension->PendingIdleIrp = NULL;
  801. DeviceExtension->IdleCallbackInfo = NULL;
  802. DeviceObject->StackSize = DeviceExtension->StackDeviceObject->StackSize
  803. + 1;
  804. // we support buffered io for read/write
  805. DeviceObject->Flags |= DO_BUFFERED_IO;
  806. // power mangement
  807. DeviceObject->Flags |= DO_POWER_PAGABLE;
  808. // we are done initializing the device object, so say so
  809. DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
  810. // get device capabilities
  811. UsbSerQueryCapabilities(DeviceExtension->StackDeviceObject,
  812. &DeviceExtension->DeviceCapabilities);
  813. // We want to determine what level to auto-powerdown to; This is the
  814. // lowest sleeping level that is LESS than D3;
  815. // If all are set to D3, auto powerdown/powerup will be disabled.
  816. // init to disabled
  817. DeviceExtension->PowerDownLevel = PowerDeviceUnspecified;
  818. for (Index = PowerSystemSleeping1; Index <= PowerSystemSleeping3;
  819. Index++) {
  820. if (DeviceExtension->DeviceCapabilities.DeviceState[Index]
  821. < PowerDeviceD3)
  822. DeviceExtension->PowerDownLevel
  823. = DeviceExtension->DeviceCapabilities.DeviceState[Index];
  824. }
  825. #ifdef WMI_SUPPORT
  826. //
  827. // Register for WMI
  828. //
  829. DeviceExtension->WmiLibInfo.GuidCount = sizeof(SerialWmiGuidList) /
  830. sizeof(WMIGUIDREGINFO);
  831. DeviceExtension->WmiLibInfo.GuidList = SerialWmiGuidList;
  832. DeviceExtension->WmiLibInfo.QueryWmiRegInfo = UsbSerQueryWmiRegInfo;
  833. DeviceExtension->WmiLibInfo.QueryWmiDataBlock = UsbSerQueryWmiDataBlock;
  834. DeviceExtension->WmiLibInfo.SetWmiDataBlock = UsbSerSetWmiDataBlock;
  835. DeviceExtension->WmiLibInfo.SetWmiDataItem = UsbSerSetWmiDataItem;
  836. DeviceExtension->WmiLibInfo.ExecuteWmiMethod = NULL;
  837. DeviceExtension->WmiLibInfo.WmiFunctionControl = NULL;
  838. IoWMIRegistrationControl(DeviceObject, WMIREG_ACTION_REGISTER);
  839. #endif
  840. }
  841. }
  842. // log an error if we got one
  843. DEBUG_LOG_ERROR(NtStatus); // init to disabled
  844. DEBUG_LOG_PATH("exit UsbSer_PnPAddDevice");
  845. DEBUG_TRACE3(("status (%08X)\n", NtStatus));
  846. return NtStatus;
  847. } // UsbSer_PnPAddDevice
  848. /************************************************************************/
  849. /* UsbSer_PnP */
  850. /************************************************************************/
  851. /* */
  852. /* Routine Description: */
  853. /* */
  854. /* This routine will receive the various Plug N Play messages. It */
  855. /* is here that we start our device, stop it, etc. */
  856. /* */
  857. /* Arguments: */
  858. /* */
  859. /* DeviceObject - pointer to a device object */
  860. /* Irp - pointer to an I/O Request Packet */
  861. /* */
  862. /* Return Value: */
  863. /* */
  864. /* NTSTATUS */
  865. /* */
  866. /************************************************************************/
  867. NTSTATUS
  868. UsbSer_PnP(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
  869. {
  870. NTSTATUS NtStatus = STATUS_SUCCESS;
  871. PIO_STACK_LOCATION IrpStack;
  872. PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
  873. PVOID IoBuffer;
  874. ULONG InputBufferLength;
  875. BOOLEAN PassDown = TRUE;
  876. PAGED_CODE();
  877. DEBUG_LOG_PATH("enter UsbSer_PnP");
  878. // Get a pointer to the current location in the Irp. This is where
  879. // the function codes and parameters are located.
  880. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  881. // Get the pointer to the input/output buffer and it's length
  882. IoBuffer = Irp->AssociatedIrp.SystemBuffer;
  883. InputBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
  884. // make entry in IRP history table
  885. DEBUG_LOG_IRP_HIST(DeviceObject, Irp, IrpStack->MajorFunction, IoBuffer,
  886. InputBufferLength);
  887. switch (IrpStack->MinorFunction) {
  888. case IRP_MN_START_DEVICE:
  889. DEBUG_LOG_PATH("IRP_MN_START_DEVICE");
  890. NtStatus = StartDevice(DeviceObject, Irp);
  891. // passed Irp to driver below and completed in start device routine
  892. PassDown = FALSE;
  893. break;
  894. case IRP_MN_QUERY_REMOVE_DEVICE:
  895. DEBUG_LOG_PATH("IRP_MN_QUERY_REMOVE_DEVICE");
  896. break;
  897. case IRP_MN_REMOVE_DEVICE:
  898. DEBUG_LOG_PATH("IRP_MN_REMOVE_DEVICE");
  899. #ifdef WMI_SUPPORT
  900. IoWMIRegistrationControl(DeviceObject, WMIREG_ACTION_DEREGISTER);
  901. #endif
  902. NtStatus = RemoveDevice(DeviceObject, Irp);
  903. PassDown = FALSE;
  904. break;
  905. case IRP_MN_CANCEL_REMOVE_DEVICE:
  906. DEBUG_LOG_PATH("IRP_MN_CANCEL_REMOVE_DEVICE");
  907. break;
  908. case IRP_MN_STOP_DEVICE:
  909. DEBUG_LOG_PATH("IRP_MN_STOP_DEVICE");
  910. NtStatus = StopDevice(DeviceObject, Irp);
  911. break;
  912. case IRP_MN_QUERY_STOP_DEVICE:
  913. DEBUG_LOG_PATH("IRP_MN_QUERY_STOP_DEVICE");
  914. break;
  915. case IRP_MN_CANCEL_STOP_DEVICE:
  916. DEBUG_LOG_PATH("IRP_MN_CANCEL_STOP_DEVICE");
  917. break;
  918. case IRP_MN_QUERY_DEVICE_RELATIONS:
  919. DEBUG_LOG_PATH("IRP_MN_QUERY_DEVICE_RELATIONS");
  920. break;
  921. case IRP_MN_QUERY_INTERFACE:
  922. DEBUG_LOG_PATH("IRP_MN_QUERY_INTERFACE");
  923. break;
  924. case IRP_MN_QUERY_CAPABILITIES:
  925. DEBUG_TRACE2(("IRP_MN_QUERY_CAPABILITIES\n"));
  926. {
  927. PKEVENT pQueryCapsEvent;
  928. PDEVICE_CAPABILITIES pDevCaps;
  929. pQueryCapsEvent = ExAllocatePool(NonPagedPool, sizeof(KEVENT));
  930. if (pQueryCapsEvent == NULL) {
  931. Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
  932. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  933. return STATUS_INSUFFICIENT_RESOURCES;
  934. }
  935. KeInitializeEvent(pQueryCapsEvent, SynchronizationEvent, FALSE);
  936. IoCopyCurrentIrpStackLocationToNext(Irp);
  937. IoSetCompletionRoutine(Irp, UsbSerSyncCompletion, pQueryCapsEvent,
  938. TRUE, TRUE, TRUE);
  939. NtStatus = IoCallDriver(DeviceExtension->StackDeviceObject, Irp);
  940. //
  941. // Wait for lower drivers to be done with the Irp
  942. //
  943. if (NtStatus == STATUS_PENDING) {
  944. KeWaitForSingleObject(pQueryCapsEvent, Executive, KernelMode,
  945. FALSE, NULL);
  946. }
  947. ExFreePool(pQueryCapsEvent);
  948. NtStatus = Irp->IoStatus.Status;
  949. if (IrpStack->Parameters.DeviceCapabilities.Capabilities == NULL) {
  950. goto errQueryCaps;
  951. }
  952. //
  953. // Save off their power capabilities
  954. //
  955. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  956. pDevCaps = IrpStack->Parameters.DeviceCapabilities.Capabilities;
  957. pDevCaps->SurpriseRemovalOK = TRUE;
  958. DeviceExtension->SystemWake = pDevCaps->SystemWake;
  959. DeviceExtension->DeviceWake = pDevCaps->DeviceWake;
  960. UsbSerSerialDump(USBSERTRACEPW,
  961. ("IRP_MN_QUERY_CAPS: SystemWake %08X "
  962. "DeviceWake %08X\n", DeviceExtension->SystemWake,
  963. DeviceExtension->DeviceWake));
  964. errQueryCaps:;
  965. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  966. return NtStatus;
  967. }
  968. case IRP_MN_QUERY_RESOURCES:
  969. DEBUG_LOG_PATH("IRP_MN_QUERY_RESOURCES");
  970. break;
  971. case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
  972. DEBUG_LOG_PATH("IRP_MN_QUERY_RESOURCE_REQUIREMENTS");
  973. break;
  974. case IRP_MN_QUERY_DEVICE_TEXT:
  975. DEBUG_LOG_PATH("IRP_MN_QUERY_DEVICE_TEXT");
  976. break;
  977. case IRP_MN_READ_CONFIG:
  978. DEBUG_LOG_PATH("IRP_MN_READ_CONFIG");
  979. break;
  980. case IRP_MN_WRITE_CONFIG:
  981. DEBUG_LOG_PATH("IRP_MN_WRITE_CONFIG");
  982. break;
  983. case IRP_MN_EJECT:
  984. DEBUG_LOG_PATH("IRP_MN_EJECT");
  985. break;
  986. case IRP_MN_SET_LOCK:
  987. DEBUG_LOG_PATH("IRP_MN_SET_LOCK");
  988. break;
  989. case IRP_MN_QUERY_ID:
  990. DEBUG_LOG_PATH("IRP_MN_QUERY_ID");
  991. break;
  992. case IRP_MN_QUERY_PNP_DEVICE_STATE:
  993. DEBUG_LOG_PATH("IRP_MN_QUERY_PNP_DEVICE_STATE");
  994. break;
  995. case IRP_MN_QUERY_BUS_INFORMATION:
  996. DEBUG_LOG_PATH("IRP_MN_QUERY_BUS_INFORMATION");
  997. break;
  998. case IRP_MN_SURPRISE_REMOVAL:
  999. {
  1000. PIRP CurrentMaskIrp;
  1001. KIRQL CancelIrql;
  1002. DEBUG_TRACE2(("IRP_MN_SURPRISE_REMOVAL\n"));
  1003. ACQUIRE_CANCEL_SPINLOCK(DeviceExtension, &CancelIrql);
  1004. // surprise removal, so stop accepting requests
  1005. UsbSerFetchBooleanLocked(&DeviceExtension->AcceptingRequests,
  1006. FALSE, &DeviceExtension->ControlLock);
  1007. // let's see if we have any events to signal
  1008. CurrentMaskIrp = DeviceExtension->CurrentMaskIrp;
  1009. // complete the queued IRP if needed
  1010. if(CurrentMaskIrp)
  1011. {
  1012. // indicate to upper layers that CD dropped if needed
  1013. if((DeviceExtension->IsrWaitMask & SERIAL_EV_RLSD) &&
  1014. (DeviceExtension->FakeModemStatus & SERIAL_MSR_DCD))
  1015. {
  1016. DEBUG_TRACE2(("Sending up a CD dropped event\n"));
  1017. DeviceExtension->FakeModemStatus &= ~SERIAL_MSR_DCD;
  1018. DeviceExtension->HistoryMask |= SERIAL_EV_RLSD;
  1019. CurrentMaskIrp->IoStatus.Status = STATUS_SUCCESS;
  1020. CurrentMaskIrp->IoStatus.Information = sizeof(ULONG);
  1021. DeviceExtension->CurrentMaskIrp = NULL;
  1022. *(PULONG) (CurrentMaskIrp->AssociatedIrp.SystemBuffer) =
  1023. DeviceExtension->HistoryMask;
  1024. DeviceExtension->HistoryMask = 0;
  1025. IoSetCancelRoutine(CurrentMaskIrp, NULL);
  1026. RELEASE_CANCEL_SPINLOCK(DeviceExtension, CancelIrql);
  1027. IoCompleteRequest(CurrentMaskIrp, IO_NO_INCREMENT);
  1028. }
  1029. else
  1030. {
  1031. RELEASE_CANCEL_SPINLOCK(DeviceExtension, CancelIrql);
  1032. }
  1033. }
  1034. else
  1035. {
  1036. RELEASE_CANCEL_SPINLOCK(DeviceExtension, CancelIrql);
  1037. }
  1038. Irp->IoStatus.Status = STATUS_SUCCESS;
  1039. break;
  1040. }
  1041. default:
  1042. DEBUG_LOG_PATH("PnP IOCTL not handled");
  1043. DEBUG_TRACE3(("IOCTL (%08X)\n", IrpStack->MinorFunction));
  1044. break;
  1045. } // case of IRP_MJ_PNP
  1046. // All PNP POWER messages get passed to StackDeviceObject.
  1047. if (PassDown) {
  1048. DEBUG_TRACE3(("Passing PnP Irp down, status (%08X)\n", NtStatus));
  1049. IoCopyCurrentIrpStackLocationToNext(Irp);
  1050. DEBUG_LOG_PATH("Passing PnP Irp down stack");
  1051. NtStatus = IoCallDriver(DeviceExtension->StackDeviceObject, Irp);
  1052. }
  1053. // log an error if we got one
  1054. DEBUG_LOG_ERROR(NtStatus);
  1055. DEBUG_LOG_PATH("exit UsbSer_PnP");
  1056. DEBUG_TRACE3(("status (%08X)\n", NtStatus));
  1057. return NtStatus;
  1058. } // UsbSer_PnP
  1059. #ifndef WMI_SUPPORT
  1060. /************************************************************************/
  1061. /* UsbSer_SystemControl */
  1062. /************************************************************************/
  1063. /* */
  1064. /* Routine Description: */
  1065. /* */
  1066. /* This routine will receive the various system control messages. */
  1067. /* */
  1068. /* Arguments: */
  1069. /* */
  1070. /* DeviceObject - pointer to a device object */
  1071. /* Irp - pointer to an I/O Request Packet */
  1072. /* */
  1073. /* Return Value: */
  1074. /* */
  1075. /* NTSTATUS */
  1076. /* */
  1077. /************************************************************************/
  1078. NTSTATUS
  1079. UsbSer_SystemControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
  1080. {
  1081. NTSTATUS NtStatus = STATUS_SUCCESS;
  1082. PIO_STACK_LOCATION IrpStack;
  1083. PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
  1084. PVOID IoBuffer;
  1085. ULONG InputBufferLength;
  1086. PAGED_CODE();
  1087. DEBUG_LOG_PATH("enter UsbSer_SystemControl");
  1088. // Get a pointer to the current location in the Irp. This is where
  1089. // the function codes and parameters are located.
  1090. IrpStack = IoGetCurrentIrpStackLocation(Irp);
  1091. // Get the pointer to the input/output buffer and it's length
  1092. IoBuffer = Irp->AssociatedIrp.SystemBuffer;
  1093. InputBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
  1094. // make entry in IRP history table
  1095. DEBUG_LOG_IRP_HIST(DeviceObject, Irp, IrpStack->MajorFunction, IoBuffer,
  1096. InputBufferLength);
  1097. // All System Control messages get passed to StackDeviceObject.
  1098. IoCopyCurrentIrpStackLocationToNext(Irp);
  1099. NtStatus = IoCallDriver(DeviceExtension->StackDeviceObject, Irp);
  1100. // log an error if we got one
  1101. DEBUG_LOG_ERROR(NtStatus);
  1102. DEBUG_LOG_PATH("exit UsbSer_SystemControl");
  1103. DEBUG_TRACE3(("status (%08X)\n", NtStatus));
  1104. return NtStatus;
  1105. } // UsbSer_SystemControl
  1106. #endif
  1107. /************************************************************************/
  1108. /* UsbSer_Cleanup */
  1109. /************************************************************************/
  1110. /* */
  1111. /* Routine Description: */
  1112. /* */
  1113. /* Arguments: */
  1114. /* */
  1115. /* DeviceObject - pointer to a device object */
  1116. /* Irp - pointer to an I/O Request Packet */
  1117. /* */
  1118. /* Return Value: */
  1119. /* */
  1120. /* NTSTATUS */
  1121. /* */
  1122. /************************************************************************/
  1123. NTSTATUS
  1124. UsbSer_Cleanup(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
  1125. {
  1126. NTSTATUS NtStatus = STATUS_SUCCESS;
  1127. USBSER_LOCKED_PAGED_CODE();
  1128. DEBUG_LOG_PATH("enter UsbSer_Cleanup");
  1129. UsbSerSerialDump(USBSERTRACEOTH, (">UsbSer_Cleanup(%08X)\n", Irp));
  1130. Irp->IoStatus.Status = STATUS_SUCCESS;
  1131. Irp->IoStatus.Information = 0;
  1132. UsbSerKillPendingIrps(DeviceObject);
  1133. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1134. // log an error if we got one
  1135. DEBUG_LOG_ERROR(NtStatus);
  1136. DEBUG_LOG_PATH("exit UsbSer_Cleanup");
  1137. DEBUG_TRACE3(("status (%08X)\n", NtStatus));
  1138. UsbSerSerialDump(USBSERTRACEOTH, ("<UsbSer_Cleanup %08X\n", NtStatus));
  1139. return NtStatus;
  1140. } // UsbSer_Cleanup
  1141. /************************************************************************/
  1142. /* UsbSerMajorNotSupported */
  1143. /************************************************************************/
  1144. /* */
  1145. /* Routine Description: */
  1146. /* Standard routine to return STATUS_NOT_SUPPORTED for IRP_MJ */
  1147. /* calls we don't handle. */
  1148. /* */
  1149. /* Arguments: */
  1150. /* */
  1151. /* DeviceObject - pointer to a device object */
  1152. /* Irp - pointer to an I/O Request Packet */
  1153. /* */
  1154. /* Return Value: */
  1155. /* */
  1156. /* NTSTATUS */
  1157. /* */
  1158. /************************************************************************/
  1159. NTSTATUS
  1160. UsbSerMajorNotSupported(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
  1161. {
  1162. PAGED_CODE();
  1163. DEBUG_LOG_PATH("enter UsbSerMajorNotSupported");
  1164. DEBUG_TRACE3(("Major (%08X)\n",
  1165. IoGetCurrentIrpStackLocation(Irp)->MajorFunction));
  1166. Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
  1167. // log an error if we got one
  1168. DEBUG_LOG_ERROR(STATUS_NOT_SUPPORTED);
  1169. DEBUG_LOG_PATH("exit UsbSerMajorNotSupported");
  1170. DEBUG_TRACE3(("status (%08X)\n", STATUS_NOT_SUPPORTED));
  1171. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1172. return STATUS_NOT_SUPPORTED;
  1173. } // UsbSerMajorNotSupported
  1174. #ifdef WMI_SUPPORT
  1175. NTSTATUS
  1176. UsbSerSystemControlDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
  1177. {
  1178. SYSCTL_IRP_DISPOSITION disposition;
  1179. NTSTATUS status;
  1180. PDEVICE_EXTENSION pDevExt
  1181. = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
  1182. PAGED_CODE();
  1183. status = WmiSystemControl( &pDevExt->WmiLibInfo,
  1184. DeviceObject,
  1185. Irp,
  1186. &disposition);
  1187. switch(disposition)
  1188. {
  1189. case IrpProcessed:
  1190. {
  1191. //
  1192. // This irp has been processed and may be completed or pending.
  1193. break;
  1194. }
  1195. case IrpNotCompleted:
  1196. {
  1197. //
  1198. // This irp has not been completed, but has been fully processed.
  1199. // we will complete it now
  1200. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  1201. break;
  1202. }
  1203. case IrpForward:
  1204. case IrpNotWmi:
  1205. {
  1206. //
  1207. // This irp is either not a WMI irp or is a WMI irp targetted
  1208. // at a device lower in the stack.
  1209. IoSkipCurrentIrpStackLocation(Irp);
  1210. status = IoCallDriver(pDevExt->StackDeviceObject, Irp);
  1211. break;
  1212. }
  1213. default:
  1214. {
  1215. //
  1216. // We really should never get here, but if we do just forward....
  1217. ASSERT(FALSE);
  1218. IoSkipCurrentIrpStackLocation(Irp);
  1219. status = IoCallDriver(pDevExt->StackDeviceObject, Irp);
  1220. break;
  1221. }
  1222. }
  1223. return(status);
  1224. }
  1225. //
  1226. // WMI System Call back functions
  1227. //
  1228. NTSTATUS
  1229. UsbSerTossWMIRequest(IN PDEVICE_OBJECT PDevObj, IN PIRP PIrp,
  1230. IN ULONG GuidIndex)
  1231. {
  1232. PDEVICE_EXTENSION pDevExt;
  1233. NTSTATUS status;
  1234. PAGED_CODE();
  1235. pDevExt = (PDEVICE_EXTENSION)PDevObj->DeviceExtension;
  1236. switch (GuidIndex)
  1237. {
  1238. case WMI_SERIAL_PORT_NAME_INFORMATION:
  1239. status = STATUS_INVALID_DEVICE_REQUEST;
  1240. break;
  1241. default:
  1242. status = STATUS_WMI_GUID_NOT_FOUND;
  1243. break;
  1244. }
  1245. status = WmiCompleteRequest(PDevObj, PIrp,
  1246. status, 0, IO_NO_INCREMENT);
  1247. return status;
  1248. }
  1249. NTSTATUS
  1250. UsbSerSetWmiDataItem(IN PDEVICE_OBJECT PDevObj, IN PIRP PIrp,
  1251. IN ULONG GuidIndex, IN ULONG InstanceIndex,
  1252. IN ULONG DataItemId,
  1253. IN ULONG BufferSize, IN PUCHAR PBuffer)
  1254. /*++
  1255. Routine Description:
  1256. This routine is a callback into the driver to set for the contents of
  1257. a data block. When the driver has finished filling the data block it
  1258. must call ClassWmiCompleteRequest to complete the irp. The driver can
  1259. return STATUS_PENDING if the irp cannot be completed immediately.
  1260. Arguments:
  1261. PDevObj is the device whose data block is being queried
  1262. PIrp is the Irp that makes this request
  1263. GuidIndex is the index into the list of guids provided when the
  1264. device registered
  1265. InstanceIndex is the index that denotes which instance of the data block
  1266. is being queried.
  1267. DataItemId has the id of the data item being set
  1268. BufferSize has the size of the data item passed
  1269. PBuffer has the new values for the data item
  1270. Return Value:
  1271. status
  1272. --*/
  1273. {
  1274. PAGED_CODE();
  1275. //
  1276. // Toss this request -- we don't support anything for it
  1277. //
  1278. return UsbSerTossWMIRequest(PDevObj, PIrp, GuidIndex);
  1279. }
  1280. NTSTATUS
  1281. UsbSerSetWmiDataBlock(IN PDEVICE_OBJECT PDevObj, IN PIRP PIrp,
  1282. IN ULONG GuidIndex, IN ULONG InstanceIndex,
  1283. IN ULONG BufferSize,
  1284. IN PUCHAR PBuffer)
  1285. /*++
  1286. Routine Description:
  1287. This routine is a callback into the driver to set the contents of
  1288. a data block. When the driver has finished filling the data block it
  1289. must call ClassWmiCompleteRequest to complete the irp. The driver can
  1290. return STATUS_PENDING if the irp cannot be completed immediately.
  1291. Arguments:
  1292. PDevObj is the device whose data block is being queried
  1293. PIrp is the Irp that makes this request
  1294. GuidIndex is the index into the list of guids provided when the
  1295. device registered
  1296. InstanceIndex is the index that denotes which instance of the data block
  1297. is being queried.
  1298. BufferSize has the size of the data block passed
  1299. PBuffer has the new values for the data block
  1300. Return Value:
  1301. status
  1302. --*/
  1303. {
  1304. PAGED_CODE();
  1305. //
  1306. // Toss this request -- we don't support anything for it
  1307. //
  1308. return UsbSerTossWMIRequest(PDevObj, PIrp, GuidIndex);
  1309. }
  1310. NTSTATUS
  1311. UsbSerQueryWmiDataBlock(IN PDEVICE_OBJECT PDevObj, IN PIRP PIrp,
  1312. IN ULONG GuidIndex,
  1313. IN ULONG InstanceIndex,
  1314. IN ULONG InstanceCount,
  1315. IN OUT PULONG InstanceLengthArray,
  1316. IN ULONG OutBufferSize,
  1317. OUT PUCHAR PBuffer)
  1318. /*++
  1319. Routine Description:
  1320. This routine is a callback into the driver to query for the contents of
  1321. a data block. When the driver has finished filling the data block it
  1322. must call ClassWmiCompleteRequest to complete the irp. The driver can
  1323. return STATUS_PENDING if the irp cannot be completed immediately.
  1324. Arguments:
  1325. PDevObj is the device whose data block is being queried
  1326. PIrp is the Irp that makes this request
  1327. GuidIndex is the index into the list of guids provided when the
  1328. device registered
  1329. InstanceIndex is the index that denotes which instance of the data block
  1330. is being queried.
  1331. InstanceCount is the number of instnaces expected to be returned for
  1332. the data block.
  1333. InstanceLengthArray is a pointer to an array of ULONG that returns the
  1334. lengths of each instance of the data block. If this is NULL then
  1335. there was not enough space in the output buffer to fufill the request
  1336. so the irp should be completed with the buffer needed.
  1337. BufferAvail on has the maximum size available to write the data
  1338. block.
  1339. PBuffer on return is filled with the returned data block
  1340. Return Value:
  1341. status
  1342. --*/
  1343. {
  1344. NTSTATUS status;
  1345. ULONG size = 0;
  1346. PDEVICE_EXTENSION pDevExt
  1347. = (PDEVICE_EXTENSION)PDevObj->DeviceExtension;
  1348. PAGED_CODE();
  1349. switch (GuidIndex) {
  1350. case WMI_SERIAL_PORT_NAME_INFORMATION:
  1351. size = pDevExt->WmiIdentifier.Length;
  1352. if (OutBufferSize < (size + sizeof(USHORT))) {
  1353. size += sizeof(USHORT);
  1354. status = STATUS_BUFFER_TOO_SMALL;
  1355. break;
  1356. }
  1357. if (pDevExt->WmiIdentifier.Buffer == NULL) {
  1358. status = STATUS_INSUFFICIENT_RESOURCES;
  1359. break;
  1360. }
  1361. //
  1362. // First, copy the string over containing our identifier
  1363. //
  1364. *(USHORT *)PBuffer = (USHORT)size;
  1365. (UCHAR *)PBuffer += sizeof(USHORT);
  1366. RtlCopyMemory(PBuffer, pDevExt->WmiIdentifier.Buffer, size);
  1367. //
  1368. // Increment total size to include the WORD containing our len
  1369. //
  1370. size += sizeof(USHORT);
  1371. *InstanceLengthArray = size;
  1372. status = STATUS_SUCCESS;
  1373. break;
  1374. default:
  1375. status = STATUS_WMI_GUID_NOT_FOUND;
  1376. break;
  1377. }
  1378. status = WmiCompleteRequest( PDevObj, PIrp,
  1379. status, size, IO_NO_INCREMENT);
  1380. return status;
  1381. }
  1382. NTSTATUS
  1383. UsbSerQueryWmiRegInfo(IN PDEVICE_OBJECT PDevObj, OUT PULONG PRegFlags,
  1384. OUT PUNICODE_STRING PInstanceName,
  1385. OUT PUNICODE_STRING *PRegistryPath,
  1386. OUT PUNICODE_STRING MofResourceName,
  1387. OUT PDEVICE_OBJECT *Pdo)
  1388. /*++
  1389. Routine Description:
  1390. This routine is a callback into the driver to retrieve information about
  1391. the guids being registered.
  1392. Implementations of this routine may be in paged memory
  1393. Arguments:
  1394. DeviceObject is the device whose registration information is needed
  1395. *RegFlags returns with a set of flags that describe all of the guids being
  1396. registered for this device. If the device wants enable and disable
  1397. collection callbacks before receiving queries for the registered
  1398. guids then it should return the WMIREG_FLAG_EXPENSIVE flag. Also the
  1399. returned flags may specify WMIREG_FLAG_INSTANCE_PDO in which case
  1400. the instance name is determined from the PDO associated with the
  1401. device object. Note that the PDO must have an associated devnode. If
  1402. WMIREG_FLAG_INSTANCE_PDO is not set then Name must return a unique
  1403. name for the device. These flags are ORed into the flags specified
  1404. by the GUIDREGINFO for each guid.
  1405. InstanceName returns with the instance name for the guids if
  1406. WMIREG_FLAG_INSTANCE_PDO is not set in the returned *RegFlags. The
  1407. caller will call ExFreePool with the buffer returned.
  1408. *RegistryPath returns with the registry path of the driver. This is
  1409. required
  1410. *MofResourceName returns with the name of the MOF resource attached to
  1411. the binary file. If the driver does not have a mof resource attached
  1412. then this can be returned as NULL.
  1413. *Pdo returns with the device object for the PDO associated with this
  1414. device if the WMIREG_FLAG_INSTANCE_PDO flag is retured in
  1415. *RegFlags.
  1416. Return Value:
  1417. status
  1418. --*/
  1419. {
  1420. PDEVICE_EXTENSION pDevExt
  1421. = (PDEVICE_EXTENSION)PDevObj->DeviceExtension;
  1422. PAGED_CODE();
  1423. *PRegFlags = WMIREG_FLAG_INSTANCE_PDO;
  1424. *PRegistryPath = &GlobalRegistryPath;
  1425. *Pdo = pDevExt->PhysDeviceObject;
  1426. return STATUS_SUCCESS;
  1427. }
  1428. #endif
  1429.