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.

595 lines
16 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, 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 k;
  168. for (k=0; k< PdoDeviceExtension->DeviceDescription->CompatIdCount; k++) {
  169. Length += (wcslen(PdoDeviceExtension->DeviceDescription->CompatId[k])+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 (k=0; k< PdoDeviceExtension->DeviceDescription->CompatIdCount; k++) {
  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[k]
  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 = STATUS_SUCCESS;
  215. status=IoOpenDeviceRegistryKey(
  216. DeviceObject,
  217. PLUGPLAY_REGKEY_DEVICE,
  218. STANDARD_RIGHTS_READ,
  219. &Handle
  220. );
  221. if (NT_SUCCESS(status)) {
  222. UNICODE_STRING KeyName;
  223. RtlInitUnicodeString(&KeyName,L"PortName");
  224. status = ZwSetValueKey(
  225. Handle,
  226. &KeyName,
  227. 0,
  228. REG_SZ,
  229. L"IR",
  230. sizeof(L"IR")
  231. );
  232. if ( !NT_SUCCESS(status) )
  233. {
  234. D_PNP(DbgPrint("IRENUM : ZwSetValueKey failed : 0x%x\n", status); )
  235. }
  236. ZwClose(Handle);
  237. }
  238. }
  239. break;
  240. }
  241. case IRP_MN_QUERY_STOP_DEVICE:
  242. D_PNP(DbgPrint("IRENUM: PDO: IRP_MN_QUERY_STOP_DEVICE\n");)
  243. // No reason here why we can't stop the device.
  244. // If there were a reason we should speak now for answering success
  245. // here may result in a stop device irp.
  246. status = STATUS_SUCCESS;
  247. break;
  248. case IRP_MN_CANCEL_STOP_DEVICE:
  249. D_PNP(DbgPrint("IRENUM: PDO: IRP_MN_CANCEL_STOP_DEVICE\n");)
  250. //
  251. // The stop was canceled. Whatever state we set, or resources we put
  252. // on hold in anticipation of the forcoming STOP device IRP should be
  253. // put back to normal. Someone, in the long list of concerned parties,
  254. // has failed the stop device query.
  255. //
  256. status = STATUS_SUCCESS;
  257. break;
  258. case IRP_MN_STOP_DEVICE:
  259. D_PNP(DbgPrint("IRENUM: PDO: IRP_MN_STOP_DEVICE\n");)
  260. // Here we shut down the device. The opposite of start.
  261. status = STATUS_SUCCESS;
  262. break;
  263. case IRP_MN_SURPRISE_REMOVAL:
  264. D_PNP(DbgPrint("IRENUM: PDO: IRP_MN_SURPRISE_REMOVAL\n");)
  265. status = STATUS_SUCCESS;
  266. break;
  267. case IRP_MN_REMOVE_DEVICE: {
  268. PFDO_DEVICE_EXTENSION FdoDeviceExtension=PdoDeviceExtension->ParentFdo->DeviceExtension;
  269. D_PNP(DbgPrint("IRENUM: PDO: IRP_MN_REMOVE_DEVICE: %08lx\n",DeviceObject);)
  270. RemoveDevice(FdoDeviceExtension->EnumHandle,PdoDeviceExtension->DeviceDescription);
  271. status=STATUS_SUCCESS;
  272. }
  273. break;
  274. case IRP_MN_QUERY_REMOVE_DEVICE:
  275. D_PNP(DbgPrint("IRENUM: PDO: IRP_MN_QUERY_REMOVE_DEVICE\n");)
  276. //
  277. // Just like Query Stop only now the impending doom is the remove irp
  278. //
  279. status = STATUS_SUCCESS;
  280. break;
  281. case IRP_MN_CANCEL_REMOVE_DEVICE:
  282. D_PNP(DbgPrint("IRENUM: PDO: IRP_MN_CANCEL_REMOVE_DEVICE\n");)
  283. //
  284. // Clean up a remove that did not go through, just like cancel STOP.
  285. //
  286. status = STATUS_SUCCESS;
  287. break;
  288. case IRP_MN_READ_CONFIG:
  289. D_PNP(DbgPrint("IRENUM: PDO: IRP_MN_READ_CONFIG: Space=%d\n",IrpSp->Parameters.ReadWriteConfig.WhichSpace);)
  290. switch ( IrpSp->Parameters.ReadWriteConfig.WhichSpace ) {
  291. case IRENUM_CONFIG_SPACE_INFO:
  292. if ((IrpSp->Parameters.ReadWriteConfig.Length >= sizeof(IRCOMM_BUS_INFO))) {
  293. IRCOMM_BUS_INFO BusInfo;
  294. BusInfo.DeviceAddress= PdoDeviceExtension->DeviceDescription->DeviceId;
  295. BusInfo.OutGoingConnection=!PdoDeviceExtension->DeviceDescription->Static;
  296. RtlCopyMemory(
  297. IrpSp->Parameters.ReadWriteConfig.Buffer,
  298. &BusInfo,
  299. sizeof(BusInfo)
  300. );
  301. status = STATUS_SUCCESS;
  302. Irp->IoStatus.Information=sizeof(BusInfo);
  303. break;
  304. }
  305. status=STATUS_BUFFER_TOO_SMALL;
  306. break;
  307. default:
  308. break;
  309. }
  310. break;
  311. case IRP_MN_QUERY_BUS_INFORMATION: {
  312. PPNP_BUS_INFORMATION BusInfo;
  313. BusInfo = ALLOCATE_PAGED_POOL( sizeof(*BusInfo));
  314. if (BusInfo != NULL) {
  315. BusInfo->BusTypeGuid = GUID_BUS_TYPE_IRDA;
  316. BusInfo->LegacyBusType=PNPBus;
  317. BusInfo->BusNumber=0;
  318. Irp->IoStatus.Information=(ULONG_PTR)BusInfo;
  319. status = STATUS_SUCCESS;
  320. } else {
  321. status=STATUS_INSUFFICIENT_RESOURCES;
  322. }
  323. break;
  324. }
  325. case IRP_MN_QUERY_DEVICE_RELATIONS: {
  326. PDEVICE_RELATIONS CurrentRelations;
  327. switch (IrpSp->Parameters.QueryDeviceRelations.Type) {
  328. case TargetDeviceRelation:
  329. CurrentRelations=ALLOCATE_PAGED_POOL(sizeof(DEVICE_RELATIONS));
  330. if (CurrentRelations != NULL) {
  331. ObReferenceObject(DeviceObject);
  332. CurrentRelations->Objects[0]=DeviceObject;
  333. CurrentRelations->Count=1;
  334. Irp->IoStatus.Information=(ULONG_PTR)CurrentRelations;
  335. status=STATUS_SUCCESS;
  336. } else {
  337. status=STATUS_INSUFFICIENT_RESOURCES;
  338. }
  339. break;
  340. default:
  341. break;
  342. }
  343. break;
  344. }
  345. default:
  346. //
  347. // we aren't handling this irp
  348. // just complete it
  349. //
  350. break;
  351. }
  352. //
  353. // the irp has been handled in some way or the other
  354. // complete it now
  355. //
  356. Irp->IoStatus.Status = status;
  357. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  358. return status;
  359. }
  360. NTSTATUS
  361. IrEnumPdoPower(
  362. IN PDEVICE_OBJECT DeviceObject,
  363. IN PIRP Irp
  364. )
  365. {
  366. NTSTATUS Status=Irp->IoStatus.Status;
  367. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
  368. PAGED_CODE();
  369. D_POWER(DbgPrint("IRENUM: PDO: Power IRP, MN func=%d\n",irpSp->MinorFunction);)
  370. PoStartNextPowerIrp(Irp);
  371. switch (irpSp->MinorFunction) {
  372. case IRP_MN_SET_POWER:
  373. case IRP_MN_QUERY_POWER:
  374. //
  375. // we under stand these two
  376. //
  377. Status=STATUS_SUCCESS;
  378. break;
  379. default:
  380. //
  381. // don't do wait wake or others
  382. //
  383. break;
  384. }
  385. Irp->IoStatus.Status = Status;
  386. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  387. return Status;
  388. }
  389. NTSTATUS
  390. IrEnumPdoWmi(
  391. IN PDEVICE_OBJECT DeviceObject,
  392. IN PIRP Irp
  393. )
  394. {
  395. NTSTATUS Status=Irp->IoStatus.Status;
  396. D_WMI(DbgPrint("IRENUM: PDO: Wmi\n");)
  397. IoCompleteRequest (Irp, IO_NO_INCREMENT);
  398. return Status;
  399. }