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.

573 lines
15 KiB

  1. #include <internal.h>
  2. #define INITGUID
  3. #include <guiddef.h>
  4. #include <wdmguid.h>
  5. #pragma alloc_text(PAGE,IrEnumPdoPnp)
  6. #pragma alloc_text(PAGE,IrEnumPdoPower)
  7. #pragma alloc_text(PAGE,IrEnumPdoWmi)
  8. #define CHILD_DEVICE_TEXT L"IR Communication Device"
  9. #define HARDWARE_ID_PREFIX L"IRENUM\\"
  10. //#define HARDWARE_ID L"IRENUM\\PNP0501"
  11. NTSTATUS
  12. IrEnumPdoPnp (
  13. IN PDEVICE_OBJECT DeviceObject,
  14. IN PIRP Irp
  15. )
  16. /*++
  17. Routine Description:
  18. Handle requests from the PlugPlay system for the devices on the BUS
  19. --*/
  20. {
  21. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
  22. PPDO_DEVICE_EXTENSION PdoDeviceExtension=DeviceObject->DeviceExtension;
  23. PDEVICE_CAPABILITIES deviceCapabilities;
  24. ULONG information;
  25. PWCHAR buffer=NULL;
  26. ULONG length, i, j;
  27. NTSTATUS status;
  28. PAGED_CODE ();
  29. status = Irp->IoStatus.Status;
  30. switch (IrpSp->MinorFunction) {
  31. case IRP_MN_QUERY_CAPABILITIES:
  32. D_PNP(DbgPrint("IRENUM: PDO: IRP_MN_QUERY_CAPABILITIES\n");)
  33. //
  34. // Get the packet.
  35. //
  36. deviceCapabilities=IrpSp->Parameters.DeviceCapabilities.Capabilities;
  37. //
  38. // Set the capabilities.
  39. //
  40. deviceCapabilities->Version = 1;
  41. deviceCapabilities->Size = sizeof (DEVICE_CAPABILITIES);
  42. // We cannot wake the system.
  43. deviceCapabilities->SystemWake = PowerSystemUnspecified;
  44. deviceCapabilities->DeviceWake = PowerDeviceUnspecified;
  45. // We have no latencies
  46. deviceCapabilities->D1Latency = 0;
  47. deviceCapabilities->D2Latency = 0;
  48. deviceCapabilities->D3Latency = 0;
  49. // No locking or ejection
  50. deviceCapabilities->LockSupported = FALSE;
  51. deviceCapabilities->EjectSupported = FALSE;
  52. // Device can be physically removed.
  53. // Technically there is no physical device to remove, but this bus
  54. // driver can yank the PDO from the PlugPlay system, when ever it
  55. // receives an IOCTL_SERENUM_REMOVE_PORT device control command.
  56. // deviceCapabilities->Removable = TRUE;
  57. deviceCapabilities->SurpriseRemovalOK=TRUE;
  58. if (PdoDeviceExtension->DeviceDescription->Printer) {
  59. //
  60. // there is no server for printers
  61. //
  62. deviceCapabilities->RawDeviceOK=TRUE;
  63. }
  64. // not Docking device
  65. deviceCapabilities->DockDevice = FALSE;
  66. // deviceCapabilities->UniqueID = TRUE;
  67. status = STATUS_SUCCESS;
  68. break;
  69. case IRP_MN_QUERY_DEVICE_TEXT:
  70. if (IrpSp->Parameters.QueryDeviceText.DeviceTextType == DeviceTextDescription) {
  71. ULONG BufferLength=0;
  72. if (PdoDeviceExtension->DeviceDescription->Name != NULL) {
  73. BufferLength += wcslen(PdoDeviceExtension->DeviceDescription->Name)*sizeof(WCHAR);
  74. }
  75. if (BufferLength > 0) {
  76. //
  77. // we have a name or manufacturer
  78. //
  79. buffer=ALLOCATE_PAGED_POOL((BufferLength+sizeof(UNICODE_NULL)+sizeof(L" ")));
  80. if (buffer != NULL) {
  81. buffer[0]=L'\0';
  82. if (PdoDeviceExtension->DeviceDescription->Name != NULL) {
  83. wcscat(buffer,PdoDeviceExtension->DeviceDescription->Name);
  84. }
  85. status=STATUS_SUCCESS;
  86. } else {
  87. status=STATUS_INSUFFICIENT_RESOURCES;
  88. }
  89. } else {
  90. //
  91. // no pnp info, just make something up
  92. //
  93. buffer=ALLOCATE_PAGED_POOL(sizeof(CHILD_DEVICE_TEXT));
  94. if (buffer != NULL) {
  95. RtlCopyMemory(buffer,CHILD_DEVICE_TEXT,sizeof(CHILD_DEVICE_TEXT));
  96. status=STATUS_SUCCESS;
  97. } else {
  98. status=STATUS_INSUFFICIENT_RESOURCES;
  99. }
  100. }
  101. Irp->IoStatus.Status=status;
  102. Irp->IoStatus.Information = (ULONG_PTR) buffer;
  103. }
  104. break;
  105. case IRP_MN_QUERY_ID:
  106. D_PNP(DbgPrint("IRENUM: PDO: IRP_MN_QUERY_ID\n");)
  107. // Query the IDs of the device
  108. switch (IrpSp->Parameters.QueryId.IdType) {
  109. case BusQueryInstanceID: {
  110. //
  111. // Build an instance ID. This is what PnP uses to tell if it has
  112. // seen this thing before or not.
  113. //
  114. ULONG Length;
  115. Length=wcslen(PdoDeviceExtension->DeviceDescription->DeviceName)*sizeof(WCHAR);
  116. buffer = ALLOCATE_PAGED_POOL( Length + sizeof(WCHAR));
  117. if (buffer) {
  118. RtlZeroMemory(buffer, Length + sizeof(WCHAR));
  119. RtlCopyMemory (buffer, PdoDeviceExtension->DeviceDescription->DeviceName, Length);
  120. status=STATUS_SUCCESS;
  121. } else {
  122. status=STATUS_NO_MEMORY;
  123. }
  124. Irp->IoStatus.Status=status;
  125. Irp->IoStatus.Information = (ULONG_PTR) buffer;
  126. break;
  127. }
  128. case BusQueryDeviceID:
  129. case BusQueryHardwareIDs: {
  130. //
  131. // return a multi WCHAR (null terminated) string (null terminated)
  132. // array for use in matching hardare ids in inf files;
  133. //
  134. //
  135. // the device reported and hardware id
  136. //
  137. ULONG Length;
  138. //
  139. // figure out the length, it is multi sz so we need a double null,
  140. //
  141. Length=wcslen(PdoDeviceExtension->DeviceDescription->HardwareId)*sizeof(WCHAR) + (sizeof(UNICODE_NULL)*2) + sizeof(HARDWARE_ID_PREFIX);
  142. buffer = ALLOCATE_PAGED_POOL( Length );
  143. if (buffer != NULL) {
  144. //
  145. // build the hardware is by concatenating irenuum\ with the value retuned by the device
  146. //
  147. RtlZeroMemory(buffer,Length);
  148. if ((IrpSp->Parameters.QueryId.IdType == BusQueryDeviceID) || !PdoDeviceExtension->DeviceDescription->Printer) {
  149. //
  150. // prepend IRENUM\ for the device ID always and for the HARDWARE id when it isn't a printer
  151. //
  152. wcscpy(buffer,HARDWARE_ID_PREFIX);
  153. }
  154. wcscat(buffer,PdoDeviceExtension->DeviceDescription->HardwareId);
  155. status=STATUS_SUCCESS;
  156. } else {
  157. status=STATUS_NO_MEMORY;
  158. }
  159. Irp->IoStatus.Information = (ULONG_PTR) buffer;
  160. break;
  161. }
  162. case BusQueryCompatibleIDs: {
  163. //
  164. // The generic ids for installation of this pdo.
  165. //
  166. ULONG Length=0;
  167. LONG i;
  168. for (i=0; i< PdoDeviceExtension->DeviceDescription->CompatIdCount; i++) {
  169. Length += (wcslen(PdoDeviceExtension->DeviceDescription->CompatId[i])+1)*sizeof(WCHAR)+sizeof(IRENUM_PREFIX);
  170. }
  171. Length += sizeof(WCHAR)*2;
  172. buffer = ALLOCATE_PAGED_POOL(Length);
  173. if (buffer != NULL) {
  174. LONG Index=0;
  175. RtlZeroMemory (buffer, Length);
  176. for (i=0; i< PdoDeviceExtension->DeviceDescription->CompatIdCount; i++) {
  177. if (!PdoDeviceExtension->DeviceDescription->Printer) {
  178. //
  179. // for printers we don't prepend our enumerator name
  180. //
  181. wcscpy(&buffer[Index],IRENUM_PREFIX);
  182. }
  183. wcscat(
  184. &buffer[Index],
  185. PdoDeviceExtension->DeviceDescription->CompatId[i]
  186. );
  187. //
  188. // figure out where the next string should go
  189. //
  190. Index += wcslen(&buffer[Index]) +1 ;
  191. }
  192. status = STATUS_SUCCESS;
  193. } else {
  194. status=STATUS_INSUFFICIENT_RESOURCES;
  195. }
  196. Irp->IoStatus.Information = (ULONG_PTR) buffer;
  197. break;
  198. }
  199. break;
  200. default:
  201. //
  202. // not supported
  203. //
  204. break;
  205. }
  206. break;
  207. case IRP_MN_START_DEVICE: {
  208. D_PNP(DbgPrint("IRENUM: PDO: IRP_MN_START_DEVICE\n");)
  209. if (PdoDeviceExtension->DeviceDescription->Printer) {
  210. //
  211. // Need to set a value in the devices parameters key for printers
  212. //
  213. HANDLE Handle;
  214. status=IoOpenDeviceRegistryKey(
  215. DeviceObject,
  216. PLUGPLAY_REGKEY_DEVICE,
  217. STANDARD_RIGHTS_READ,
  218. &Handle
  219. );
  220. if (NT_SUCCESS(status)) {
  221. UNICODE_STRING KeyName;
  222. RtlInitUnicodeString(&KeyName,L"PortName");
  223. ZwSetValueKey(
  224. Handle,
  225. &KeyName,
  226. 0,
  227. REG_SZ,
  228. L"IR",
  229. sizeof(L"IR")
  230. );
  231. ZwClose(Handle);
  232. }
  233. }
  234. status = STATUS_SUCCESS;
  235. break;
  236. }
  237. case IRP_MN_QUERY_STOP_DEVICE:
  238. D_PNP(DbgPrint("IRENUM: PDO: IRP_MN_QUERY_STOP_DEVICE\n");)
  239. // No reason here why we can't stop the device.
  240. // If there were a reason we should speak now for answering success
  241. // here may result in a stop device irp.
  242. status = STATUS_SUCCESS;
  243. break;
  244. case IRP_MN_CANCEL_STOP_DEVICE:
  245. D_PNP(DbgPrint("IRENUM: PDO: IRP_MN_CANCEL_STOP_DEVICE\n");)
  246. //
  247. // The stop was canceled. Whatever state we set, or resources we put
  248. // on hold in anticipation of the forcoming STOP device IRP should be
  249. // put back to normal. Someone, in the long list of concerned parties,
  250. // has failed the stop device query.
  251. //
  252. status = STATUS_SUCCESS;
  253. break;
  254. case IRP_MN_STOP_DEVICE:
  255. D_PNP(DbgPrint("IRENUM: PDO: IRP_MN_STOP_DEVICE\n");)
  256. // Here we shut down the device. The opposite of start.
  257. status = STATUS_SUCCESS;
  258. break;
  259. case IRP_MN_SURPRISE_REMOVAL:
  260. D_PNP(DbgPrint("IRENUM: PDO: IRP_MN_SURPRISE_REMOVAL\n");)
  261. status = STATUS_SUCCESS;
  262. break;
  263. case IRP_MN_REMOVE_DEVICE: {
  264. PFDO_DEVICE_EXTENSION FdoDeviceExtension=PdoDeviceExtension->ParentFdo->DeviceExtension;
  265. D_PNP(DbgPrint("IRENUM: PDO: IRP_MN_REMOVE_DEVICE: %08lx\n",DeviceObject);)
  266. RemoveDevice(FdoDeviceExtension->EnumHandle,PdoDeviceExtension->DeviceDescription);
  267. status=STATUS_SUCCESS;
  268. }
  269. break;
  270. case IRP_MN_QUERY_REMOVE_DEVICE:
  271. D_PNP(DbgPrint("IRENUM: PDO: IRP_MN_QUERY_REMOVE_DEVICE\n");)
  272. //
  273. // Just like Query Stop only now the impending doom is the remove irp
  274. //
  275. status = STATUS_SUCCESS;
  276. break;
  277. case IRP_MN_CANCEL_REMOVE_DEVICE:
  278. D_PNP(DbgPrint("IRENUM: PDO: IRP_MN_CANCEL_REMOVE_DEVICE\n");)
  279. //
  280. // Clean up a remove that did not go through, just like cancel STOP.
  281. //
  282. status = STATUS_SUCCESS;
  283. break;
  284. case IRP_MN_READ_CONFIG:
  285. D_PNP(DbgPrint("IRENUM: PDO: IRP_MN_READ_CONFIG: Space=%d\n",IrpSp->Parameters.ReadWriteConfig.WhichSpace);)
  286. switch ( IrpSp->Parameters.ReadWriteConfig.WhichSpace ) {
  287. case IRENUM_CONFIG_SPACE_INFO:
  288. if ((IrpSp->Parameters.ReadWriteConfig.Length >= sizeof(IRCOMM_BUS_INFO))) {
  289. IRCOMM_BUS_INFO BusInfo;
  290. BusInfo.DeviceAddress= PdoDeviceExtension->DeviceDescription->DeviceId;
  291. BusInfo.OutGoingConnection=!PdoDeviceExtension->DeviceDescription->Static;
  292. RtlCopyMemory(
  293. IrpSp->Parameters.ReadWriteConfig.Buffer,
  294. &BusInfo,
  295. sizeof(BusInfo)
  296. );
  297. status = STATUS_SUCCESS;
  298. Irp->IoStatus.Information=sizeof(BusInfo);
  299. break;
  300. }
  301. status=STATUS_BUFFER_TOO_SMALL;
  302. break;
  303. default:
  304. break;
  305. }
  306. break;
  307. case IRP_MN_QUERY_BUS_INFORMATION: {
  308. PPNP_BUS_INFORMATION BusInfo;
  309. BusInfo = ALLOCATE_PAGED_POOL( sizeof(*BusInfo));
  310. if (BusInfo != NULL) {
  311. BusInfo->BusTypeGuid = GUID_BUS_TYPE_IRDA;
  312. BusInfo->LegacyBusType=PNPBus;
  313. BusInfo->BusNumber=0;
  314. Irp->IoStatus.Information=(ULONG_PTR)BusInfo;
  315. status = STATUS_SUCCESS;
  316. } else {
  317. status=STATUS_INSUFFICIENT_RESOURCES;
  318. }
  319. break;
  320. }
  321. case IRP_MN_QUERY_DEVICE_RELATIONS: {
  322. PDEVICE_RELATIONS CurrentRelations;
  323. switch (IrpSp->Parameters.QueryDeviceRelations.Type) {
  324. case TargetDeviceRelation:
  325. CurrentRelations=ALLOCATE_PAGED_POOL(sizeof(DEVICE_RELATIONS));
  326. if (CurrentRelations != NULL) {
  327. ObReferenceObject(DeviceObject);
  328. CurrentRelations->Objects[0]=DeviceObject;
  329. CurrentRelations->Count=1;
  330. Irp->IoStatus.Information=(ULONG_PTR)CurrentRelations;
  331. status=STATUS_SUCCESS;
  332. } else {
  333. status=STATUS_INSUFFICIENT_RESOURCES;
  334. }
  335. break;
  336. default:
  337. break;
  338. }
  339. break;
  340. }
  341. default:
  342. //
  343. // we aren't handling this irp
  344. // just complete it
  345. //
  346. break;
  347. }
  348. //
  349. // the irp has been handled in some way or the other
  350. // complete it now
  351. //
  352. Irp->IoStatus.Status = status;
  353. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  354. return status;
  355. }
  356. NTSTATUS
  357. IrEnumPdoPower(
  358. IN PDEVICE_OBJECT DeviceObject,
  359. IN PIRP Irp
  360. )
  361. {
  362. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
  363. PAGED_CODE();
  364. D_POWER(DbgPrint("IRENUM: PDO: Power IRP, MN func=%d\n",irpSp->MinorFunction);)
  365. PoStartNextPowerIrp(Irp);
  366. Irp->IoStatus.Status = STATUS_SUCCESS;
  367. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  368. return STATUS_SUCCESS;
  369. }
  370. NTSTATUS
  371. IrEnumPdoWmi(
  372. IN PDEVICE_OBJECT DeviceObject,
  373. IN PIRP Irp
  374. )
  375. {
  376. NTSTATUS Status=Irp->IoStatus.Status;
  377. D_WMI(DbgPrint("IRENUM: PDO: Wmi\n");)
  378. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  379. return Status;
  380. }