|
|
1.1 ! root 1: /* Copyright (C) 2004 TrueCrypt Team, truecrypt.org ! 2: This product uses components written by Paul Le Roux <[email protected]> */ ! 3: ! 4: #include "TCdefs.h" ! 5: #include "crypto.h" ! 6: #include "fat.h" ! 7: #include "volumes.h" ! 8: ! 9: #include "apidrvr.h" ! 10: #include "ntdriver.h" ! 11: #include "ntvol.h" ! 12: #include "ntrawdv.h" ! 13: #include "ntfiledv.h" ! 14: ! 15: #include "cache.h" ! 16: ! 17: //#ifdef _DEBUG ! 18: //#define EXTRA_INFO 1 ! 19: //#endif ! 20: ! 21: #pragma warning( disable : 4127 ) ! 22: ! 23: #define FIRST_READ_SIZE SECTOR_SIZE*2 ! 24: ! 25: NTSTATUS ! 26: TCOpenVolume (PDEVICE_OBJECT DeviceObject, ! 27: PEXTENSION Extension, ! 28: MOUNT_STRUCT * mount, ! 29: PWSTR pwszMountVolume, ! 30: BOOL bRawDevice) ! 31: { ! 32: struct msdos_boot_sector *boot_sector = NULL; ! 33: FILE_STANDARD_INFORMATION FileStandardInfo; ! 34: FILE_BASIC_INFORMATION FileBasicInfo; ! 35: OBJECT_ATTRIBUTES oaFileAttributes; ! 36: UNICODE_STRING FullFileName; ! 37: IO_STATUS_BLOCK IoStatusBlock; ! 38: LARGE_INTEGER lDiskLength; ! 39: char *readBuffer; ! 40: NTSTATUS ntStatus; ! 41: ! 42: Extension->pfoDeviceFile = NULL; ! 43: Extension->hDeviceFile = NULL; ! 44: ! 45: readBuffer = TCalloc (FIRST_READ_SIZE); ! 46: if (readBuffer == NULL) ! 47: { ! 48: ntStatus = STATUS_INSUFFICIENT_RESOURCES; ! 49: goto error; ! 50: } ! 51: ! 52: RtlInitUnicodeString (&FullFileName, pwszMountVolume); ! 53: ! 54: InitializeObjectAttributes (&oaFileAttributes, &FullFileName, OBJ_CASE_INSENSITIVE, ! 55: NULL, NULL); ! 56: ! 57: ntStatus = ZwCreateFile (&Extension->hDeviceFile, ! 58: GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, ! 59: &oaFileAttributes, ! 60: &IoStatusBlock, ! 61: NULL, ! 62: FILE_ATTRIBUTE_NORMAL | ! 63: FILE_ATTRIBUTE_SYSTEM, ! 64: 0, ! 65: FILE_OPEN, ! 66: FILE_WRITE_THROUGH | ! 67: FILE_NO_INTERMEDIATE_BUFFERING | ! 68: FILE_SYNCHRONOUS_IO_NONALERT, ! 69: NULL, ! 70: 0); ! 71: ! 72: /* 26-4-99 NT for some partitions returns this code, it is really a ! 73: access denied */ ! 74: if (ntStatus == 0xc000001b) ! 75: { ! 76: ntStatus = STATUS_ACCESS_DENIED; ! 77: } ! 78: ! 79: if (ntStatus == STATUS_ACCESS_DENIED) ! 80: { ! 81: ntStatus = ZwCreateFile (&Extension->hDeviceFile, ! 82: GENERIC_READ | SYNCHRONIZE, ! 83: &oaFileAttributes, ! 84: &IoStatusBlock, ! 85: NULL, ! 86: FILE_ATTRIBUTE_NORMAL | ! 87: FILE_ATTRIBUTE_SYSTEM, ! 88: 0, ! 89: FILE_OPEN, ! 90: FILE_WRITE_THROUGH | ! 91: FILE_NO_INTERMEDIATE_BUFFERING | ! 92: FILE_SYNCHRONOUS_IO_NONALERT, ! 93: NULL, ! 94: 0); ! 95: Extension->bReadOnly = TRUE; ! 96: } ! 97: else ! 98: Extension->bReadOnly = FALSE; ! 99: ! 100: /* 26-4-99 NT for some partitions returns this code, it is really a ! 101: access denied */ ! 102: if (ntStatus == 0xc000001b) ! 103: { ! 104: /* Partitions which return this code can still be opened with ! 105: FILE_SHARE_READ but this causes NT problems elsewhere in ! 106: particular if you do FILE_SHARE_READ NT will die later if ! 107: anyone even tries to open the partition (or file for that ! 108: matter...) */ ! 109: ntStatus = STATUS_SHARING_VIOLATION; ! 110: } ! 111: ! 112: if (!NT_SUCCESS (ntStatus)) ! 113: { ! 114: goto error; ! 115: } ! 116: ! 117: ntStatus = ZwReadFile (Extension->hDeviceFile, NULL, NULL, NULL, ! 118: &IoStatusBlock, readBuffer, FIRST_READ_SIZE, NULL, NULL); ! 119: ! 120: if (!NT_SUCCESS (ntStatus)) ! 121: { ! 122: Dump ("Read failed: NTSTATUS 0x%08x\n", ntStatus); ! 123: } ! 124: else if (IoStatusBlock.Information != FIRST_READ_SIZE) ! 125: { ! 126: Dump ("Read didn't read enough data in: %lu / %lu\n", IoStatusBlock.Information, FIRST_READ_SIZE); ! 127: ntStatus = STATUS_UNSUCCESSFUL; ! 128: } ! 129: ! 130: if (!NT_SUCCESS (ntStatus)) ! 131: { ! 132: goto error; ! 133: } ! 134: ! 135: ! 136: KeInitializeEvent (&Extension->keVolumeEvent, NotificationEvent, FALSE); ! 137: ! 138: if (bRawDevice == FALSE) ! 139: { ! 140: ntStatus = ZwQueryInformationFile (Extension->hDeviceFile, ! 141: &IoStatusBlock, ! 142: &FileBasicInfo, ! 143: sizeof (FileBasicInfo), ! 144: FileBasicInformation); ! 145: ! 146: if (NT_SUCCESS (ntStatus)) ! 147: ntStatus = ZwQueryInformationFile (Extension->hDeviceFile, ! 148: &IoStatusBlock, ! 149: &FileStandardInfo, ! 150: sizeof (FileStandardInfo), ! 151: FileStandardInformation); ! 152: ! 153: if (!NT_SUCCESS (ntStatus)) ! 154: { ! 155: Dump ("ZwQueryInformationFile failed while opening file: NTSTATUS 0x%08x\n", ! 156: ntStatus); ! 157: goto error; ! 158: } ! 159: else ! 160: lDiskLength.QuadPart = FileStandardInfo.EndOfFile.QuadPart; ! 161: ! 162: if (FileBasicInfo.FileAttributes & FILE_ATTRIBUTE_COMPRESSED) ! 163: { ! 164: Dump ("File \"%ls\" is marked as compressed - not supported!\n", pwszMountVolume); ! 165: mount->nReturnCode = ERR_COMPRESSION_NOT_SUPPORTED; ! 166: ntStatus = STATUS_SUCCESS; ! 167: goto error; ! 168: } ! 169: ! 170: ntStatus = ObReferenceObjectByHandle (Extension->hDeviceFile, ! 171: FILE_ALL_ACCESS, ! 172: *IoFileObjectType, ! 173: KernelMode, ! 174: &Extension->pfoDeviceFile, ! 175: 0); ! 176: ! 177: if (!NT_SUCCESS (ntStatus)) ! 178: { ! 179: goto error; ! 180: } ! 181: ! 182: /* Get the FSD device for the file (probably either NTFS or ! 183: FAT) */ ! 184: Extension->pFsdDevice = IoGetRelatedDeviceObject (Extension->pfoDeviceFile); ! 185: ! 186: DeviceObject->StackSize = (CCHAR) (Extension->pFsdDevice->StackSize + 1); ! 187: ! 188: } ! 189: else ! 190: { ! 191: DISK_GEOMETRY dg; ! 192: ! 193: ZwClose (Extension->hDeviceFile); ! 194: Extension->hDeviceFile = NULL; ! 195: ! 196: if (Extension->bReadOnly == TRUE) ! 197: ntStatus = IoGetDeviceObjectPointer (&FullFileName, ! 198: FILE_READ_DATA, ! 199: &Extension->pfoDeviceFile, ! 200: &Extension->pFsdDevice); ! 201: else ! 202: ntStatus = IoGetDeviceObjectPointer (&FullFileName, ! 203: FILE_ALL_ACCESS, ! 204: &Extension->pfoDeviceFile, ! 205: &Extension->pFsdDevice); ! 206: ! 207: if (!NT_SUCCESS (ntStatus)) ! 208: { ! 209: goto error; ! 210: } ! 211: ! 212: DeviceObject->StackSize = (CCHAR) (Extension->pFsdDevice->StackSize + 1); ! 213: ! 214: ! 215: if (wcscmp (Extension->pFsdDevice->DriverObject->DriverName.Buffer, WIDE ("\\FileSystem\\RAW")) != 0) ! 216: { ! 217: /* FAT/NTFS "knows" about this device */ ! 218: ntStatus = STATUS_SHARING_VIOLATION; ! 219: goto error; ! 220: } ! 221: ! 222: ntStatus = TCSendDeviceIoControlRequest (DeviceObject, ! 223: Extension, IOCTL_DISK_GET_DRIVE_GEOMETRY, ! 224: (char *) &dg, sizeof (dg)); ! 225: ! 226: if (!NT_SUCCESS (ntStatus)) ! 227: { ! 228: goto error; ! 229: } ! 230: ! 231: if (dg.MediaType == FixedMedia) ! 232: { ! 233: PARTITION_INFORMATION pi; ! 234: ! 235: ntStatus = TCSendDeviceIoControlRequest (DeviceObject, ! 236: Extension, IOCTL_DISK_GET_PARTITION_INFO, ! 237: (char *) &pi, sizeof (pi)); ! 238: ! 239: if (!NT_SUCCESS (ntStatus)) ! 240: { ! 241: goto error; ! 242: } ! 243: else ! 244: lDiskLength.QuadPart = pi.PartitionLength.QuadPart; ! 245: ! 246: } ! 247: else ! 248: { ! 249: lDiskLength.QuadPart = dg.Cylinders.QuadPart * dg.SectorsPerTrack * ! 250: dg.TracksPerCylinder * dg.BytesPerSector; ! 251: } ! 252: ! 253: ! 254: } ! 255: ! 256: if (lDiskLength.QuadPart < MIN_VOLUME_SIZE || lDiskLength.QuadPart > MAX_VOLUME_SIZE) ! 257: { ! 258: /* Volume too large or too small for us to handle... */ ! 259: mount->nReturnCode = ERR_VOL_SIZE_WRONG; ! 260: ntStatus = STATUS_SUCCESS; ! 261: goto error; ! 262: } ! 263: else ! 264: Extension->DiskLength = lDiskLength.QuadPart; ! 265: ! 266: /* Attempt to recognize the volume */ ! 267: ! 268: KeWaitForMutexObject (&driverMutex, Executive, KernelMode, ! 269: FALSE, NULL); ! 270: ! 271: mount->nReturnCode = VolumeReadHeaderCache ( ! 272: mount->bCache, ! 273: readBuffer, ! 274: mount->szPassword, ! 275: strlen (mount->szPassword), ! 276: &Extension->cryptoInfo); ! 277: ! 278: KeReleaseMutex (&driverMutex, FALSE); ! 279: ! 280: if (mount->nReturnCode == 0) ! 281: { ! 282: /* Handle the volume setup for TC */ ! 283: ! 284: boot_sector = (struct msdos_boot_sector *) (readBuffer + SECTOR_SIZE); ! 285: ! 286: /* It's in the volume file so we must decrypt it */ ! 287: Extension->cryptoInfo->decrypt_sector ((ULONG *) boot_sector, 1, 1, ! 288: &Extension->cryptoInfo->ks[0], ! 289: Extension->cryptoInfo->iv, ! 290: Extension->cryptoInfo->cipher); ! 291: ! 292: /* There's one extra sector than there should be */ ! 293: Extension->DiskLength -= SECTOR_SIZE; ! 294: ! 295: /* Volume setup end */ ! 296: ! 297: //Extension->TracksPerCylinder = boot_sector->heads; ! 298: //Extension->SectorsPerTrack = boot_sector->secs_track; ! 299: //Extension->NumberOfCylinders = (ULONG) (Extension->DiskLength / Extension->BytesPerSector / ! 300: // Extension->SectorsPerTrack / Extension->TracksPerCylinder); ! 301: Extension->TracksPerCylinder = 1; ! 302: Extension->SectorsPerTrack = 1; ! 303: Extension->BytesPerSector = *((unsigned short *) boot_sector->sector_size); ! 304: Extension->NumberOfCylinders = Extension->DiskLength / Extension->BytesPerSector; ! 305: ! 306: Extension->PartitionType = (UCHAR) ((boot_sector->fs_type[4] == '6') ? ! 307: PARTITION_FAT_16 : PARTITION_FAT_12); ! 308: if(boot_sector->fs_type[3] == '3') Extension->PartitionType = (UCHAR) PARTITION_FAT32; ! 309: ! 310: Extension->bRawDevice = bRawDevice; ! 311: ! 312: if (wcslen (pwszMountVolume) < 64) ! 313: wcscpy (Extension->wszVolume, pwszMountVolume); ! 314: else ! 315: { ! 316: memcpy (Extension->wszVolume, pwszMountVolume, 60 * 2); ! 317: Extension->wszVolume[60] = (WCHAR) '.'; ! 318: Extension->wszVolume[61] = (WCHAR) '.'; ! 319: Extension->wszVolume[62] = (WCHAR) '.'; ! 320: Extension->wszVolume[63] = (WCHAR) 0; ! 321: } ! 322: ! 323: Extension->mountTime = mount->time; ! 324: ! 325: TCfree (readBuffer); ! 326: ! 327: return STATUS_SUCCESS; ! 328: } ! 329: ! 330: ! 331: /* Failed due to some non-OS reason so we drop through and return NT ! 332: SUCCESS then nReturnCode is checked later in user-mode */ ! 333: ! 334: if (mount->nReturnCode == ERR_OUTOFMEMORY) ! 335: ntStatus = STATUS_INSUFFICIENT_RESOURCES; ! 336: else ! 337: ntStatus = STATUS_SUCCESS; ! 338: ! 339: error: ! 340: ! 341: /* Close the hDeviceFile */ ! 342: if (Extension->hDeviceFile != NULL) ! 343: ZwClose (Extension->hDeviceFile); ! 344: ! 345: /* The cryptoInfo pointer is deallocated if the readheader routines ! 346: fail so there is no need to deallocate here */ ! 347: ! 348: /* Dereference the user-mode file object */ ! 349: if (Extension->pfoDeviceFile != NULL) ! 350: ObDereferenceObject (Extension->pfoDeviceFile); ! 351: ! 352: /* Free the tmp IO buffer */ ! 353: if (readBuffer != NULL) ! 354: TCfree (readBuffer); ! 355: ! 356: return ntStatus; ! 357: } ! 358: ! 359: void ! 360: TCCloseVolume (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension) ! 361: { ! 362: if (DeviceObject); /* Remove compiler warning */ ! 363: ! 364: if (Extension->hDeviceFile != NULL) ! 365: ZwClose (Extension->hDeviceFile); ! 366: ObDereferenceObject (Extension->pfoDeviceFile); ! 367: crypto_close (Extension->cryptoInfo); ! 368: ! 369: } ! 370: ! 371: /* This rountine can be called at any IRQL so we need to tread carefully. Not ! 372: even DbgPrint or KdPrint are called here as the kernel sometimes faults if ! 373: they are called at high IRQL */ ! 374: ! 375: NTSTATUS ! 376: TCCompletion (PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID pUserBuffer) ! 377: { ! 378: PIO_STACK_LOCATION irpSp; ! 379: PEXTENSION Extension; ! 380: NTSTATUS ntStatus; ! 381: ! 382: Extension = (PEXTENSION) DeviceObject->DeviceExtension; ! 383: ! 384: /* Check to make sure the DeviceObject passed in is actually ours! */ ! 385: if (Extension->lMagicNumber != 0xabfeacde) ! 386: KeBugCheck ((ULONG) 0xabfeacde); ! 387: ! 388: ASSERT (Extension->nDosDriveNo >= 0 && Extension->nDosDriveNo <= 0x19); ! 389: ! 390: #ifdef USE_KERNEL_MUTEX ! 391: KeWaitForMutexObject (&Extension->KernelMutex, Executive, KernelMode, ! 392: FALSE, NULL); ! 393: #endif ! 394: ! 395: #if EXTRA_INFO ! 396: Dump ("Completing IRP...BEGIN\n"); ! 397: Dump ("COMPLETION USER BUFFER IS 0x%08x MDL ADDRESS IS 0x%08x\n", Irp->UserBuffer, Irp->MdlAddress); ! 398: Dump ("COMPLETION Irp->Tail.Overlay.OriginalFileObject = 0x%08x\n", Irp->Tail.Overlay.OriginalFileObject); ! 399: Dump ("Completing DeviceObject 0x%08x Irp 0x%08x\n", DeviceObject, Irp); ! 400: #endif ! 401: ! 402: /* Note: The Irp stack location we get back here is our one, we setup ! 403: the next stack location with a copy of this stack data in the send ! 404: function... here we always get back our own stack location, so ! 405: it's possible to use Read.Key to store extra pointers if needed. */ ! 406: irpSp = IoGetCurrentIrpStackLocation (Irp); ! 407: ! 408: ntStatus = Irp->IoStatus.Status; ! 409: ! 410: if (ntStatus == STATUS_TOO_LATE) ! 411: KeBugCheck ((ULONG) 0x50ff); ! 412: ! 413: if (Irp->PendingReturned) /* From Windows NT File System ! 414: Internals */ ! 415: IoMarkIrpPending (Irp); ! 416: ! 417: if (Extension->bRawDevice == FALSE) ! 418: { ! 419: /* Note: For some reason even though we used DIRECT_IO ! 420: sometimes the Irp's come back to use with MDLs !! if we ! 421: get an MDL here we need to free it up otherwise later when ! 422: we call IoFreeIrp the system will trap */ ! 423: ! 424: PMDL pMdl, pNextMdl; ! 425: ! 426: pMdl = Irp->MdlAddress; ! 427: ! 428: while (pMdl != NULL) ! 429: { ! 430: pNextMdl = pMdl->Next; ! 431: ! 432: MmUnmapLockedPages (MmGetSystemAddressForMdlSafe (pMdl, HighPagePriority), pMdl); ! 433: MmUnlockPages (pMdl); ! 434: IoFreeMdl (pMdl); ! 435: ! 436: pMdl = pNextMdl; ! 437: } ! 438: } ! 439: ! 440: if (NT_SUCCESS (Irp->IoStatus.Status) && irpSp->MajorFunction == IRP_MJ_READ) ! 441: { ! 442: __int64 tmpOffset = irpSp->Parameters.Read.ByteOffset.QuadPart; ! 443: ULONG tmpLength = irpSp->Parameters.Read.Length; ! 444: PUCHAR CurrentAddress; ! 445: ! 446: if (Extension->bRawDevice == TRUE) ! 447: CurrentAddress = MmGetSystemAddressForMdlSafe (Irp->MdlAddress, HighPagePriority); ! 448: else ! 449: CurrentAddress = Irp->UserBuffer; ! 450: ! 451: if (tmpLength > 0) ! 452: { ! 453: /* Decrypt the data on read */ ! 454: Extension->cryptoInfo->decrypt_sector ((ULONG *) CurrentAddress, ! 455: tmpOffset / SECTOR_SIZE, ! 456: tmpLength / SECTOR_SIZE, ! 457: &Extension->cryptoInfo->ks[0], ! 458: Extension->cryptoInfo->iv, ! 459: Extension->cryptoInfo->cipher); ! 460: } ! 461: ! 462: if (Extension->bRawDevice == FALSE) ! 463: { ! 464: PIRP OldIrp = (PIRP) pUserBuffer; ! 465: PUCHAR OriginalAddress; ! 466: CurrentAddress = Irp->UserBuffer; ! 467: OriginalAddress = MmGetSystemAddressForMdlSafe (OldIrp->MdlAddress, HighPagePriority); ! 468: memcpy (OriginalAddress, CurrentAddress, Irp->IoStatus.Information); ! 469: } ! 470: ! 471: } ! 472: ! 473: if (NT_SUCCESS (Irp->IoStatus.Status) && irpSp->MajorFunction == IRP_MJ_WRITE) ! 474: { ! 475: PUCHAR CurrentAddress; ! 476: PUCHAR OriginalAddress; ! 477: ! 478: if (Extension->bRawDevice == TRUE) ! 479: { ! 480: CurrentAddress = MmGetSystemAddressForMdlSafe (Irp->MdlAddress, HighPagePriority); ! 481: OriginalAddress = MmGetSystemAddressForMdlSafe ((PMDL) pUserBuffer, HighPagePriority); ! 482: } ! 483: else ! 484: { ! 485: PIRP OldIrp = (PIRP) pUserBuffer; ! 486: CurrentAddress = Irp->UserBuffer; ! 487: OriginalAddress = MmGetSystemAddressForMdlSafe (OldIrp->MdlAddress, HighPagePriority); ! 488: } ! 489: ! 490: //if (NT_SUCCESS (Irp->IoStatus.Status)) ! 491: //{ ! 492: // __int64 tmpOffset = irpSp->Parameters.Read.ByteOffset.QuadPart; ! 493: //} ! 494: } ! 495: ! 496: if (Extension->bRawDevice == TRUE && irpSp->MajorFunction == IRP_MJ_WRITE) ! 497: { ! 498: PUCHAR tmpBuffer = MmGetSystemAddressForMdlSafe (Irp->MdlAddress, HighPagePriority); ! 499: /* Free the temp buffer we allocated */ ! 500: TCfree (tmpBuffer); ! 501: /* Free the Mdl we allocated */ ! 502: IoFreeMdl (Irp->MdlAddress); ! 503: /* Reset the Irp */ ! 504: Irp->MdlAddress = pUserBuffer; ! 505: } ! 506: ! 507: if (Extension->bRawDevice == TRUE && irpSp->MajorFunction == IRP_MJ_READ) ! 508: { ! 509: /* Nothing to do */ ! 510: } ! 511: ! 512: #if EXTRA_INFO ! 513: Dump ("COMPLETION OLD USER BUFFER IS 0x%08x MDL ADDRESS IS 0x%08x\n", Irp->UserBuffer, Irp->MdlAddress); ! 514: Dump ("COMPLETION OLD Irp->Tail.Overlay.OriginalFileObject = 0x%08x\n", Irp->Tail.Overlay.OriginalFileObject); ! 515: Dump ("Completing IRP 0x%08x NTSTATUS 0x%08x information %lu END\n", (ULONG) irpSp->MajorFunction, ! 516: Irp->IoStatus.Status, Irp->IoStatus.Information); ! 517: #endif ! 518: ! 519: if (Extension->bRawDevice == FALSE) ! 520: { ! 521: PIRP OldIrp = (PIRP) pUserBuffer; ! 522: PVOID tmpBuffer = Irp->UserBuffer; ! 523: BOOL bFreeBuffer = irpSp->MajorFunction == IRP_MJ_WRITE || irpSp->MajorFunction == IRP_MJ_READ; ! 524: ! 525: OldIrp->IoStatus.Status = Irp->IoStatus.Status; ! 526: OldIrp->IoStatus.Information = Irp->IoStatus.Information; ! 527: ! 528: IoCompleteRequest (OldIrp, IO_DISK_INCREMENT); ! 529: ! 530: #if EXTRA_INFO ! 531: Dump ("About to free allocated IRP\n"); ! 532: #endif ! 533: ! 534: Irp->UserBuffer = NULL; ! 535: ! 536: /* Free the allocated IRP. Note: This must be done before we ! 537: free tmpBuffer! */ ! 538: IoFreeIrp (Irp); ! 539: ! 540: /* Note: From here on we cannot touch the Irp or irpSp */ ! 541: ! 542: #if EXTRA_INFO ! 543: Dump ("Free allocated buffer = %d\n", bFreeBuffer); ! 544: #endif ! 545: ! 546: if (bFreeBuffer == TRUE) ! 547: TCfree (tmpBuffer); ! 548: ! 549: ntStatus = STATUS_MORE_PROCESSING_REQUIRED; ! 550: } ! 551: ! 552: #ifdef USE_KERNEL_MUTEX ! 553: KeReleaseMutex (&Extension->KernelMutex, FALSE); ! 554: #endif ! 555: ! 556: return ntStatus; ! 557: } ! 558: ! 559: NTSTATUS ! 560: TCReadWrite (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension, PIRP Irp) ! 561: { ! 562: PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp); ! 563: PUCHAR tmpBuffer = NULL;/* Remove compiler warning */ ! 564: NTSTATUS ntStatus; ! 565: ! 566: // Dump ("TCReadWrite BEGIN\n"); ! 567: ! 568: /* Check for invalid parameters. It is an error for the starting ! 569: offset + length to go past the end of the buffer, or for the ! 570: length to not be a proper multiple of the sector size. Others are ! 571: possible, but we don't check them since we trust the file system ! 572: and they aren't deadly. */ ! 573: if (irpSp->Parameters.Read.ByteOffset.QuadPart + irpSp->Parameters.Read.Length > Extension->DiskLength ! 574: || (irpSp->Parameters.Read.Length & (Extension->BytesPerSector - 1))) ! 575: { ! 576: return COMPLETE_IRP (DeviceObject, Irp, STATUS_INVALID_PARAMETER, 0); ! 577: } ! 578: else ! 579: { ! 580: if (irpSp->Parameters.Read.Length == 0) ! 581: { ! 582: return COMPLETE_IRP (DeviceObject, Irp, STATUS_INVALID_PARAMETER, 0); ! 583: } ! 584: } ! 585: ! 586: #if EXTRA_INFO ! 587: Dump ("USER BUFFER IS 0x%08x MDL ADDRESS IS 0x%08x\n", Irp->UserBuffer, Irp->MdlAddress); ! 588: Dump ("Irp->Tail.Overlay.OriginalFileObject = 0x%08x\n", Irp->Tail.Overlay.OriginalFileObject); ! 589: Dump ("irpSp->FileObject = 0x%08x\n", irpSp->FileObject); ! 590: ! 591: if (Irp->Tail.Overlay.OriginalFileObject != NULL) ! 592: { ! 593: if (Irp->Tail.Overlay.OriginalFileObject->FileName.Length != 0) ! 594: Dump ("Irp->Tail.Overlay.OriginalFileObject = %ls\n", Irp->Tail.Overlay.OriginalFileObject->FileName.Buffer); ! 595: else ! 596: Dump ("Irp->Tail.Overlay.OriginalFileObject = %ls\n", WIDE ("null value")); ! 597: ! 598: } ! 599: ! 600: if (irpSp->FileObject != NULL) ! 601: { ! 602: if (irpSp->FileObject->FileName.Length != 0) ! 603: Dump ("irpSp->FileObject = %ls\n", irpSp->FileObject->FileName.Buffer); ! 604: else ! 605: Dump ("irpSp->FileObject = %ls\n", WIDE ("null value")); ! 606: ! 607: } ! 608: #endif ! 609: ! 610: if (Extension->bReadOnly == TRUE && irpSp->MajorFunction == IRP_MJ_WRITE) ! 611: return COMPLETE_IRP (DeviceObject, Irp, STATUS_MEDIA_WRITE_PROTECTED, 0); ! 612: ! 613: if (Extension->bRawDevice == FALSE || irpSp->MajorFunction == IRP_MJ_WRITE) ! 614: { ! 615: tmpBuffer = TCalloc (irpSp->Parameters.Read.Length); ! 616: if (tmpBuffer == NULL) ! 617: return COMPLETE_IRP (DeviceObject, Irp, STATUS_INSUFFICIENT_RESOURCES, 0); ! 618: } ! 619: ! 620: if (irpSp->MajorFunction == IRP_MJ_READ) ! 621: { ! 622: // Dump ("Read: 0x%08x for %lu bytes...\n", irpSp->Parameters.Read.ByteOffset.LowPart, ! 623: // irpSp->Parameters.Read.Length); ! 624: ! 625: /* Fixup the parameters to handle this particular volume type */ ! 626: irpSp->Parameters.Read.ByteOffset.QuadPart += SECTOR_SIZE; ! 627: ! 628: if (Extension->bRawDevice == TRUE) ! 629: ntStatus = TCSendIRP_RawDevice (DeviceObject, Extension, ! 630: NULL, IRP_READ_OPERATION | IRP_NOCACHE, ! 631: irpSp->MajorFunction, ! 632: Irp); ! 633: else ! 634: ntStatus = TCSendIRP_FileDevice (DeviceObject, Extension, ! 635: tmpBuffer, IRP_READ_OPERATION | IRP_NOCACHE, ! 636: irpSp->MajorFunction, ! 637: Irp); ! 638: } ! 639: else ! 640: { ! 641: PUCHAR CurrentAddress; ! 642: ! 643: // Dump ("Write: 0x%08x for %lu bytes...\n", irpSp->Parameters.Read.ByteOffset.LowPart, ! 644: // irpSp->Parameters.Read.Length); ! 645: ! 646: CurrentAddress = (PUCHAR) MmGetSystemAddressForMdlSafe (Irp->MdlAddress, HighPagePriority); ! 647: ! 648: /* Fixup the parameters to handle this particular volume type */ ! 649: irpSp->Parameters.Read.ByteOffset.QuadPart += SECTOR_SIZE; ! 650: ! 651: memcpy (tmpBuffer, CurrentAddress, irpSp->Parameters.Read.Length); ! 652: ! 653: /* Encrypt the data */ ! 654: Extension->cryptoInfo->encrypt_sector ((ULONG *) tmpBuffer, ! 655: irpSp->Parameters.Read.ByteOffset.QuadPart / SECTOR_SIZE, ! 656: irpSp->Parameters.Read.Length / SECTOR_SIZE, ! 657: &Extension->cryptoInfo->ks[0], ! 658: Extension->cryptoInfo->iv, ! 659: Extension->cryptoInfo->cipher); ! 660: ! 661: if (Extension->bRawDevice == TRUE) ! 662: { ! 663: PMDL tmpBufferMdl = IoAllocateMdl (tmpBuffer, irpSp->Parameters.Read.Length, FALSE, FALSE, NULL); ! 664: PMDL pTrueMdl = Irp->MdlAddress; ! 665: ! 666: if (tmpBufferMdl == NULL) ! 667: { ! 668: TCfree (tmpBuffer); ! 669: return COMPLETE_IRP (DeviceObject, Irp, STATUS_INSUFFICIENT_RESOURCES, 0); ! 670: } ! 671: ! 672: MmBuildMdlForNonPagedPool (tmpBufferMdl); ! 673: ! 674: Irp->MdlAddress = tmpBufferMdl; ! 675: ! 676: #if EXTRA_INFO ! 677: Dump ("NEW MDL ADDRESS IS 0x%08x UserBuffer = 0x%08x\n", Irp->MdlAddress, Irp->UserBuffer); ! 678: #endif ! 679: ! 680: ntStatus = TCSendIRP_RawDevice (DeviceObject, Extension, ! 681: pTrueMdl, IRP_WRITE_OPERATION | IRP_NOCACHE, ! 682: irpSp->MajorFunction, ! 683: Irp); ! 684: } ! 685: else ! 686: { ! 687: ntStatus = TCSendIRP_FileDevice (DeviceObject, Extension, ! 688: tmpBuffer, IRP_WRITE_OPERATION | IRP_NOCACHE, ! 689: irpSp->MajorFunction, ! 690: Irp); ! 691: } ! 692: ! 693: } ! 694: ! 695: // Dump ("TCReadWrite END\n"); ! 696: return ntStatus; ! 697: } ! 698: ! 699: NTSTATUS ! 700: TCSendDeviceIoControlRequest (PDEVICE_OBJECT DeviceObject, ! 701: PEXTENSION Extension, ! 702: ULONG IoControlCode, ! 703: char *OutputBuffer, ! 704: int OutputBufferSize) ! 705: { ! 706: IO_STATUS_BLOCK IoStatusBlock; ! 707: NTSTATUS ntStatus; ! 708: PIRP Irp; ! 709: ! 710: if (DeviceObject); /* Remove compiler warning */ ! 711: ! 712: KeClearEvent (&Extension->keVolumeEvent); ! 713: ! 714: Irp = IoBuildDeviceIoControlRequest (IoControlCode, ! 715: Extension->pFsdDevice, ! 716: NULL, 0, ! 717: OutputBuffer, OutputBufferSize, ! 718: FALSE, ! 719: &Extension->keVolumeEvent, ! 720: &IoStatusBlock); ! 721: ! 722: if (Irp == NULL) ! 723: { ! 724: Dump ("IRP allocation failed\n"); ! 725: return STATUS_INSUFFICIENT_RESOURCES; ! 726: } ! 727: ! 728: ntStatus = IoCallDriver (Extension->pFsdDevice, Irp); ! 729: if (ntStatus == STATUS_PENDING) ! 730: { ! 731: KeWaitForSingleObject (&Extension->keVolumeEvent, UserRequest, UserMode, FALSE, NULL); ! 732: ntStatus = IoStatusBlock.Status; ! 733: } ! 734: ! 735: return ntStatus; ! 736: } ! 737: ! 738: NTSTATUS ! 739: COMPLETE_IRP (PDEVICE_OBJECT DeviceObject, ! 740: PIRP Irp, ! 741: NTSTATUS IrpStatus, ! 742: ULONG IrpInformation) ! 743: { ! 744: Irp->IoStatus.Status = IrpStatus; ! 745: Irp->IoStatus.Information = IrpInformation; ! 746: ! 747: if (DeviceObject); /* Remove compiler warning */ ! 748: ! 749: #ifdef _DEBUG ! 750: if (!NT_SUCCESS (IrpStatus)) ! 751: { ! 752: PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp); ! 753: Dump ("COMPLETE_IRP FAILING IRP %ls Flags 0x%08x vpb 0x%08x NTSTATUS 0x%08x\n", TCTranslateCode (irpSp->MajorFunction), ! 754: (ULONG) DeviceObject->Flags, (ULONG) DeviceObject->Vpb->Flags, IrpStatus); ! 755: } ! 756: //else ! 757: //{ ! 758: // PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp); ! 759: // Dump ("COMPLETE_IRP SUCCESS IRP %ls Flags 0x%08x vpb 0x%08x NTSTATUS 0x%08x\n", TCTranslateCode (irpSp->MajorFunction), ! 760: // (ULONG) DeviceObject->Flags, (ULONG) DeviceObject->Vpb->Flags, IrpStatus); ! 761: //} ! 762: #endif ! 763: IoCompleteRequest (Irp, IO_NO_INCREMENT); ! 764: return IrpStatus; ! 765: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.