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.

379 lines
13 KiB

  1. /*++
  2. Copyright (c) 1991-1998 Microsoft Corporation
  3. Module Name:
  4. ioctl.c
  5. Abstract:
  6. Author:
  7. Neil Sandlin (neilsa) 26-Apr-99
  8. Environment:
  9. Kernel mode only.
  10. --*/
  11. #include "pch.h"
  12. #ifdef ALLOC_PRAGMA
  13. #pragma alloc_text(PAGE,MemCardDeviceControl)
  14. #endif
  15. NTSTATUS
  16. MemCardDeviceControl(
  17. IN PDEVICE_OBJECT DeviceObject,
  18. IN PIRP Irp
  19. )
  20. /*++
  21. Routine Description:
  22. This routine is called by the I/O system to perform a device I/O
  23. control function.
  24. Arguments:
  25. DeviceObject - a pointer to the object that represents the device
  26. that I/O is to be done on.
  27. Irp - a pointer to the I/O Request Packet for this request.
  28. Return Value:
  29. STATUS_SUCCESS or STATUS_PENDING if recognized I/O control code,
  30. STATUS_INVALID_DEVICE_REQUEST otherwise.
  31. --*/
  32. {
  33. PIO_STACK_LOCATION irpSp;
  34. PMEMCARD_EXTENSION memcardExtension;
  35. PDISK_GEOMETRY outputBuffer;
  36. NTSTATUS status;
  37. ULONG outputBufferLength;
  38. UCHAR i;
  39. ULONG formatExParametersSize;
  40. PFORMAT_EX_PARAMETERS formatExParameters;
  41. MemCardDump( MEMCARDIOCTL, ("MemCard: IOCTL entered\n") );
  42. memcardExtension = DeviceObject->DeviceExtension;
  43. irpSp = IoGetCurrentIrpStackLocation( Irp );
  44. //
  45. // If the device has been removed we will just fail this request outright.
  46. //
  47. if ( memcardExtension->IsRemoved ) {
  48. Irp->IoStatus.Information = 0;
  49. Irp->IoStatus.Status = STATUS_DELETE_PENDING;
  50. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  51. return STATUS_DELETE_PENDING;
  52. }
  53. //
  54. // If the device hasn't been started we will let the IOCTL through. This
  55. // is another hack for ACPI.
  56. //
  57. if (!memcardExtension->IsStarted) {
  58. IoSkipCurrentIrpStackLocation( Irp );
  59. return IoCallDriver( memcardExtension->TargetObject, Irp );
  60. }
  61. switch( irpSp->Parameters.DeviceIoControl.IoControlCode ) {
  62. case IOCTL_MOUNTDEV_QUERY_DEVICE_NAME: {
  63. PMOUNTDEV_NAME mountName;
  64. MemCardDump( MEMCARDIOCTL, ("MemCard: DO %.8x Irp %.8x IOCTL_MOUNTDEV_QUERY_DEVICE_NAME\n",
  65. DeviceObject, Irp));
  66. ASSERT(memcardExtension->DeviceName.Buffer);
  67. if ( irpSp->Parameters.DeviceIoControl.OutputBufferLength <
  68. sizeof(MOUNTDEV_NAME) ) {
  69. status = STATUS_INVALID_PARAMETER;
  70. break;
  71. }
  72. mountName = Irp->AssociatedIrp.SystemBuffer;
  73. mountName->NameLength = memcardExtension->DeviceName.Length;
  74. if ( irpSp->Parameters.DeviceIoControl.OutputBufferLength <
  75. sizeof(USHORT) + mountName->NameLength) {
  76. status = STATUS_BUFFER_OVERFLOW;
  77. Irp->IoStatus.Information = sizeof(MOUNTDEV_NAME);
  78. break;
  79. }
  80. RtlCopyMemory( mountName->Name, memcardExtension->DeviceName.Buffer,
  81. mountName->NameLength);
  82. status = STATUS_SUCCESS;
  83. Irp->IoStatus.Information = sizeof(USHORT) + mountName->NameLength;
  84. break;
  85. }
  86. case IOCTL_MOUNTDEV_QUERY_UNIQUE_ID: {
  87. PMOUNTDEV_UNIQUE_ID uniqueId;
  88. MemCardDump( MEMCARDIOCTL, ("MemCard: DO %.8x Irp %.8x IOCTL_MOUNTDEV_QUERY_UNIQUE_ID\n",
  89. DeviceObject, Irp));
  90. if ( !memcardExtension->InterfaceString.Buffer ||
  91. irpSp->Parameters.DeviceIoControl.OutputBufferLength <
  92. sizeof(MOUNTDEV_UNIQUE_ID)) {
  93. status = STATUS_INVALID_PARAMETER;
  94. break;
  95. }
  96. uniqueId = Irp->AssociatedIrp.SystemBuffer;
  97. uniqueId->UniqueIdLength =
  98. memcardExtension->InterfaceString.Length;
  99. if (irpSp->Parameters.DeviceIoControl.OutputBufferLength <
  100. sizeof(USHORT) + uniqueId->UniqueIdLength) {
  101. status = STATUS_BUFFER_OVERFLOW;
  102. Irp->IoStatus.Information = sizeof(MOUNTDEV_UNIQUE_ID);
  103. break;
  104. }
  105. RtlCopyMemory( uniqueId->UniqueId,
  106. memcardExtension->InterfaceString.Buffer,
  107. uniqueId->UniqueIdLength );
  108. status = STATUS_SUCCESS;
  109. Irp->IoStatus.Information = sizeof(USHORT) +
  110. uniqueId->UniqueIdLength;
  111. break;
  112. }
  113. case IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME: {
  114. MemCardDump(MEMCARDIOCTL,("MemCard: DO %.8x Irp %.8x IOCTL_MOUNTDEV_QUERY_SUGGESTED_LINK_NAME\n",
  115. DeviceObject, Irp));
  116. status = STATUS_INVALID_DEVICE_REQUEST;
  117. break;
  118. }
  119. case IOCTL_DISK_GET_MEDIA_TYPES: {
  120. ULONG ByteCapacity;
  121. MemCardDump(MEMCARDIOCTL,("MemCard: DO %.8x Irp %.8x IOCTL_DISK_GET_MEDIA_TYPES\n",
  122. DeviceObject, Irp));
  123. outputBufferLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
  124. outputBuffer = (PDISK_GEOMETRY) Irp->AssociatedIrp.SystemBuffer;
  125. //
  126. // Make sure that the input buffer has enough room to return
  127. // at least one descriptions of a supported media type.
  128. //
  129. if (outputBufferLength < (sizeof(DISK_GEOMETRY))) {
  130. status = STATUS_BUFFER_TOO_SMALL;
  131. break;
  132. }
  133. //
  134. // Assume success, although we might modify it to a buffer
  135. // overflow warning below (if the buffer isn't big enough
  136. // to hold ALL of the media descriptions).
  137. //
  138. status = STATUS_SUCCESS;
  139. i = 0;
  140. Irp->IoStatus.Information = 0;
  141. //
  142. // Fill in capacities from 512K to 8M
  143. //
  144. for (ByteCapacity = 0x80000; ByteCapacity <= 0x800000; ByteCapacity*=2) {
  145. if (outputBufferLength < (sizeof(DISK_GEOMETRY) + Irp->IoStatus.Information)) {
  146. status = STATUS_BUFFER_OVERFLOW;
  147. break;
  148. }
  149. outputBuffer->MediaType = FixedMedia;
  150. outputBuffer->Cylinders.LowPart = ByteCapacity / (8 * 2 * 512);
  151. outputBuffer->Cylinders.HighPart = 0;
  152. outputBuffer->TracksPerCylinder = 2;
  153. outputBuffer->SectorsPerTrack = 8;
  154. outputBuffer->BytesPerSector = 512;
  155. MemCardDump( MEMCARDIOCTL, ("MemCard: Cyls=%x\n", outputBuffer->Cylinders.LowPart));
  156. outputBuffer++;
  157. Irp->IoStatus.Information += sizeof( DISK_GEOMETRY );
  158. }
  159. break;
  160. }
  161. case IOCTL_DISK_CHECK_VERIFY:
  162. MemCardDump( MEMCARDIOCTL, ("MemCard: DO %.8x Irp %.8x IOCTL_DISK_CHECK_VERIFY\n",
  163. DeviceObject, Irp));
  164. status = STATUS_SUCCESS;
  165. break;
  166. case IOCTL_DISK_GET_DRIVE_GEOMETRY: {
  167. PDISK_GEOMETRY outputBuffer = (PDISK_GEOMETRY) Irp->AssociatedIrp.SystemBuffer;
  168. MemCardDump( MEMCARDIOCTL, ("MemCard: DO %.8x Irp %.8x IOCTL_DISK_GET_DRIVE_GEOMETRY\n",
  169. DeviceObject, Irp));
  170. if ( irpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( DISK_GEOMETRY ) ) {
  171. status = STATUS_INVALID_PARAMETER;
  172. break;
  173. }
  174. status = STATUS_SUCCESS;
  175. if (!memcardExtension->ByteCapacity) {
  176. //
  177. // Just zero out everything. The
  178. // caller shouldn't look at it.
  179. //
  180. outputBuffer->MediaType = Unknown;
  181. outputBuffer->Cylinders.LowPart = 0;
  182. outputBuffer->Cylinders.HighPart = 0;
  183. outputBuffer->TracksPerCylinder = 0;
  184. outputBuffer->SectorsPerTrack = 0;
  185. outputBuffer->BytesPerSector = 0;
  186. } else {
  187. //
  188. // Return the geometry of the current
  189. // media.
  190. //
  191. outputBuffer->MediaType = FixedMedia;
  192. outputBuffer->Cylinders.HighPart = 0;
  193. outputBuffer->Cylinders.LowPart = memcardExtension->ByteCapacity / (8 * 2 * 512);
  194. outputBuffer->TracksPerCylinder = 2;
  195. outputBuffer->SectorsPerTrack = 8;
  196. outputBuffer->BytesPerSector = 512;
  197. }
  198. MemCardDump( MEMCARDIOCTL, ("MemCard: Capacity=%.8x => Cyl=%x\n",
  199. memcardExtension->ByteCapacity, outputBuffer->Cylinders.LowPart));
  200. Irp->IoStatus.Information = sizeof( DISK_GEOMETRY );
  201. break;
  202. }
  203. case IOCTL_DISK_IS_WRITABLE: {
  204. MemCardDump( MEMCARDIOCTL, ("MemCard: DO %.8x Irp %.8x IOCTL_DISK_IS_WRITABLE\n",
  205. DeviceObject, Irp));
  206. if ((memcardExtension->PcmciaInterface.IsWriteProtected)(memcardExtension->UnderlyingPDO)) {
  207. status = STATUS_INVALID_PARAMETER;
  208. } else {
  209. status = STATUS_SUCCESS;
  210. }
  211. break;
  212. }
  213. case IOCTL_DISK_VERIFY: {
  214. PVERIFY_INFORMATION verifyInformation = Irp->AssociatedIrp.SystemBuffer;
  215. if (irpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(VERIFY_INFORMATION)) {
  216. status = STATUS_INVALID_PARAMETER;
  217. break;
  218. }
  219. //NOTE: not implemented
  220. Irp->IoStatus.Information = verifyInformation->Length;
  221. status = STATUS_SUCCESS;
  222. break;
  223. }
  224. case IOCTL_DISK_GET_DRIVE_LAYOUT: {
  225. PDRIVE_LAYOUT_INFORMATION outputBuffer = (PDRIVE_LAYOUT_INFORMATION) Irp->AssociatedIrp.SystemBuffer;
  226. MemCardDump( MEMCARDIOCTL, ("MemCard: DO %.8x Irp %.8x IOCTL_DISK_GET_DRIVE_LAYOUT\n",
  227. DeviceObject, Irp));
  228. if ( irpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(DRIVE_LAYOUT_INFORMATION) ) {
  229. status = STATUS_INVALID_PARAMETER;
  230. break;
  231. }
  232. RtlZeroMemory(outputBuffer, sizeof(DRIVE_LAYOUT_INFORMATION));
  233. outputBuffer->PartitionCount = 1;
  234. outputBuffer->PartitionEntry[0].StartingOffset.LowPart = 512;
  235. outputBuffer->PartitionEntry[0].PartitionLength.LowPart = memcardExtension->ByteCapacity;
  236. outputBuffer->PartitionEntry[0].RecognizedPartition = TRUE;
  237. status = STATUS_SUCCESS;
  238. Irp->IoStatus.Information = sizeof(DRIVE_LAYOUT_INFORMATION);
  239. break;
  240. }
  241. case IOCTL_DISK_GET_PARTITION_INFO: {
  242. PPARTITION_INFORMATION outputBuffer = (PPARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
  243. MemCardDump( MEMCARDIOCTL, ("MemCard: DO %.8x Irp %.8x IOCTL_DISK_GET_PARTITION_INFO\n",
  244. DeviceObject, Irp));
  245. if ( irpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( PARTITION_INFORMATION ) ) {
  246. status = STATUS_INVALID_PARAMETER;
  247. break;
  248. }
  249. RtlZeroMemory(outputBuffer, sizeof(PARTITION_INFORMATION));
  250. outputBuffer->RecognizedPartition = TRUE;
  251. outputBuffer->StartingOffset.LowPart = 512;
  252. outputBuffer->PartitionLength.LowPart = memcardExtension->ByteCapacity;
  253. status = STATUS_SUCCESS;
  254. Irp->IoStatus.Information = sizeof( PARTITION_INFORMATION );
  255. break;
  256. }
  257. case IOCTL_DISK_SET_DRIVE_LAYOUT:
  258. MemCardDump( MEMCARDIOCTL, ("MemCard: DO %.8x Irp %.8x IOCTL_DISK_SET_DRIVE_LAYOUT\n",
  259. DeviceObject, Irp));
  260. case IOCTL_MOUNTMGR_CHANGE_NOTIFY:
  261. case IOCTL_MOUNTDEV_LINK_CREATED:
  262. case IOCTL_MOUNTDEV_LINK_DELETED:
  263. default: {
  264. MemCardDump(MEMCARDIOCTL,
  265. ("MemCard: IOCTL - unsupported device request %.8x\n", irpSp->Parameters.DeviceIoControl.IoControlCode));
  266. status = STATUS_INVALID_DEVICE_REQUEST;
  267. break;
  268. //IoSkipCurrentIrpStackLocation( Irp );
  269. //status = IoCallDriver( memcardExtension->TargetObject, Irp );
  270. //return status;
  271. }
  272. }
  273. if ( status != STATUS_PENDING ) {
  274. Irp->IoStatus.Status = status;
  275. if (!NT_SUCCESS( status ) && IoIsErrorUserInduced( status )) {
  276. IoSetHardErrorOrVerifyDevice( Irp, DeviceObject );
  277. }
  278. MemCardDump( MEMCARDIOCTL, ("MemCard: DO %.8x Irp %.8x IOCTL comp %.8x\n", DeviceObject, Irp, status));
  279. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  280. }
  281. MemCardDump( MEMCARDIOCTL, ("MemCard: DO %.8x Irp %.8x IOCTL <-- %.8x \n", DeviceObject, Irp, status));
  282. return status;
  283. }