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.

488 lines
12 KiB

  1. /*++
  2. Copyright (c) 1989-2000 Microsoft Corporation
  3. Module Name:
  4. DevCtrl.c
  5. Abstract:
  6. This module implements the File System Device Control routines for Udfs
  7. called by the dispatch driver.
  8. // @@BEGIN_DDKSPLIT
  9. Author:
  10. Dan Lovinger {DanLo] 28-Jan-1997
  11. Revision History:
  12. // @@END_DDKSPLIT
  13. --*/
  14. #include "UdfProcs.h"
  15. //
  16. // The Bug check file id for this module
  17. //
  18. #define BugCheckFileId (UDFS_BUG_CHECK_DEVCTRL)
  19. //
  20. // The local debug trace level
  21. //
  22. #define Dbg (UDFS_DEBUG_LEVEL_DEVCTRL)
  23. //
  24. // Local support routines
  25. //
  26. NTSTATUS
  27. UdfDvdReadStructure (
  28. IN PIRP_CONTEXT IrpContext,
  29. IN PIRP Irp,
  30. IN PFCB Fcb
  31. );
  32. NTSTATUS
  33. UdfDvdTransferKey (
  34. IN PIRP_CONTEXT IrpContext,
  35. IN PIRP Irp,
  36. IN PFCB Fcb
  37. );
  38. NTSTATUS
  39. UdfDevCtrlCompletionRoutine (
  40. IN PDEVICE_OBJECT DeviceObject,
  41. IN PIRP Irp,
  42. IN PVOID Contxt
  43. );
  44. #ifdef ALLOC_PRAGMA
  45. #pragma alloc_text(PAGE, UdfCommonDevControl)
  46. #pragma alloc_text(PAGE, UdfDvdReadStructure)
  47. #pragma alloc_text(PAGE, UdfDvdTransferKey)
  48. #endif
  49. NTSTATUS
  50. UdfCommonDevControl (
  51. IN PIRP_CONTEXT IrpContext,
  52. IN PIRP Irp
  53. )
  54. /*++
  55. Routine Description:
  56. This is the common routine for doing Device control operations called
  57. by both the fsd and fsp threads
  58. Arguments:
  59. Irp - Supplies the Irp to process
  60. Return Value:
  61. NTSTATUS - The return status for the operation
  62. --*/
  63. {
  64. NTSTATUS Status;
  65. TYPE_OF_OPEN TypeOfOpen;
  66. PFCB Fcb;
  67. PCCB Ccb;
  68. PIO_STACK_LOCATION IrpSp;
  69. PVOID TargetBuffer;
  70. PAGED_CODE();
  71. //
  72. // Extract and decode the file object.
  73. //
  74. IrpSp = IoGetCurrentIrpStackLocation( Irp );
  75. TypeOfOpen = UdfDecodeFileObject( IrpSp->FileObject,
  76. &Fcb,
  77. &Ccb );
  78. //
  79. // A few IOCTLs actually require some intervention on our part to
  80. // translate some information from file-based to device-based units.
  81. //
  82. if (TypeOfOpen == UserFileOpen) {
  83. UdfAcquireFileShared( IrpContext, Fcb );
  84. try {
  85. UdfVerifyFcbOperation( IrpContext, Fcb);
  86. switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
  87. case IOCTL_DVD_READ_KEY:
  88. case IOCTL_DVD_SEND_KEY:
  89. Status = UdfDvdTransferKey( IrpContext, Irp, Fcb );
  90. break;
  91. case IOCTL_DVD_READ_STRUCTURE:
  92. Status = UdfDvdReadStructure( IrpContext, Irp, Fcb );
  93. break;
  94. case IOCTL_STORAGE_SET_READ_AHEAD:
  95. //
  96. // We're just going to no-op this for now.
  97. //
  98. Status = STATUS_SUCCESS;
  99. UdfCompleteRequest( IrpContext, Irp, Status );
  100. break;
  101. default:
  102. Status = STATUS_INVALID_PARAMETER;
  103. UdfCompleteRequest( IrpContext, Irp, Status );
  104. break;
  105. }
  106. }
  107. finally {
  108. UdfReleaseFile( IrpContext, Fcb);
  109. }
  110. return Status;
  111. }
  112. //
  113. // Now the only type of opens we accept are user volume opens.
  114. //
  115. if (TypeOfOpen != UserVolumeOpen) {
  116. UdfCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
  117. return STATUS_INVALID_PARAMETER;
  118. }
  119. //
  120. // Handle the case of the disk type ourselves. We're really just going to
  121. // lie about this, but it is a good lie.
  122. //
  123. if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_CDROM_DISK_TYPE) {
  124. //
  125. // Verify the Vcb in this case to detect if the volume has changed.
  126. //
  127. UdfVerifyVcb( IrpContext, Fcb->Vcb );
  128. //
  129. // Check the size of the output buffer.
  130. //
  131. if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof( CDROM_DISK_DATA )) {
  132. UdfCompleteRequest( IrpContext, Irp, STATUS_BUFFER_TOO_SMALL );
  133. return STATUS_BUFFER_TOO_SMALL;
  134. }
  135. //
  136. // Copy the data from the Vcb.
  137. //
  138. ((PCDROM_DISK_DATA) Irp->AssociatedIrp.SystemBuffer)->DiskData = CDROM_DISK_DATA_TRACK;
  139. Irp->IoStatus.Information = sizeof( CDROM_DISK_DATA );
  140. UdfCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
  141. return STATUS_SUCCESS;
  142. }
  143. //
  144. // Copy the arguments and set up the completion routine
  145. //
  146. IoCopyCurrentIrpStackLocationToNext( Irp );
  147. IoSetCompletionRoutine( Irp,
  148. UdfDevCtrlCompletionRoutine,
  149. NULL,
  150. TRUE,
  151. TRUE,
  152. TRUE );
  153. //
  154. // Send the request.
  155. //
  156. Status = IoCallDriver( IrpContext->Vcb->TargetDeviceObject, Irp );
  157. //
  158. // Cleanup our Irp Context. The driver has completed the Irp.
  159. //
  160. UdfCompleteRequest( IrpContext, NULL, STATUS_SUCCESS );
  161. return Status;
  162. }
  163. NTSTATUS
  164. UdfDvdTransferKey (
  165. IN PIRP_CONTEXT IrpContext,
  166. IN PIRP Irp,
  167. IN PFCB Fcb
  168. )
  169. /*++
  170. Routine Description:
  171. This routine handles the special form of the Dvd key negotiation IOCTLs
  172. performed in the context of a file. For these IOCTLs, the incoming parameter
  173. is in file-relative form, which must be translated to a device-relatvie form
  174. before it can continue.
  175. Arguments:
  176. Irp - Supplies the Irp to process
  177. Fcb - Supplies the file being operated with
  178. Return Value:
  179. NTSTATUS - The return status for the operation
  180. --*/
  181. {
  182. NTSTATUS Status = STATUS_INVALID_PARAMETER;
  183. PDVD_COPY_PROTECT_KEY TransferKey;
  184. LARGE_INTEGER Offset;
  185. BOOLEAN Result;
  186. PIO_STACK_LOCATION IrpSp;
  187. //
  188. // Grab the input buffer and confirm basic validity.
  189. //
  190. IrpSp = IoGetCurrentIrpStackLocation( Irp );
  191. TransferKey = (PDVD_COPY_PROTECT_KEY) Irp->AssociatedIrp.SystemBuffer;
  192. if ((IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(DVD_COPY_PROTECT_KEY)) ||
  193. (TransferKey->Parameters.TitleOffset.QuadPart >= Fcb->FileSize.QuadPart)) {
  194. UdfCompleteRequest( IrpContext, Irp, Status );
  195. return Status;
  196. }
  197. //
  198. // Now, convert the file byte offset in the structure to a physical sector.
  199. //
  200. Result = FsRtlLookupLargeMcbEntry( &Fcb->Mcb,
  201. LlSectorsFromBytes( Fcb->Vcb, TransferKey->Parameters.TitleOffset.QuadPart ),
  202. &Offset.QuadPart,
  203. NULL,
  204. NULL,
  205. NULL,
  206. NULL );
  207. //
  208. // If we failed the lookup, we know that this must be some form of unrecorded
  209. // extent on the media. This IOCTL is ill-defined at this point, so we have
  210. // to give up.
  211. //
  212. if (!Result || Offset.QuadPart == -1) {
  213. UdfCompleteRequest( IrpContext, Irp, Status );
  214. return Status;
  215. }
  216. //
  217. // The input is buffered from user space, so we know we can just rewrite it.
  218. //
  219. TransferKey->Parameters.TitleOffset.QuadPart = LlBytesFromSectors( Fcb->Vcb, Offset.QuadPart );
  220. //
  221. // Copy the arguments and set up the completion routine
  222. //
  223. IoCopyCurrentIrpStackLocationToNext( Irp );
  224. IoSetCompletionRoutine( Irp,
  225. UdfDevCtrlCompletionRoutine,
  226. NULL,
  227. TRUE,
  228. TRUE,
  229. TRUE );
  230. //
  231. // Send the request.
  232. //
  233. Status = IoCallDriver( IrpContext->Vcb->TargetDeviceObject, Irp );
  234. //
  235. // Cleanup our Irp Context. The driver has completed the Irp.
  236. //
  237. UdfCompleteRequest( IrpContext, NULL, STATUS_SUCCESS );
  238. return Status;
  239. }
  240. NTSTATUS
  241. UdfDvdReadStructure (
  242. IN PIRP_CONTEXT IrpContext,
  243. IN PIRP Irp,
  244. IN PFCB Fcb
  245. )
  246. /*++
  247. Routine Description:
  248. This routine handles the special form of the Dvd structure reading IOCTLs
  249. performed in the context of a file. For these IOCTLs, the incoming parameter
  250. is in file-relative form, which must be translated to a device-relatvie form
  251. before it can continue.
  252. Arguments:
  253. Irp - Supplies the Irp to process
  254. Fcb - Supplies the file being operated with
  255. Return Value:
  256. NTSTATUS - The return status for the operation
  257. --*/
  258. {
  259. NTSTATUS Status = STATUS_INVALID_PARAMETER;
  260. PDVD_READ_STRUCTURE ReadStructure;
  261. LARGE_INTEGER Offset;
  262. BOOLEAN Result;
  263. PIO_STACK_LOCATION IrpSp;
  264. //
  265. // Grab the input buffer and confirm basic validity.
  266. //
  267. IrpSp = IoGetCurrentIrpStackLocation( Irp );
  268. ReadStructure = (PDVD_READ_STRUCTURE) Irp->AssociatedIrp.SystemBuffer;
  269. if ((IrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof(DVD_READ_STRUCTURE)) ||
  270. (ReadStructure->BlockByteOffset.QuadPart >= Fcb->FileSize.QuadPart)) {
  271. UdfCompleteRequest( IrpContext, Irp, Status );
  272. return Status;
  273. }
  274. //
  275. // Now, convert the file byte offset in the structure to a physical sector.
  276. //
  277. Result = FsRtlLookupLargeMcbEntry( &Fcb->Mcb,
  278. LlSectorsFromBytes( Fcb->Vcb, ReadStructure->BlockByteOffset.QuadPart ),
  279. &Offset.QuadPart,
  280. NULL,
  281. NULL,
  282. NULL,
  283. NULL );
  284. //
  285. // If we failed the lookup, we know that this must be some form of unrecorded
  286. // extent on the media. This IOCTL is ill-defined at this point, so we have
  287. // to give up.
  288. //
  289. if (!Result || Offset.QuadPart == -1) {
  290. UdfCompleteRequest( IrpContext, Irp, Status );
  291. return Status;
  292. }
  293. //
  294. // The input is buffered from user space, so we know we can just rewrite it.
  295. //
  296. ReadStructure->BlockByteOffset.QuadPart = LlBytesFromSectors( Fcb->Vcb, Offset.QuadPart );
  297. //
  298. // Copy the arguments and set up the completion routine
  299. //
  300. IoCopyCurrentIrpStackLocationToNext( Irp );
  301. IoSetCompletionRoutine( Irp,
  302. UdfDevCtrlCompletionRoutine,
  303. NULL,
  304. TRUE,
  305. TRUE,
  306. TRUE );
  307. //
  308. // Send the request.
  309. //
  310. Status = IoCallDriver( IrpContext->Vcb->TargetDeviceObject, Irp );
  311. //
  312. // Cleanup our Irp Context. The driver has completed the Irp.
  313. //
  314. UdfCompleteRequest( IrpContext, NULL, STATUS_SUCCESS );
  315. return Status;
  316. }
  317. //
  318. // Local support routine
  319. //
  320. NTSTATUS
  321. UdfDevCtrlCompletionRoutine (
  322. IN PDEVICE_OBJECT DeviceObject,
  323. IN PIRP Irp,
  324. IN PVOID Contxt
  325. )
  326. {
  327. //
  328. // Add the hack-o-ramma to fix formats.
  329. //
  330. if (Irp->PendingReturned) {
  331. IoMarkIrpPending( Irp );
  332. }
  333. return STATUS_SUCCESS;
  334. UNREFERENCED_PARAMETER( DeviceObject );
  335. UNREFERENCED_PARAMETER( Contxt );
  336. }