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.

682 lines
22 KiB

  1. /*++
  2. Copyright (c) 1997-2000 Microsoft Corporation
  3. Module Name:
  4. io.c
  5. Abstract:
  6. This module handles device ioctl's and read/write to the sdbus driver.
  7. Authors:
  8. Neil Sandlin (neilsa) 1-Jan-2002
  9. Environment:
  10. Kernel mode
  11. Revision History :
  12. --*/
  13. #include "pch.h"
  14. NTSTATUS
  15. SdbusPdoSubmitRequest(
  16. IN PFDO_EXTENSION fdoExtension,
  17. IN PPDO_EXTENSION pdoExtension,
  18. IN PSDBUS_REQUEST_PACKET SdRp,
  19. PSDBUS_WORKPACKET_COMPLETION_ROUTINE CompletionRoutine,
  20. IN PIRP Irp
  21. );
  22. VOID
  23. SdbusPdoInternalIoctlCompletion (
  24. IN PSD_WORK_PACKET WorkPacket,
  25. IN NTSTATUS status
  26. );
  27. VOID
  28. SdbusPdoIoctlCompletion (
  29. IN PSD_WORK_PACKET WorkPacket,
  30. IN NTSTATUS status
  31. );
  32. NTSTATUS
  33. SdbusFdoDeviceControl(
  34. IN PDEVICE_OBJECT Fdo,
  35. IN PIRP Irp
  36. )
  37. /*++
  38. Routine Description:
  39. IOCTL device routine
  40. Arguments:
  41. DeviceObject - Pointer to the device object.
  42. Irp - Pointer to the IRP
  43. Return Value:
  44. Status
  45. --*/
  46. {
  47. Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
  48. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  49. return STATUS_INVALID_DEVICE_REQUEST;
  50. }
  51. NTSTATUS
  52. SdbusPdoInternalDeviceControl(
  53. IN PDEVICE_OBJECT Pdo,
  54. IN PIRP Irp
  55. )
  56. /*++
  57. Routine Description:
  58. IOCTL device routine
  59. Arguments:
  60. DeviceObject - Pointer to the device object.
  61. Irp - Pointer to the IRP
  62. Return Value:
  63. Status
  64. --*/
  65. {
  66. PPDO_EXTENSION pdoExtension = Pdo->DeviceExtension;
  67. PFDO_EXTENSION fdoExtension = pdoExtension->FdoExtension;
  68. PDEVICE_OBJECT fdo = fdoExtension->DeviceObject;
  69. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
  70. NTSTATUS status = STATUS_SUCCESS;
  71. DebugPrint((SDBUS_DEBUG_IOCTL, "pdo %.08x irp %.08x code %08x DISPATCH\n", Pdo, Irp,
  72. irpSp->Parameters.DeviceIoControl.IoControlCode));
  73. switch (irpSp->Parameters.DeviceIoControl.IoControlCode) {
  74. case IOCTL_SD_SUBMIT_REQUEST: {
  75. PSDBUS_REQUEST_PACKET SdRp = Irp->AssociatedIrp.SystemBuffer;
  76. if (irpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(SDBUS_REQUEST_PACKET)) {
  77. status = STATUS_INVALID_PARAMETER;
  78. break;
  79. }
  80. //
  81. // Build and queue a work packet to handle this request
  82. //
  83. status = SdbusPdoSubmitRequest(fdoExtension,
  84. pdoExtension,
  85. SdRp,
  86. SdbusPdoInternalIoctlCompletion,
  87. Irp);
  88. break;
  89. }
  90. default:
  91. status = STATUS_INVALID_DEVICE_REQUEST;
  92. DebugPrint((SDBUS_DEBUG_IOCTL, "pdo %.08x irp %.08x complete %08x\n", Pdo, Irp, status));
  93. break;
  94. }
  95. if (status != STATUS_PENDING) {
  96. Irp->IoStatus.Status = status;
  97. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  98. }
  99. DebugPrint((SDBUS_DEBUG_IOCTL, "pdo %.08x ioctl exits %08x\n", Pdo, status));
  100. return status;
  101. }
  102. VOID
  103. SdbusPdoInternalIoctlCompletion (
  104. IN PSD_WORK_PACKET WorkPacket,
  105. IN NTSTATUS status
  106. )
  107. {
  108. PIRP irp = WorkPacket->CompletionContext;
  109. DebugPrint((SDBUS_DEBUG_IOCTL, "pdo %08x irp %08x ioctl complete %08x\n",
  110. WorkPacket->PdoExtension->DeviceObject, irp, status));
  111. if (NT_SUCCESS(status)) {
  112. irp->IoStatus.Information = WorkPacket->Information;
  113. }
  114. irp->IoStatus.Status = status;
  115. IoCompleteRequest(irp, IO_NO_INCREMENT);
  116. ExFreePool(WorkPacket);
  117. }
  118. NTSTATUS
  119. SdbusPdoSubmitRequest(
  120. IN PFDO_EXTENSION fdoExtension,
  121. IN PPDO_EXTENSION pdoExtension,
  122. IN PSDBUS_REQUEST_PACKET SdRp,
  123. PSDBUS_WORKPACKET_COMPLETION_ROUTINE CompletionRoutine,
  124. IN PIRP Irp
  125. )
  126. {
  127. NTSTATUS status;
  128. PSD_WORK_PACKET workPacket;
  129. switch(SdRp->Function) {
  130. case SDRP_READ_BLOCK:
  131. status = SdbusBuildWorkPacket(fdoExtension,
  132. SDWP_READBLOCK,
  133. CompletionRoutine,
  134. Irp,
  135. &workPacket);
  136. if (!NT_SUCCESS(status)) {
  137. break;
  138. }
  139. workPacket->PdoExtension = pdoExtension;
  140. workPacket->Parameters.ReadBlock.ByteOffset = SdRp->Parameters.ReadBlock.ByteOffset;
  141. workPacket->Parameters.ReadBlock.Buffer = SdRp->Parameters.ReadBlock.Buffer;
  142. workPacket->Parameters.ReadBlock.Length = SdRp->Parameters.ReadBlock.Length;
  143. SdbusQueueWorkPacket(fdoExtension, workPacket, WP_TYPE_IO);
  144. status = STATUS_PENDING;
  145. break;
  146. case SDRP_WRITE_BLOCK:
  147. if ((*(fdoExtension->FunctionBlock->IsWriteProtected))(fdoExtension)) {
  148. status = STATUS_MEDIA_WRITE_PROTECTED;
  149. break;
  150. }
  151. status = SdbusBuildWorkPacket(fdoExtension,
  152. SDWP_WRITEBLOCK,
  153. CompletionRoutine,
  154. Irp,
  155. &workPacket);
  156. if (!NT_SUCCESS(status)) {
  157. break;
  158. }
  159. workPacket->PdoExtension = pdoExtension;
  160. workPacket->Parameters.WriteBlock.ByteOffset = SdRp->Parameters.WriteBlock.ByteOffset;
  161. workPacket->Parameters.WriteBlock.Buffer = SdRp->Parameters.WriteBlock.Buffer;
  162. workPacket->Parameters.WriteBlock.Length = SdRp->Parameters.WriteBlock.Length;
  163. IoMarkIrpPending(Irp);
  164. SdbusQueueWorkPacket(fdoExtension, workPacket, WP_TYPE_IO);
  165. status = STATUS_PENDING;
  166. break;
  167. case SDRP_READ_IO:
  168. status = SdbusBuildWorkPacket(fdoExtension,
  169. SDWP_READIO,
  170. CompletionRoutine,
  171. Irp,
  172. &workPacket);
  173. if (!NT_SUCCESS(status)) {
  174. break;
  175. }
  176. workPacket->PdoExtension = pdoExtension;
  177. workPacket->Parameters.ReadIo.Offset = SdRp->Parameters.ReadIo.Offset;
  178. workPacket->Parameters.ReadIo.Buffer = SdRp->Parameters.ReadIo.Buffer;
  179. workPacket->Parameters.ReadIo.Length = 1;
  180. IoMarkIrpPending(Irp);
  181. SdbusQueueWorkPacket(fdoExtension, workPacket, WP_TYPE_IO);
  182. status = STATUS_PENDING;
  183. break;
  184. case SDRP_READ_IO_EXTENDED:
  185. status = SdbusBuildWorkPacket(fdoExtension,
  186. SDWP_READIO_EXTENDED,
  187. CompletionRoutine,
  188. Irp,
  189. &workPacket);
  190. if (!NT_SUCCESS(status)) {
  191. break;
  192. }
  193. workPacket->PdoExtension = pdoExtension;
  194. workPacket->Parameters.ReadIo.Offset = SdRp->Parameters.ReadIoExtended.Offset;
  195. workPacket->Parameters.ReadIo.Buffer = SdRp->Parameters.ReadIoExtended.Buffer;
  196. workPacket->Parameters.ReadIo.Length = SdRp->Parameters.ReadIoExtended.Length;
  197. IoMarkIrpPending(Irp);
  198. SdbusQueueWorkPacket(fdoExtension, workPacket, WP_TYPE_IO);
  199. status = STATUS_PENDING;
  200. break;
  201. case SDRP_WRITE_IO:
  202. status = SdbusBuildWorkPacket(fdoExtension,
  203. SDWP_WRITEIO,
  204. CompletionRoutine,
  205. Irp,
  206. &workPacket);
  207. if (!NT_SUCCESS(status)) {
  208. break;
  209. }
  210. workPacket->PdoExtension = pdoExtension;
  211. workPacket->Parameters.WriteIo.Offset = SdRp->Parameters.WriteIo.Offset;
  212. workPacket->Parameters.WriteIo.Data = SdRp->Parameters.WriteIo.Data;
  213. workPacket->Parameters.WriteIo.Length = 1;
  214. IoMarkIrpPending(Irp);
  215. SdbusQueueWorkPacket(fdoExtension, workPacket, WP_TYPE_IO);
  216. status = STATUS_PENDING;
  217. break;
  218. case SDRP_WRITE_IO_EXTENDED:
  219. status = SdbusBuildWorkPacket(fdoExtension,
  220. SDWP_WRITEIO_EXTENDED,
  221. CompletionRoutine,
  222. Irp,
  223. &workPacket);
  224. if (!NT_SUCCESS(status)) {
  225. break;
  226. }
  227. workPacket->PdoExtension = pdoExtension;
  228. workPacket->Parameters.WriteIo.Offset = SdRp->Parameters.WriteIoExtended.Offset;
  229. workPacket->Parameters.WriteIo.Buffer = SdRp->Parameters.WriteIoExtended.Buffer;
  230. workPacket->Parameters.WriteIo.Length = SdRp->Parameters.WriteIoExtended.Length;
  231. IoMarkIrpPending(Irp);
  232. SdbusQueueWorkPacket(fdoExtension, workPacket, WP_TYPE_IO);
  233. status = STATUS_PENDING;
  234. break;
  235. case SDRP_ACKNOWLEDGE_INTERRUPT:
  236. ASSERT((pdoExtension->Flags & SDBUS_PDO_CALLBACK_IN_SERVICE) != 0);
  237. pdoExtension->Flags &= ~SDBUS_PDO_CALLBACK_IN_SERVICE;
  238. (*(fdoExtension->FunctionBlock->AcknowledgeEvent))(fdoExtension, SDBUS_EVENT_CARD_INTERRUPT);
  239. status = STATUS_SUCCESS;
  240. break;
  241. default:
  242. status = STATUS_INVALID_PARAMETER;
  243. }
  244. return status;
  245. }
  246. NTSTATUS
  247. SdbusPdoDeviceControl(
  248. IN PDEVICE_OBJECT Pdo,
  249. IN PIRP Irp
  250. )
  251. /*++
  252. Routine Description:
  253. IOCTL device routine
  254. Arguments:
  255. DeviceObject - Pointer to the device object.
  256. Irp - Pointer to the IRP
  257. Return Value:
  258. Status
  259. --*/
  260. {
  261. PPDO_EXTENSION pdoExtension = Pdo->DeviceExtension;
  262. PFDO_EXTENSION fdoExtension = pdoExtension->FdoExtension;
  263. PDEVICE_OBJECT fdo = fdoExtension->DeviceObject;
  264. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
  265. NTSTATUS status = STATUS_SUCCESS;
  266. PSD_WORK_PACKET workPacket;
  267. DebugPrint((SDBUS_DEBUG_IOCTL, "pdo %.08x irp %.08x code %08x DISPATCH\n", Pdo, Irp,
  268. irpSp->Parameters.DeviceIoControl.IoControlCode));
  269. switch (irpSp->Parameters.DeviceIoControl.IoControlCode) {
  270. case IOCTL_SD_INTERFACE_OPEN: {
  271. PSDBUS_INTERFACE_DATA interfaceData = Irp->AssociatedIrp.SystemBuffer;
  272. if (irpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(SDBUS_INTERFACE_DATA)) {
  273. status = STATUS_INVALID_PARAMETER;
  274. break;
  275. }
  276. if (interfaceData->DeviceGeneratesInterrupts) {
  277. pdoExtension->Flags |= SDBUS_PDO_GENERATES_IRQ;
  278. //
  279. // ISSUE: this is not multifunction-aware
  280. //
  281. if (interfaceData->CallbackAtDpcLevel) {
  282. //
  283. // reflect ISR at dispatch level
  284. //
  285. pdoExtension->Flags |= SDBUS_PDO_DPC_CALLBACK;
  286. } else {
  287. //
  288. // reflect ISR at passive level
  289. //
  290. KeInitializeEvent(&fdoExtension->CardInterruptEvent, SynchronizationEvent, FALSE);
  291. KeInitializeEvent(&fdoExtension->WorkItemExitEvent, SynchronizationEvent, FALSE);
  292. fdoExtension->Flags |= SDBUS_FDO_WORK_ITEM_ACTIVE;
  293. IoQueueWorkItem(fdoExtension->IoWorkItem,
  294. SdbusEventWorkItemProc,
  295. DelayedWorkQueue,
  296. NULL);
  297. }
  298. (*(fdoExtension->FunctionBlock->EnableEvent))(fdoExtension, SDBUS_EVENT_CARD_INTERRUPT);
  299. }
  300. // TO IMPLEMENT: can I validate this address at all?
  301. pdoExtension->CallbackRoutine = interfaceData->CallbackRoutine;
  302. pdoExtension->CallbackRoutineContext = interfaceData->CallbackRoutineContext;
  303. status = STATUS_SUCCESS;
  304. break;
  305. }
  306. case IOCTL_SD_INTERFACE_CLOSE:
  307. //
  308. // ISSUE: this is not multifunction-aware
  309. //
  310. if (fdoExtension->Flags & SDBUS_FDO_WORK_ITEM_ACTIVE) {
  311. fdoExtension->Flags &= ~SDBUS_FDO_WORK_ITEM_ACTIVE;
  312. KeSetEvent(&fdoExtension->WorkItemExitEvent, 0, FALSE);
  313. }
  314. status = STATUS_SUCCESS;
  315. break;
  316. case IOCTL_SD_GET_DEVICE_PARMS: {
  317. PSDBUS_DEVICE_PARAMETERS deviceParameters = Irp->AssociatedIrp.SystemBuffer;
  318. ULONG deviceSize;
  319. ULONGLONG capacity, blockNr, mult, block_len;
  320. PSD_CSD sdCsd;
  321. DebugPrint((SDBUS_DEBUG_IOCTL, "IOCTL_SD_GET_DEVICE_PARMS\n"));
  322. if (irpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(SDBUS_DEVICE_PARAMETERS)) {
  323. status = STATUS_INVALID_PARAMETER;
  324. break;
  325. }
  326. //ISSUE: NEED TO IMPLEMENT: synchronization
  327. sdCsd = &fdoExtension->CardData->SdCsd;
  328. deviceSize = sdCsd->b.DeviceSizeHigh << 2 | sdCsd->c.DeviceSizeLow;
  329. mult = (1 << (sdCsd->c.DeviceSizeMultiplier+2));
  330. blockNr = (deviceSize+1) * mult;
  331. block_len = (1 << sdCsd->b.MaxReadDataBlockLength);
  332. capacity = blockNr * block_len;
  333. deviceParameters->Capacity = capacity;
  334. deviceParameters->WriteProtected = (*(fdoExtension->FunctionBlock->IsWriteProtected))(fdoExtension);
  335. Irp->IoStatus.Information = sizeof(SDBUS_DEVICE_PARAMETERS);
  336. DebugPrint((SDBUS_DEBUG_IOCTL, "pdo %.08x irp %.08x complete %08x\n", Pdo, Irp, status));
  337. break;
  338. }
  339. #if 0
  340. case IOCTL_SD_READ_BLOCK: {
  341. PSDBUS_READ_PARAMETERS readParameters = Irp->AssociatedIrp.SystemBuffer;
  342. DebugPrint((SDBUS_DEBUG_IOCTL, "IOCTL_SD_READ_BLOCK - off %08x len %08x\n",
  343. (ULONG)readParameters->ByteOffset, readParameters->Length));
  344. if ((irpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(SDBUS_READ_PARAMETERS)) ||
  345. (irpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG_PTR))) {
  346. status = STATUS_INVALID_PARAMETER;
  347. break;
  348. }
  349. status = SdbusBuildWorkPacket(fdoExtension,
  350. SDWP_READBLOCK,
  351. SdbusPdoIoctlCompletion,
  352. Irp,
  353. &workPacket);
  354. if (!NT_SUCCESS(status)) {
  355. break;
  356. }
  357. workPacket->PdoExtension = pdoExtension;
  358. workPacket->Parameters.ReadBlock.ByteOffset = readParameters->ByteOffset;
  359. workPacket->Parameters.ReadBlock.Buffer = readParameters->Buffer;
  360. workPacket->Parameters.ReadBlock.Length = readParameters->Length;
  361. IoMarkIrpPending(Irp);
  362. Irp = NULL;
  363. SdbusQueueWorkPacket(fdoExtension, workPacket, WP_TYPE_IO);
  364. status = STATUS_PENDING;
  365. break;
  366. }
  367. case IOCTL_SD_WRITE_BLOCK: {
  368. PSDBUS_WRITE_PARAMETERS writeParameters = Irp->AssociatedIrp.SystemBuffer;
  369. DebugPrint((SDBUS_DEBUG_IOCTL, "IOCTL_SD_WRITE_BLOCK - off %08x len %08x\n",
  370. (ULONG)writeParameters->ByteOffset, writeParameters->Length));
  371. if ((irpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(SDBUS_WRITE_PARAMETERS)) ||
  372. (irpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG_PTR))) {
  373. status = STATUS_INVALID_PARAMETER;
  374. break;
  375. }
  376. if ((*(fdoExtension->FunctionBlock->IsWriteProtected))(fdoExtension)) {
  377. status = STATUS_MEDIA_WRITE_PROTECTED;
  378. break;
  379. }
  380. status = SdbusBuildWorkPacket(fdoExtension,
  381. SDWP_WRITEBLOCK,
  382. SdbusPdoIoctlCompletion,
  383. Irp,
  384. &workPacket);
  385. if (!NT_SUCCESS(status)) {
  386. break;
  387. }
  388. workPacket->PdoExtension = pdoExtension;
  389. workPacket->Parameters.WriteBlock.ByteOffset = writeParameters->ByteOffset;
  390. workPacket->Parameters.WriteBlock.Buffer = writeParameters->Buffer;
  391. workPacket->Parameters.WriteBlock.Length = writeParameters->Length;
  392. IoMarkIrpPending(Irp);
  393. Irp = NULL;
  394. SdbusQueueWorkPacket(fdoExtension, workPacket, WP_TYPE_IO);
  395. status = STATUS_PENDING;
  396. break;
  397. }
  398. case IOCTL_SD_IO_READ: {
  399. PSDBUS_IO_READ_PARAMETERS readParameters = Irp->AssociatedIrp.SystemBuffer;
  400. WORKPROC_FUNCTION workProcFunction;
  401. if ((irpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(SDBUS_IO_READ_PARAMETERS)) ||
  402. (irpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG_PTR))) {
  403. status = STATUS_INVALID_PARAMETER;
  404. break;
  405. }
  406. if (readParameters->CmdType == 52) {
  407. workProcFunction = SDWP_READIO;
  408. } else if (readParameters->CmdType == 53) {
  409. workProcFunction = SDWP_READIO_EXTENDED;
  410. } else {
  411. status = STATUS_INVALID_PARAMETER;
  412. break;
  413. }
  414. status = SdbusBuildWorkPacket(fdoExtension,
  415. workProcFunction,
  416. SdbusPdoIoctlCompletion,
  417. Irp,
  418. &workPacket);
  419. if (!NT_SUCCESS(status)) {
  420. break;
  421. }
  422. workPacket->PdoExtension = pdoExtension;
  423. workPacket->Parameters.ReadIo.Offset = readParameters->Offset;
  424. workPacket->Parameters.ReadIo.Buffer = readParameters->Buffer;
  425. workPacket->Parameters.ReadIo.Length = readParameters->Length;
  426. IoMarkIrpPending(Irp);
  427. Irp = NULL;
  428. SdbusQueueWorkPacket(fdoExtension, workPacket, WP_TYPE_IO);
  429. status = STATUS_PENDING;
  430. break;
  431. }
  432. case IOCTL_SD_IO_WRITE: {
  433. PSDBUS_IO_WRITE_PARAMETERS writeParameters = Irp->AssociatedIrp.SystemBuffer;
  434. WORKPROC_FUNCTION workProcFunction;
  435. if ((irpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(SDBUS_IO_WRITE_PARAMETERS)) ||
  436. (irpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG_PTR))) {
  437. status = STATUS_INVALID_PARAMETER;
  438. break;
  439. }
  440. if (writeParameters->CmdType == 52) {
  441. workProcFunction = SDWP_WRITEIO;
  442. } else if (writeParameters->CmdType == 53) {
  443. workProcFunction = SDWP_WRITEIO_EXTENDED;
  444. } else {
  445. status = STATUS_INVALID_PARAMETER;
  446. break;
  447. }
  448. status = SdbusBuildWorkPacket(fdoExtension,
  449. workProcFunction,
  450. SdbusPdoIoctlCompletion,
  451. Irp,
  452. &workPacket);
  453. if (!NT_SUCCESS(status)) {
  454. break;
  455. }
  456. workPacket->PdoExtension = pdoExtension;
  457. workPacket->Parameters.WriteIo.Offset = writeParameters->Offset;
  458. workPacket->Parameters.WriteIo.Buffer = writeParameters->Buffer;
  459. workPacket->Parameters.WriteIo.Length = writeParameters->Length;
  460. IoMarkIrpPending(Irp);
  461. Irp = NULL;
  462. SdbusQueueWorkPacket(fdoExtension, workPacket, WP_TYPE_IO);
  463. status = STATUS_PENDING;
  464. break;
  465. }
  466. #endif
  467. case IOCTL_SD_ACKNOWLEDGE_CARD_IRQ:
  468. ASSERT((pdoExtension->Flags & SDBUS_PDO_CALLBACK_IN_SERVICE) != 0);
  469. pdoExtension->Flags &= ~SDBUS_PDO_CALLBACK_IN_SERVICE;
  470. (*(fdoExtension->FunctionBlock->AcknowledgeEvent))(fdoExtension, SDBUS_EVENT_CARD_INTERRUPT);
  471. status = STATUS_SUCCESS;
  472. break;
  473. default:
  474. status = STATUS_INVALID_DEVICE_REQUEST;
  475. DebugPrint((SDBUS_DEBUG_IOCTL, "pdo %.08x irp %.08x complete %08x\n", Pdo, Irp, status));
  476. break;
  477. }
  478. if (status != STATUS_PENDING) {
  479. Irp->IoStatus.Status = status;
  480. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  481. }
  482. DebugPrint((SDBUS_DEBUG_IOCTL, "pdo %.08x ioctl exits %08x\n", Pdo, status));
  483. return status;
  484. }
  485. VOID
  486. SdbusPdoIoctlCompletion (
  487. IN PSD_WORK_PACKET WorkPacket,
  488. IN NTSTATUS status
  489. )
  490. {
  491. PIRP irp = WorkPacket->CompletionContext;
  492. DebugPrint((SDBUS_DEBUG_IOCTL, "pdo %08x irp %08x ioctl complete %08x\n",
  493. WorkPacket->PdoExtension->DeviceObject, irp, status));
  494. if (NT_SUCCESS(status)) {
  495. PULONG_PTR outputBuffer = (PULONG_PTR)irp->AssociatedIrp.SystemBuffer;
  496. // ISSUE make this so the individual worker routine can decide how big the return buffer is
  497. *outputBuffer = WorkPacket->Information;
  498. irp->IoStatus.Information = sizeof(ULONG_PTR);
  499. }
  500. irp->IoStatus.Status = status;
  501. IoCompleteRequest(irp, IO_NO_INCREMENT);
  502. ExFreePool(WorkPacket);
  503. }