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.

483 lines
15 KiB

  1. // @doc
  2. /**********************************************************************
  3. *
  4. * @module SWVB_PnP.cpp |
  5. *
  6. * Power and PnP handlers for SWVB Virtual Devices
  7. *
  8. * History
  9. * ----------------------------------------------------------
  10. * Mitchell S. Dernis Original
  11. *
  12. * (c) 1986-1998 Microsoft Corporation. All right reserved.
  13. *
  14. * @topic SWVB_PnP |
  15. * Power and PnP IRPs are handled here as if for a PDO
  16. **********************************************************************/
  17. #define __DEBUG_MODULE_IN_USE__ GCK_SWVB_PNP_C
  18. extern "C"
  19. {
  20. #include <WDM.H>
  21. #include "GckShell.h"
  22. #include "debug.h"
  23. DECLARE_MODULE_DEBUG_LEVEL((DBG_WARN|DBG_ERROR|DBG_CRITICAL));
  24. //DECLARE_MODULE_DEBUG_LEVEL((DBG_ALL));
  25. }
  26. #include "SWVBENUM.h"
  27. #include <stdio.h>
  28. /***********************************************************************************
  29. **
  30. ** NTSTATUS GCK_SWVB_PnP(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
  31. **
  32. ** @func Handles IRP_MJ_PNP for Virtual Devices.
  33. **
  34. ** @rdesc STATUS_SUCCESS, or various errors
  35. **
  36. *************************************************************************************/
  37. NTSTATUS GCK_SWVB_PnP
  38. (
  39. IN PDEVICE_OBJECT pDeviceObject, // @parm Device Object for our context
  40. IN PIRP pIrp // @parm IRP to handle
  41. )
  42. {
  43. NTSTATUS NtStatus;
  44. PIO_STACK_LOCATION pIrpStack;
  45. PSWVB_PDO_EXT pPdoExt;
  46. PDEVICE_CAPABILITIES pDeviceCapabilities;
  47. PAGED_CODE ();
  48. GCK_DBG_ENTRY_PRINT(("Entering GCK_SWVB_PnP\n"));
  49. //
  50. // By default we will not change the status
  51. //
  52. NtStatus = pIrp->IoStatus.Status;
  53. //
  54. // PDO Device Extension
  55. //
  56. pPdoExt = (PSWVB_PDO_EXT) pDeviceObject->DeviceExtension;
  57. ASSERT( GCK_DO_TYPE_SWVB == pPdoExt->ulGckDevObjType);
  58. pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  59. GCK_IncRemoveLock(&pPdoExt->RemoveLock);
  60. //
  61. // Handle by Minor IRP code
  62. //
  63. switch (pIrpStack->MinorFunction) {
  64. case IRP_MN_START_DEVICE:
  65. GCK_DBG_TRACE_PRINT(("IRP_MN_START_DEVICE\n"));
  66. pPdoExt->fStarted = TRUE;
  67. pPdoExt->fRemoved = FALSE;
  68. //Give virtual device a chance at the IRP
  69. if(pPdoExt->pServiceTable->pfnStart)
  70. {
  71. NtStatus = pPdoExt->pServiceTable->pfnStart(pDeviceObject, pIrp);
  72. }
  73. else
  74. {
  75. NtStatus = STATUS_SUCCESS;
  76. }
  77. break;
  78. case IRP_MN_STOP_DEVICE:
  79. GCK_DBG_TRACE_PRINT(("IRP_MN_STOP_DEVICE\n"));
  80. pPdoExt->fStarted = FALSE;
  81. //Give virtual device a chance at the IRP
  82. if(pPdoExt->pServiceTable->pfnStop)
  83. {
  84. NtStatus = pPdoExt->pServiceTable->pfnStop(pDeviceObject, pIrp);
  85. }
  86. else
  87. {
  88. NtStatus = STATUS_SUCCESS;
  89. }
  90. break;
  91. case IRP_MN_REMOVE_DEVICE:
  92. GCK_DBG_TRACE_PRINT(("IRP_MN_REMOVE_DEVICE\n"));
  93. //We are not setup to handle remove twice.
  94. if(pPdoExt->fRemoved)
  95. {
  96. pIrp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
  97. IoCompleteRequest (pIrp, IO_NO_INCREMENT);
  98. GCK_DBG_EXIT_PRINT(("Exiting GCK_SWVB_PnP STATUS_NO_SUCH_DEVICE on remove\n"));
  99. return STATUS_NO_SUCH_DEVICE;
  100. }
  101. //Sometimes we get a remove without a stop, so do the stop stuff if necessary
  102. if(pPdoExt->fStarted)
  103. {
  104. pPdoExt->fStarted = FALSE;
  105. //Give virtual device a chance at the IRP
  106. if(pPdoExt->pServiceTable->pfnStop)
  107. {
  108. NtStatus = pPdoExt->pServiceTable->pfnStop(pDeviceObject, pIrp);
  109. }
  110. }
  111. // We will no longer receive requests for this device as it has been removed.
  112. pPdoExt->fRemoved = TRUE;
  113. // Undo our increment upon entry to this routine
  114. GCK_DecRemoveLock(&pPdoExt->RemoveLock);
  115. //We may have ordered this removal, or the PnP system
  116. //may just be rearranging things for us. If we ordered it,
  117. //we need to cleanup, and give the virtual device a chance
  118. //to cleanup. If the PnP system is rearranging things we nod
  119. //back, sure it is removed, and pretty much ignore it.
  120. if(!pPdoExt->fAttached)
  121. {
  122. // Give virtual device a chance at the IRP
  123. if(pPdoExt->pServiceTable->pfnRemove)
  124. {
  125. NtStatus = pPdoExt->pServiceTable->pfnRemove(pDeviceObject, pIrp);
  126. }
  127. // failure to succeed is pretty darn serious
  128. if(!NT_SUCCESS(NtStatus))
  129. {
  130. ASSERT(FALSE); /** ?? **/
  131. GCK_DBG_CRITICAL_PRINT(("Virtual Device had the gall to fail remove!\n"));
  132. return NtStatus;
  133. }
  134. // free memory for storing the HardwareID
  135. ASSERT(pPdoExt->pmwszHardwareID);
  136. ExFreePool(pPdoExt->pmwszHardwareID);
  137. //
  138. // Undo the bias Irp count so it can go to zero
  139. // if this does not take it to zero, we have to wait
  140. // until it goes to zero, forever.
  141. //
  142. GCK_DecRemoveLockAndWait(&pPdoExt->RemoveLock, NULL);
  143. // Delete this device, if the open count is zero
  144. if( 0 == pPdoExt->ulOpenCount )
  145. {
  146. ObDereferenceObject(pDeviceObject);
  147. IoDeleteDevice(pDeviceObject);
  148. }
  149. }
  150. // Must succeed this
  151. pIrp->IoStatus.Status = STATUS_SUCCESS;
  152. IoCompleteRequest (pIrp, IO_NO_INCREMENT);
  153. GCK_DBG_EXIT_PRINT(("Exiting GCK_SWVB_PnP succeeding remove\n"));
  154. return STATUS_SUCCESS;
  155. case IRP_MN_QUERY_DEVICE_RELATIONS:
  156. GCK_DBG_TRACE_PRINT(("IRP_MN_QUERY_DEVICE_RELATIONS: Type = %d\n",
  157. pIrpStack->Parameters.QueryDeviceRelations.Type));
  158. // TargetDeviceRelation just wants to know who the PDO is, and it
  159. // is us so we handle it.
  160. if (TargetDeviceRelation == pIrpStack->Parameters.QueryDeviceRelations.Type)
  161. {
  162. PDEVICE_RELATIONS pDeviceRelations;
  163. GCK_DBG_TRACE_PRINT(("TargetDeviceRelations\n"));
  164. pDeviceRelations = (PDEVICE_RELATIONS) pIrp->IoStatus.Information;
  165. if (!pDeviceRelations)
  166. {
  167. pDeviceRelations = (PDEVICE_RELATIONS)EX_ALLOCATE_POOL(PagedPool, sizeof(DEVICE_RELATIONS));
  168. if (!pDeviceRelations) {
  169. GCK_DBG_ERROR_PRINT(("Couldn' allocate DEVICE_RELATIONS for TargetDevice!!\n"));
  170. NtStatus = STATUS_INSUFFICIENT_RESOURCES;
  171. break;
  172. }
  173. }
  174. else if (pDeviceRelations->Count != 0)
  175. {
  176. ULONG uIndex;
  177. // Nobody but the PDO should be setting this value!
  178. ASSERT(pDeviceRelations->Count == 0);
  179. //
  180. // Deref any objects that were previously in the list
  181. // This code copied out of some system code (gameenum perhaps)
  182. // Seems like this code should not be necessary, but what the
  183. // hell? It does no harm.
  184. for( uIndex= 0; uIndex< pDeviceRelations->Count; uIndex++)
  185. {
  186. ObDereferenceObject(pDeviceRelations->Objects[uIndex]);
  187. pDeviceRelations->Objects[uIndex] = NULL;
  188. }
  189. }
  190. pDeviceRelations->Count = 1;
  191. pDeviceRelations->Objects[0] = pDeviceObject;
  192. ObReferenceObject(pDeviceObject);
  193. NtStatus = STATUS_SUCCESS;
  194. pIrp->IoStatus.Information = (ULONG) pDeviceRelations;
  195. break;
  196. }
  197. //
  198. // Fall through
  199. //
  200. NtStatus = pIrp->IoStatus.Status;
  201. break;
  202. case IRP_MN_QUERY_CAPABILITIES:
  203. GCK_DBG_TRACE_PRINT(("IRP_MN_QUERY_CAPABILITIES\n"));
  204. // Get the packet.
  205. pDeviceCapabilities=pIrpStack->Parameters.DeviceCapabilities.Capabilities;
  206. // Set the capabilities.
  207. pDeviceCapabilities->Version = 1;
  208. pDeviceCapabilities->Size = sizeof (DEVICE_CAPABILITIES);
  209. // BUG If we get a virtual keystroke it would be nice
  210. // BUG to shut off the screen saver. Not sure if this
  211. // BUG is related or not.
  212. pDeviceCapabilities->SystemWake = PowerSystemUnspecified;
  213. pDeviceCapabilities->DeviceWake = PowerDeviceUnspecified;
  214. // We have no latencies
  215. pDeviceCapabilities->D1Latency = 0;
  216. pDeviceCapabilities->D2Latency = 0;
  217. pDeviceCapabilities->D3Latency = 0;
  218. // No locking or ejection
  219. pDeviceCapabilities->LockSupported = FALSE;
  220. pDeviceCapabilities->EjectSupported = FALSE;
  221. // Device can be physically removed.
  222. // Technically there is no physical device to remove, but this bus
  223. // driver can yank the PDO from the PlugPlay system, whenever
  224. // the last joystick goes away.
  225. pDeviceCapabilities->Removable = TRUE;
  226. pDeviceCapabilities->SurpriseRemovalOK = TRUE;
  227. //This will force HIDSwvd.sys to be loaded
  228. pDeviceCapabilities->RawDeviceOK = FALSE;
  229. //Should surpress most UI
  230. pDeviceCapabilities->SilentInstall = TRUE;
  231. // not Docking device
  232. pDeviceCapabilities->DockDevice = FALSE;
  233. //We want to avoid having PnP attach some extra info.
  234. //So impose that only one bus can be on the system at a time.
  235. pDeviceCapabilities->UniqueID = TRUE;
  236. NtStatus = STATUS_SUCCESS;
  237. break;
  238. case IRP_MN_QUERY_ID:
  239. GCK_DBG_TRACE_PRINT(("IRP_MN_QUERY_ID\n"));
  240. //
  241. // Handle by type of ID requested
  242. //
  243. switch (pIrpStack->Parameters.QueryId.IdType)
  244. {
  245. case BusQueryDeviceID:
  246. // this can be the same as the hardware ids (which requires a multi
  247. // sz) ... we are just allocating more than enough memory
  248. case BusQueryHardwareIDs:
  249. {
  250. ULONG ulLength;
  251. ULONG ulTotalLength;
  252. PWCHAR pmwszBuffer;
  253. // return a multi WCHAR (null terminated) string (null terminated)
  254. // array for use in matching hardare ids in inf files;
  255. ulLength = MultiSzWByteLength(pPdoExt->pmwszHardwareID);
  256. ulTotalLength = ulLength + sizeof(SWVB_BUS_ID);
  257. pmwszBuffer = (PWCHAR)EX_ALLOCATE_POOL(PagedPool, ulTotalLength);
  258. if (pmwszBuffer)
  259. {
  260. RtlCopyMemory (pmwszBuffer, SWVB_BUS_ID, sizeof(SWVB_BUS_ID));
  261. //The sizeof(WCHAR) is so that we chomp over the terminating UNICODE_NULL.
  262. RtlCopyMemory ( (PCHAR)pmwszBuffer + sizeof(SWVB_BUS_ID) - sizeof(WCHAR), pPdoExt->pmwszHardwareID, ulLength);
  263. NtStatus = STATUS_SUCCESS;
  264. }
  265. else
  266. {
  267. NtStatus = STATUS_INSUFFICIENT_RESOURCES;
  268. }
  269. GCK_DBG_TRACE_PRINT(("First HardwareIDs is %ws\n", pmwszBuffer));
  270. pIrp->IoStatus.Information = (ULONG) pmwszBuffer;
  271. break;
  272. }
  273. case BusQueryInstanceID:
  274. {
  275. //
  276. ULONG ulLength;
  277. PWCHAR pmwszBuffer;
  278. ulLength = MultiSzWByteLength(pPdoExt->pmwszHardwareID) + sizeof(SWVB_INSTANCE_EXT);
  279. pmwszBuffer = (PWCHAR)EX_ALLOCATE_POOL (PagedPool, ulLength);
  280. if (pmwszBuffer)
  281. {
  282. swprintf(pmwszBuffer, SWVB_INSTANCE_ID_TMPLT, pPdoExt->pmwszHardwareID, pPdoExt->ulInstanceNumber);
  283. NtStatus = STATUS_SUCCESS;
  284. }
  285. else
  286. {
  287. NtStatus = STATUS_INSUFFICIENT_RESOURCES;
  288. }
  289. GCK_DBG_TRACE_PRINT(("Instance ID is %ws\n", pmwszBuffer));
  290. pIrp->IoStatus.Information = (ULONG) pmwszBuffer;
  291. break;
  292. }
  293. case BusQueryCompatibleIDs:
  294. pIrp->IoStatus.Information = 0;
  295. NtStatus = STATUS_NOT_SUPPORTED;
  296. break;
  297. }
  298. break;
  299. case IRP_MN_QUERY_PNP_DEVICE_STATE:
  300. GCK_DBG_TRACE_PRINT(("IRP_MN_QUERY_PNP_DEVICE_STATE\n"));
  301. NtStatus = STATUS_SUCCESS;
  302. break;
  303. case IRP_MN_SURPRISE_REMOVAL:
  304. GCK_DBG_TRACE_PRINT(("IRP_MN_SURPRISE_REMOVAL\n"));
  305. // BUGBUG we may need to know that this happened in the future
  306. NtStatus = STATUS_SUCCESS;
  307. break;
  308. //
  309. // These are just completed with success
  310. //
  311. case IRP_MN_QUERY_REMOVE_DEVICE:
  312. GCK_DBG_TRACE_PRINT(("IRP_MN_QUERY_REMOVE_DEVICE\n"));
  313. NtStatus = STATUS_SUCCESS;
  314. break;
  315. case IRP_MN_CANCEL_REMOVE_DEVICE:
  316. GCK_DBG_TRACE_PRINT(("IRP_MN_CANCEL_REMOVE_DEVICE\n"));
  317. NtStatus = STATUS_SUCCESS;
  318. break;
  319. case IRP_MN_QUERY_STOP_DEVICE:
  320. GCK_DBG_TRACE_PRINT(("IRP_MN_QUERY_STOP_DEVICE\n"));
  321. NtStatus = STATUS_SUCCESS;
  322. break;
  323. case IRP_MN_CANCEL_STOP_DEVICE:
  324. GCK_DBG_TRACE_PRINT(("IRP_MN_CANCEL_STOP_DEVICE\n"));
  325. NtStatus = STATUS_SUCCESS;
  326. break;
  327. //
  328. // These are just completed with their default status.
  329. //
  330. case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
  331. GCK_DBG_TRACE_PRINT(("IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n"));
  332. break;
  333. case IRP_MN_READ_CONFIG:
  334. GCK_DBG_TRACE_PRINT(("IRP_MN_READ_CONFIG\n"));
  335. break;
  336. case IRP_MN_WRITE_CONFIG:
  337. GCK_DBG_TRACE_PRINT(("IRP_MN_WRITE_CONFIG\n"));
  338. break;
  339. case IRP_MN_EJECT:
  340. GCK_DBG_TRACE_PRINT(("IRP_MN_EJECT\n"));
  341. break;
  342. case IRP_MN_SET_LOCK:
  343. GCK_DBG_TRACE_PRINT(("IRP_MN_SET_LOCK\n"));
  344. break;
  345. case IRP_MN_QUERY_INTERFACE:
  346. GCK_DBG_TRACE_PRINT(("IRP_MN_QUERY_INTERFACE\n"));
  347. break;
  348. default:
  349. GCK_DBG_TRACE_PRINT(("Unknown IRP_MJ_PNP minor function = 0x%x\n", pIrpStack->MinorFunction));
  350. }
  351. //
  352. // We are a PDO, there is no-one beneath us, we cannot send IRP's down.
  353. // So we complete with the status set in the above switch/case,
  354. // if not change there, the default is to preserve the status as
  355. // NtStatus = pIrp->IoStatus.Status is done prior to entering the
  356. // switch/case
  357. //
  358. pIrp->IoStatus.Status = NtStatus;
  359. IoCompleteRequest (pIrp, IO_NO_INCREMENT);
  360. GCK_DecRemoveLock(&pPdoExt->RemoveLock);
  361. GCK_DBG_EXIT_PRINT(("Exiting GCK_SWVB_PnP with Status, 0x%0.8x\n", NtStatus));
  362. return NtStatus;
  363. }
  364. /***********************************************************************************
  365. **
  366. ** NTSTATUS GCK_SWVB_Power(IN PDEVICE_OBJECT pDeviceObject, IN OUT PIRP pIrp)
  367. **
  368. ** @func Handles Power IRPs for Virtual Devices. We only have virtual
  369. ** devices so we support any power IRP. Just succeed, sure we handle
  370. ** that power level. In the future, we may wish to keep track of what
  371. ** state we are in, so we can wake the system, etc.
  372. **
  373. ** @rdesc STATUS_SUCCESS
  374. **
  375. *************************************************************************************/
  376. NTSTATUS GCK_SWVB_Power
  377. (
  378. IN PDEVICE_OBJECT pDeviceObject, // @parm Device Object IRP is sent to
  379. IN OUT PIRP pIrp // @parm IRP to process
  380. )
  381. {
  382. NTSTATUS NtStatus = STATUS_UNSUCCESSFUL;
  383. PIO_STACK_LOCATION pIrpStack;
  384. PSWVB_PDO_EXT pPdoExt = (PSWVB_PDO_EXT)pDeviceObject->DeviceExtension;
  385. ASSERT( GCK_DO_TYPE_SWVB == pPdoExt->ulGckDevObjType);
  386. GCK_DBG_ENTRY_PRINT(("Entering GCK_SWVB_Power\n"));
  387. pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  388. GCK_IncRemoveLock(&pPdoExt->RemoveLock);
  389. switch (pIrpStack->MinorFunction){
  390. case IRP_MN_SET_POWER:
  391. switch (pIrpStack->Parameters.Power.Type) {
  392. case SystemPowerState:
  393. NtStatus = STATUS_SUCCESS;
  394. break;
  395. case DevicePowerState:
  396. NtStatus = STATUS_SUCCESS;
  397. break;
  398. default:
  399. NtStatus = pIrp->IoStatus.Status;
  400. }
  401. break;
  402. case IRP_MN_WAIT_WAKE:
  403. //We just return STATUS_NOT_SUPPORTED as we do not support
  404. //waking the system.
  405. NtStatus = STATUS_NOT_SUPPORTED;
  406. break;
  407. case IRP_MN_POWER_SEQUENCE:
  408. ASSERT(FALSE); //Shouldn't happen
  409. NtStatus = pIrp->IoStatus.Status;
  410. break;
  411. case IRP_MN_QUERY_POWER:
  412. NtStatus = STATUS_SUCCESS;
  413. break;
  414. default:
  415. NtStatus = pIrp->IoStatus.Status;
  416. break;
  417. }
  418. //we are done so signal that we are ready for next one
  419. PoStartNextPowerIrp(pIrp);
  420. ASSERT(NtStatus != STATUS_UNSUCCESSFUL);
  421. pIrp->IoStatus.Status = NtStatus;
  422. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  423. GCK_DecRemoveLock(&pPdoExt->RemoveLock);
  424. GCK_DBG_EXIT_PRINT(("Exiting GCK_Power with Status, 0x%0.8x\n", NtStatus));
  425. return NtStatus;
  426. }