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.

1111 lines
26 KiB

  1. /*++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. spfile.c
  5. Abstract:
  6. File operations for text setup.
  7. Author:
  8. Ted Miller (tedm) 2-Aug-1993
  9. Revision History:
  10. Jim Schmidt (jimschm) 10-Apr-1997 Added file attribute routines
  11. --*/
  12. #include "spprecmp.h"
  13. #pragma hdrstop
  14. NTSTATUS
  15. SpGetFileSize(
  16. IN HANDLE hFile,
  17. OUT PULONG Size
  18. )
  19. /*++
  20. Routine Description:
  21. Determine the size of a file. Only the low 32 bits of the size
  22. are considered.
  23. Arguments:
  24. hFile - supplies open handle to file whose size is desired.
  25. Size - receives size of file.
  26. Return Value:
  27. --*/
  28. {
  29. NTSTATUS Status;
  30. IO_STATUS_BLOCK IoStatusBlock;
  31. FILE_STANDARD_INFORMATION StandardInfo;
  32. Status = ZwQueryInformationFile(
  33. hFile,
  34. &IoStatusBlock,
  35. &StandardInfo,
  36. sizeof(StandardInfo),
  37. FileStandardInformation
  38. );
  39. if(!NT_SUCCESS(Status)) {
  40. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: SpGetFileSize: status %lx from ZwQueryInformationFile\n",Status));
  41. return(Status);
  42. }
  43. *Size = StandardInfo.EndOfFile.LowPart;
  44. return(STATUS_SUCCESS);
  45. }
  46. NTSTATUS
  47. SpMapEntireFile(
  48. IN HANDLE hFile,
  49. OUT PHANDLE Section,
  50. OUT PVOID *ViewBase,
  51. IN BOOLEAN WriteAccess
  52. )
  53. /*++
  54. Routine Description:
  55. Map an entire file for read or write access access.
  56. Arguments:
  57. hFile - supplies handle of open file to be mapped.
  58. Section - receives handle for section object created to map file.
  59. ViewBase - receives address of the view of the file
  60. WriteAccess - if TRUE, map file for read and write access.
  61. If FALSE, map file for read access.
  62. Return Value:
  63. --*/
  64. {
  65. NTSTATUS Status;
  66. LARGE_INTEGER SectionOffset;
  67. SIZE_T ViewSize = 0;
  68. SectionOffset.QuadPart = 0;
  69. Status = ZwCreateSection(
  70. Section,
  71. STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ
  72. | (WriteAccess ? SECTION_MAP_WRITE : 0),
  73. NULL,
  74. NULL, // entire file
  75. WriteAccess ? PAGE_READWRITE : PAGE_READONLY,
  76. SEC_COMMIT,
  77. hFile
  78. );
  79. if(!NT_SUCCESS(Status)) {
  80. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: Status %lx from ZwCreateSection\n",Status));
  81. return(Status);
  82. }
  83. *ViewBase = NULL;
  84. Status = ZwMapViewOfSection(
  85. *Section,
  86. NtCurrentProcess(),
  87. ViewBase,
  88. 0,
  89. 0,
  90. &SectionOffset,
  91. &ViewSize,
  92. ViewShare,
  93. 0,
  94. WriteAccess ? PAGE_READWRITE : PAGE_READONLY
  95. );
  96. if(!NT_SUCCESS(Status)) {
  97. NTSTATUS s;
  98. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: SpMapEntireFile: Status %lx from ZwMapViewOfSection\n",Status));
  99. s = ZwClose(*Section);
  100. if(!NT_SUCCESS(s)) {
  101. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: SpMapEntireFile: Warning: status %lx from ZwClose on section handle\n",s));
  102. }
  103. return(Status);
  104. }
  105. return(STATUS_SUCCESS);
  106. }
  107. BOOLEAN
  108. SpUnmapFile(
  109. IN HANDLE Section,
  110. IN PVOID ViewBase
  111. )
  112. {
  113. NTSTATUS Status;
  114. BOOLEAN rc = TRUE;
  115. Status = ZwUnmapViewOfSection(NtCurrentProcess(),ViewBase);
  116. if(!NT_SUCCESS(Status)) {
  117. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: Warning: status %lx from ZwUnmapViewOfSection\n",Status));
  118. rc = FALSE;
  119. }
  120. Status = ZwClose(Section);
  121. if(!NT_SUCCESS(Status)) {
  122. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: Warning: status %lx from ZwClose on section handle\n",Status));
  123. rc = FALSE;
  124. }
  125. return(rc);
  126. }
  127. NTSTATUS
  128. SpOpenAndMapFile(
  129. IN PWSTR FileName, OPTIONAL // only needed if no FileHandle
  130. IN OUT PHANDLE FileHandle,
  131. OUT PHANDLE SectionHandle,
  132. OUT PVOID *ViewBase,
  133. OUT PULONG FileSize,
  134. IN BOOLEAN WriteAccess
  135. )
  136. {
  137. IO_STATUS_BLOCK IoStatusBlock;
  138. UNICODE_STRING UnicodeString;
  139. OBJECT_ATTRIBUTES Obja;
  140. NTSTATUS Status;
  141. BOOLEAN MustClose = FALSE;
  142. //
  143. // If necessary, open the file.
  144. //
  145. if(!(*FileHandle)) {
  146. INIT_OBJA(&Obja,&UnicodeString,FileName);
  147. Status = ZwCreateFile(
  148. FileHandle,
  149. FILE_GENERIC_READ | (WriteAccess ? FILE_GENERIC_WRITE : 0),
  150. &Obja,
  151. &IoStatusBlock,
  152. NULL,
  153. FILE_ATTRIBUTE_NORMAL,
  154. FILE_SHARE_READ,
  155. FILE_OPEN,
  156. 0,
  157. NULL,
  158. 0
  159. );
  160. if(!NT_SUCCESS(Status)) {
  161. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: SpOpenAndMapFile: Unable to open %ws (%lx)\n",FileName,Status));
  162. return(Status);
  163. } else {
  164. MustClose = TRUE;
  165. }
  166. }
  167. //
  168. // Get the size of the file.
  169. //
  170. Status = SpGetFileSize(*FileHandle,FileSize);
  171. if(!NT_SUCCESS(Status)) {
  172. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: SpOpenAndMapFile: unable to determine size of file %ws(%lx)\n",
  173. FileName ? FileName : L"(handle)", Status));
  174. if(MustClose) {
  175. ZwClose(*FileHandle);
  176. }
  177. return(Status);
  178. }
  179. //
  180. // Map the file.
  181. //
  182. Status = SpMapEntireFile(*FileHandle,SectionHandle,ViewBase,WriteAccess);
  183. if(!NT_SUCCESS(Status)) {
  184. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: SpOpenAndMapFile: unable to map %ws (%lx)\n",
  185. FileName ? FileName : L"(handle)", Status));
  186. if(MustClose) {
  187. ZwClose(*FileHandle);
  188. }
  189. return(Status);
  190. }
  191. return(STATUS_SUCCESS);
  192. }
  193. NTSTATUS
  194. SpSetInformationFile(
  195. IN HANDLE Handle,
  196. IN FILE_INFORMATION_CLASS FileInformationClass,
  197. IN ULONG Length,
  198. IN PVOID FileInformation
  199. )
  200. {
  201. NTSTATUS Status;
  202. PFILE_OBJECT FileObject;
  203. OBJECT_HANDLE_INFORMATION HandleInfo;
  204. //
  205. // Reference the object.
  206. //
  207. Status = ObReferenceObjectByHandle(
  208. Handle,
  209. (ACCESS_MASK)DELETE,
  210. *IoFileObjectType,
  211. ExGetPreviousMode(),
  212. &FileObject,
  213. &HandleInfo
  214. );
  215. if(!NT_SUCCESS(Status)) {
  216. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: SpSetInformationFile: ObReferenceObjectByHandle failed (%lx)\n",Status));
  217. return(Status);
  218. }
  219. //
  220. // Set the information.
  221. //
  222. Status = IoSetInformation(FileObject,FileInformationClass,Length,FileInformation);
  223. if(!NT_SUCCESS(Status)) {
  224. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: IoSetInformation returns %lx\n",Status));
  225. }
  226. //
  227. // Clean up and return.
  228. //
  229. ObDereferenceObject(FileObject);
  230. return(Status);
  231. }
  232. NTSTATUS
  233. SpSetAttributes (
  234. IN PWSTR SrcNTPath,
  235. IN ULONG FileAttributes
  236. )
  237. /*++
  238. Routine Description:
  239. Applies FileAttributes to the specified file.
  240. Arguments:
  241. SrcNTPath - The NT path of the file needing attribute modification
  242. FileAttributes - The FILE_ATTRIBUTE_* flags to apply.
  243. Return Value:
  244. NTSTATUS code.
  245. --*/
  246. {
  247. OBJECT_ATTRIBUTES Obja; // for ZwOpenFile
  248. IO_STATUS_BLOCK IoStatusBlock; // for ZwOpenFile
  249. UNICODE_STRING UnicodeString; // DontCare string
  250. NTSTATUS Status; // Return value
  251. HANDLE FileHandle; // Handle of file to be modified
  252. FILE_BASIC_INFORMATION BasicInfo; // For attribs modification
  253. INIT_OBJA(&Obja, &UnicodeString, SrcNTPath);
  254. Status = ZwOpenFile(
  255. &FileHandle,
  256. (ACCESS_MASK)(DELETE|FILE_WRITE_ATTRIBUTES),
  257. &Obja,
  258. &IoStatusBlock,
  259. FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE,
  260. FILE_NON_DIRECTORY_FILE|FILE_OPEN_FOR_BACKUP_INTENT
  261. );
  262. if (!NT_SUCCESS (Status)) {
  263. Status = ZwOpenFile(
  264. &FileHandle,
  265. (ACCESS_MASK)(DELETE|FILE_WRITE_ATTRIBUTES),
  266. &Obja,
  267. &IoStatusBlock,
  268. FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE,
  269. FILE_DIRECTORY_FILE|FILE_OPEN_FOR_BACKUP_INTENT
  270. );
  271. }
  272. if(NT_SUCCESS(Status)) {
  273. RtlZeroMemory( &BasicInfo, sizeof( FILE_BASIC_INFORMATION ) );
  274. BasicInfo.FileAttributes = FileAttributes;
  275. Status = SpSetInformationFile(
  276. FileHandle,
  277. FileBasicInformation,
  278. sizeof(BasicInfo),
  279. &BasicInfo
  280. );
  281. ZwClose(FileHandle);
  282. }
  283. if (!NT_SUCCESS(Status)) {
  284. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: SpSetAttributes failed for %ws, Status=%lx\n", SrcNTPath, Status));
  285. }
  286. return Status;
  287. }
  288. NTSTATUS
  289. SpGetAttributes (
  290. IN PWSTR SrcNTPath,
  291. OUT PULONG FileAttributesPtr
  292. )
  293. /*++
  294. Routine Description:
  295. Obtains FileAttributes for the specified file.
  296. Arguments:
  297. SrcNTPath - The NT path of the file to obtain attributes
  298. FileAttributesPtr - A poitner to a DWORD that recieves FILE_ATTRIBUTE_*
  299. flags
  300. Return Value:
  301. NTSTATUS code. FileAttributePtr is modified only with status is NO_ERROR.
  302. --*/
  303. {
  304. OBJECT_ATTRIBUTES Obja; // for ZwOpenFile
  305. IO_STATUS_BLOCK IoStatusBlock; // for ZwOpenFile
  306. UNICODE_STRING UnicodeString; // DontCare string
  307. NTSTATUS Status; // Return value
  308. HANDLE FileHandle; // Handle of file to be queried
  309. FILE_BASIC_INFORMATION BasicInfo; // For attribs retrieval
  310. INIT_OBJA(&Obja, &UnicodeString, SrcNTPath);
  311. Status = ZwOpenFile(
  312. &FileHandle,
  313. (ACCESS_MASK)(FILE_TRAVERSE | FILE_READ_ATTRIBUTES),
  314. &Obja,
  315. &IoStatusBlock,
  316. FILE_SHARE_READ,
  317. FILE_NON_DIRECTORY_FILE
  318. );
  319. if (!NT_SUCCESS (Status)) {
  320. Status = ZwOpenFile(
  321. &FileHandle,
  322. (ACCESS_MASK)(FILE_TRAVERSE | FILE_READ_ATTRIBUTES),
  323. &Obja,
  324. &IoStatusBlock,
  325. FILE_SHARE_READ,
  326. FILE_DIRECTORY_FILE
  327. );
  328. }
  329. if(NT_SUCCESS(Status)) {
  330. Status = ZwQueryInformationFile(
  331. FileHandle,
  332. &IoStatusBlock,
  333. &BasicInfo,
  334. sizeof(BasicInfo),
  335. FileBasicInformation
  336. );
  337. ZwClose(FileHandle);
  338. if (NT_SUCCESS(Status)) {
  339. *FileAttributesPtr = BasicInfo.FileAttributes;
  340. }
  341. }
  342. if (!NT_SUCCESS(Status)) {
  343. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: SpGetAttributes failed for %ws, Status=%lx\n", SrcNTPath, Status));
  344. }
  345. return Status;
  346. }
  347. NTSTATUS
  348. SpDeleteFileEx(
  349. IN PCWSTR Name1,
  350. IN PCWSTR Name2, OPTIONAL
  351. IN PCWSTR Name3, OPTIONAL
  352. IN ULONG ShareFlags, OPTIONAL
  353. IN ULONG OpenFlags OPTIONAL
  354. )
  355. {
  356. PWSTR p;
  357. NTSTATUS Status;
  358. IO_STATUS_BLOCK IoStatusBlock;
  359. UNICODE_STRING UnicodeString;
  360. OBJECT_ATTRIBUTES Obja;
  361. HANDLE Handle;
  362. FILE_DISPOSITION_INFORMATION Disposition;
  363. FILE_BASIC_INFORMATION BasicInfo;
  364. //
  365. // Point to temporary buffer for pathname.
  366. //
  367. p = TemporaryBuffer;
  368. //
  369. // Build up the full name of the file to delete.
  370. //
  371. wcscpy(p,Name1);
  372. if(Name2) {
  373. SpConcatenatePaths(p,Name2);
  374. }
  375. if(Name3) {
  376. SpConcatenatePaths(p,Name3);
  377. }
  378. //
  379. // Prepare to open the file.
  380. //
  381. INIT_OBJA(&Obja,&UnicodeString,p);
  382. //
  383. // Attempt to open the file.
  384. //
  385. Status = ZwOpenFile(
  386. &Handle,
  387. (ACCESS_MASK)(DELETE | FILE_WRITE_ATTRIBUTES),
  388. &Obja,
  389. &IoStatusBlock,
  390. ShareFlags,
  391. OpenFlags
  392. );
  393. if(!NT_SUCCESS(Status)) {
  394. if (Status != STATUS_OBJECT_NAME_NOT_FOUND) {
  395. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: Unable to open %ws for delete (%lx)\n",p,Status));
  396. }
  397. return(Status);
  398. }
  399. //
  400. // Change the file attribute to normal
  401. //
  402. RtlZeroMemory( &BasicInfo, sizeof( FILE_BASIC_INFORMATION ) );
  403. BasicInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
  404. Status = SpSetInformationFile(
  405. Handle,
  406. FileBasicInformation,
  407. sizeof(BasicInfo),
  408. &BasicInfo
  409. );
  410. if(!NT_SUCCESS(Status)) {
  411. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: Unable to change attribute of %ws, Status = (%lx)\n",p,Status));
  412. return(Status);
  413. }
  414. //
  415. // Set up for delete and call worker to do it.
  416. //
  417. #undef DeleteFile
  418. Disposition.DeleteFile = TRUE;
  419. Status = SpSetInformationFile(
  420. Handle,
  421. FileDispositionInformation,
  422. sizeof(Disposition),
  423. &Disposition
  424. );
  425. //
  426. // Clean up and return.
  427. //
  428. ZwClose(Handle);
  429. return(Status);
  430. }
  431. NTSTATUS
  432. SpDeleteFile(
  433. IN PCWSTR Name1,
  434. IN PCWSTR Name2, OPTIONAL
  435. IN PCWSTR Name3 OPTIONAL
  436. )
  437. {
  438. return( SpDeleteFileEx( Name1,
  439. Name2,
  440. Name3,
  441. FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
  442. FILE_NON_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT ) );
  443. }
  444. BOOLEAN
  445. SpFileExists(
  446. IN PCWSTR PathName,
  447. IN BOOLEAN Directory
  448. )
  449. /*++
  450. Routine Description:
  451. Determine if a file or directory exists
  452. Arguments:
  453. PathName - PathName of file or directory to check
  454. Directory - Whether PathName refers to a directory or a file
  455. Return Value:
  456. NT_SUCCESS(NTSTATUS) if file exists.
  457. --*/
  458. {
  459. UNICODE_STRING UnicodeString;
  460. OBJECT_ATTRIBUTES Obja;
  461. HANDLE Handle;
  462. IO_STATUS_BLOCK IoStatusBlock;
  463. NTSTATUS Status;
  464. INIT_OBJA(&Obja,&UnicodeString,PathName);
  465. Status = ZwCreateFile(
  466. &Handle,
  467. FILE_READ_ATTRIBUTES,
  468. &Obja,
  469. &IoStatusBlock,
  470. NULL,
  471. 0,
  472. FILE_SHARE_READ | FILE_SHARE_WRITE,
  473. FILE_OPEN,
  474. Directory ? FILE_DIRECTORY_FILE : FILE_NON_DIRECTORY_FILE,
  475. NULL,
  476. 0
  477. );
  478. if(NT_SUCCESS(Status)) {
  479. ZwClose(Handle);
  480. return(TRUE);
  481. } else {
  482. return(FALSE);
  483. }
  484. }
  485. NTSTATUS
  486. SpRenameFile(
  487. IN PWSTR OldName,
  488. IN PWSTR NewName,
  489. IN BOOLEAN AllowDirectoryRename
  490. )
  491. /*++
  492. Routine Description:
  493. Rename a file or directory
  494. Arguments:
  495. OldName - Old name of file
  496. NewName - New name of file
  497. AllowDirectoryRename - if TRUE, then this routine will rename a directory,
  498. otherwise directory renames are not allowed.
  499. Return Value:
  500. NT_SUCCESS(NTSTATUS) if file successfully renamed
  501. --*/
  502. {
  503. NTSTATUS Status;
  504. IO_STATUS_BLOCK IoStatusBlock;
  505. UNICODE_STRING UnicodeString;
  506. OBJECT_ATTRIBUTES Obja;
  507. HANDLE Handle;
  508. BYTE Buffer[ACTUAL_MAX_PATH * sizeof(WCHAR) + sizeof(FILE_RENAME_INFORMATION)];
  509. PFILE_RENAME_INFORMATION pNameInfo;
  510. ULONG NameInfoLength, FileNameLength;
  511. //
  512. // Prepare to open the file.
  513. //
  514. INIT_OBJA(&Obja,&UnicodeString,OldName);
  515. //
  516. // Attempt to open the file as a file.
  517. //
  518. Status = ZwOpenFile(
  519. &Handle,
  520. (ACCESS_MASK)(DELETE | SYNCHRONIZE),
  521. &Obja,
  522. &IoStatusBlock,
  523. FILE_SHARE_READ | FILE_SHARE_WRITE,
  524. FILE_NON_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT
  525. );
  526. if(!NT_SUCCESS(Status) && AllowDirectoryRename) {
  527. //
  528. // Attempt to open the file as a directory.
  529. //
  530. Status = ZwOpenFile(
  531. &Handle,
  532. (ACCESS_MASK)(DELETE | SYNCHRONIZE),
  533. &Obja,
  534. &IoStatusBlock,
  535. FILE_SHARE_READ | FILE_SHARE_WRITE,
  536. FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT
  537. );
  538. }
  539. if(!NT_SUCCESS(Status)) {
  540. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: Unable to open %ws for rename (%lx)\n",OldName,Status));
  541. return(Status);
  542. }
  543. //
  544. // Change the file name
  545. //
  546. NameInfoLength = sizeof(Buffer);
  547. FileNameLength = (wcslen(NewName))*sizeof(WCHAR);
  548. memset(Buffer, 0, sizeof(Buffer));
  549. pNameInfo = (PFILE_RENAME_INFORMATION)Buffer;
  550. pNameInfo->ReplaceIfExists = FALSE;
  551. pNameInfo->RootDirectory = NULL;
  552. pNameInfo->FileNameLength = FileNameLength;
  553. wcscpy( pNameInfo->FileName, NewName );
  554. Status = SpSetInformationFile(
  555. Handle,
  556. FileRenameInformation,
  557. NameInfoLength,
  558. (PVOID)pNameInfo
  559. );
  560. if(!NT_SUCCESS(Status)) {
  561. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: Unable to change name of %ls to %ls. Status = (%lx)\n",OldName,NewName,Status));
  562. }
  563. //
  564. // Clean up and return.
  565. //
  566. ZwClose(Handle);
  567. return(Status);
  568. }
  569. USHORT
  570. SpChkSum(
  571. ULONG PartialSum,
  572. PUSHORT Source,
  573. ULONG Length
  574. )
  575. /*++
  576. Routine Description:
  577. Compute a partial checksum on a portion of an imagefile.
  578. Arguments:
  579. PartialSum - Supplies the initial checksum value.
  580. Sources - Supplies a pointer to the array of words for which the
  581. checksum is computed.
  582. Length - Supplies the length of the array in words.
  583. Return Value:
  584. The computed checksum value is returned as the function value.
  585. --*/
  586. {
  587. //
  588. // Compute the word wise checksum allowing carries to occur into the
  589. // high order half of the checksum longword.
  590. //
  591. while (Length--) {
  592. PartialSum += *Source++;
  593. PartialSum = (PartialSum >> 16) + (PartialSum & 0xffff);
  594. }
  595. //
  596. // Fold final carry into a single word result and return the resultant
  597. // value.
  598. //
  599. return (USHORT)(((PartialSum >> 16) + PartialSum) & 0xffff);
  600. }
  601. PIMAGE_NT_HEADERS
  602. SpChecksumMappedFile(
  603. IN PVOID BaseAddress,
  604. IN ULONG FileSize,
  605. OUT PULONG HeaderSum,
  606. OUT PULONG Checksum
  607. )
  608. {
  609. PIMAGE_NT_HEADERS NtHeaders;
  610. USHORT PartialSum;
  611. PUSHORT AdjustSum;
  612. try {
  613. //
  614. // Compute the checksum of this file and zero the header sum.
  615. //
  616. PartialSum = SpChkSum(0,BaseAddress,(FileSize+1) >> 1);
  617. *HeaderSum = 0;
  618. //
  619. // See whether this is an image.
  620. //
  621. if(NtHeaders = RtlImageNtHeader(BaseAddress)) {
  622. //
  623. // The file is an image file -- subtract the two checksum words
  624. // in the optional header from the computed checksum before adding
  625. // the file length, and set the value of the header checksum.
  626. //
  627. *HeaderSum = NtHeaders->OptionalHeader.CheckSum;
  628. AdjustSum = (PUSHORT)(&NtHeaders->OptionalHeader.CheckSum);
  629. PartialSum -= (PartialSum < AdjustSum[0]);
  630. PartialSum -= AdjustSum[0];
  631. PartialSum -= (PartialSum < AdjustSum[1]);
  632. PartialSum -= AdjustSum[1];
  633. }
  634. //
  635. // Compute the checksum.
  636. //
  637. *Checksum = (ULONG)PartialSum + FileSize;
  638. } except(EXCEPTION_EXECUTE_HANDLER) {
  639. NtHeaders = NULL;
  640. }
  641. return(NtHeaders);
  642. }
  643. NTSTATUS
  644. SpOpenNameMayBeCompressed(
  645. IN PWSTR FullPath,
  646. IN ULONG OpenAccess,
  647. IN ULONG FileAttributes,
  648. IN ULONG ShareFlags,
  649. IN ULONG Disposition,
  650. IN ULONG OpenFlags,
  651. OUT PHANDLE Handle,
  652. OUT PBOOLEAN OpenedCompressedName OPTIONAL
  653. )
  654. {
  655. NTSTATUS Status;
  656. PWSTR compname;
  657. PWSTR names[2];
  658. int compord,uncompord;
  659. static BOOLEAN PreviousWasCompressed = FALSE;
  660. BOOLEAN IsComp;
  661. int i;
  662. UNICODE_STRING UnicodeString;
  663. OBJECT_ATTRIBUTES Obja;
  664. IO_STATUS_BLOCK IoStatusBlock;
  665. //
  666. // Generate compressed name.
  667. //
  668. compname = SpGenerateCompressedName(FullPath);
  669. //
  670. // Figure out which name to try to use first. If the last successful
  671. // call to this routine opened the file using the compressed name, then
  672. // try to open the compressed name first. Otherwise try to open the
  673. // uncompressed name first.
  674. //
  675. if(PreviousWasCompressed) {
  676. compord = 0;
  677. uncompord = 1;
  678. } else {
  679. compord = 1;
  680. uncompord = 0;
  681. }
  682. names[uncompord] = FullPath;
  683. names[compord] = compname;
  684. for(i=0; i<2; i++) {
  685. INIT_OBJA(&Obja,&UnicodeString,names[i]);
  686. Status = ZwCreateFile(
  687. Handle,
  688. OpenAccess,
  689. &Obja,
  690. &IoStatusBlock,
  691. NULL,
  692. FileAttributes,
  693. ShareFlags,
  694. Disposition,
  695. OpenFlags,
  696. NULL,
  697. 0
  698. );
  699. if(NT_SUCCESS(Status)) {
  700. IsComp = (BOOLEAN)(i == compord);
  701. PreviousWasCompressed = IsComp;
  702. if(OpenedCompressedName) {
  703. *OpenedCompressedName = IsComp;
  704. }
  705. break;
  706. }
  707. }
  708. SpMemFree(compname);
  709. return(Status);
  710. }
  711. NTSTATUS
  712. SpGetFileSizeByName(
  713. IN PWSTR DevicePath OPTIONAL,
  714. IN PWSTR Directory OPTIONAL,
  715. IN PWSTR FileName,
  716. OUT PULONG Size
  717. )
  718. /*++
  719. Routine Description:
  720. Determine the size of a file. Only the low 32 bits of the size
  721. are considered.
  722. Arguments:
  723. DevicePath - Path to the device that contains the file.
  724. Directory - Name of the directory that contains the file.
  725. FileName - Name of the file.
  726. Size - receives size of file.
  727. Return Value:
  728. NTSTATUs -
  729. --*/
  730. {
  731. PWSTR CompleteFileName;
  732. HANDLE FileHandle;
  733. OBJECT_ATTRIBUTES ObjectAttributes;
  734. IO_STATUS_BLOCK IoStatusBlock;
  735. NTSTATUS Status;
  736. UNICODE_STRING UnicodeFileName;
  737. ULONG FileNameLength;
  738. FileNameLength = wcslen( FileName ) + 1;
  739. if( DevicePath != NULL ) {
  740. FileNameLength += wcslen( DevicePath ) + 1;
  741. }
  742. if( Directory != NULL ) {
  743. FileNameLength += wcslen( Directory ) + 1;
  744. }
  745. CompleteFileName = SpMemAlloc( FileNameLength*sizeof( WCHAR ) );
  746. if( CompleteFileName == NULL ) {
  747. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: Unable to allocate memory on SpGetFileSizeByName \n" ));
  748. return( STATUS_NO_MEMORY );
  749. }
  750. *CompleteFileName = (WCHAR)'\0';
  751. if( DevicePath != NULL ) {
  752. SpConcatenatePaths( CompleteFileName, DevicePath );
  753. }
  754. if( Directory != NULL ) {
  755. SpConcatenatePaths( CompleteFileName, Directory );
  756. }
  757. SpConcatenatePaths( CompleteFileName, FileName );
  758. RtlInitUnicodeString( &UnicodeFileName,
  759. CompleteFileName );
  760. InitializeObjectAttributes( &ObjectAttributes,
  761. &UnicodeFileName,
  762. OBJ_CASE_INSENSITIVE,
  763. NULL,
  764. NULL );
  765. Status = ZwOpenFile( &FileHandle,
  766. STANDARD_RIGHTS_READ | FILE_READ_ATTRIBUTES | SYNCHRONIZE,
  767. &ObjectAttributes,
  768. &IoStatusBlock,
  769. 0,
  770. FILE_SYNCHRONOUS_IO_NONALERT );
  771. if( !NT_SUCCESS( Status ) ) {
  772. SpMemFree( CompleteFileName );
  773. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: ZwOpenFile() failed. File = %ls, Status = %x\n",FileName, Status ) );
  774. return( Status );
  775. }
  776. Status = SpGetFileSize( FileHandle, Size );
  777. ZwClose( FileHandle );
  778. SpMemFree( CompleteFileName );
  779. if( !NT_SUCCESS( Status ) ) {
  780. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: SpGetFileSize() failed. File = %ls, Status = %x\n",FileName, Status ) );
  781. return( Status );
  782. }
  783. return( Status );
  784. }
  785. VOID
  786. SpVerifyNoCompression(
  787. IN PWSTR FileName
  788. )
  789. /*++
  790. Routine Description:
  791. Determine if the file is compressed (via NTFS compression), and if so,
  792. uncompress it.
  793. Arguments:
  794. FileName - Name of the file that must be uncompressed.
  795. Return Value:
  796. none
  797. --*/
  798. {
  799. HANDLE FileHandle;
  800. IO_STATUS_BLOCK IoStatusBlock;
  801. UNICODE_STRING UnicodeString;
  802. OBJECT_ATTRIBUTES Obja;
  803. NTSTATUS Status;
  804. FILE_BASIC_INFORMATION BasicFileInfo;
  805. INIT_OBJA(&Obja, &UnicodeString, FileName);
  806. Status = ZwCreateFile(
  807. &FileHandle,
  808. 0,
  809. &Obja,
  810. &IoStatusBlock,
  811. NULL,
  812. FILE_ATTRIBUTE_NORMAL,
  813. FILE_SHARE_READ | FILE_SHARE_WRITE,
  814. FILE_OPEN,
  815. 0,
  816. NULL,
  817. 0
  818. );
  819. if(!NT_SUCCESS(Status)) {
  820. //
  821. // Ignore error.
  822. //
  823. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: SpVerifyNoCompression unable to open file %ws (%lx)\n", FileName, Status));
  824. return;
  825. }
  826. Status = ZwQueryInformationFile(
  827. FileHandle,
  828. &IoStatusBlock,
  829. &BasicFileInfo,
  830. sizeof(BasicFileInfo),
  831. FileBasicInformation
  832. );
  833. if(!NT_SUCCESS(Status)) {
  834. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: SpVerifyNoCompression unable to get basic file info for %ws (%lx)\n", FileName, Status));
  835. goto ComprVerifyDone;
  836. }
  837. if(BasicFileInfo.FileAttributes & FILE_ATTRIBUTE_COMPRESSED) {
  838. USHORT CompressionState = 0;
  839. Status = ZwFsControlFile(
  840. FileHandle,
  841. NULL,
  842. NULL,
  843. NULL,
  844. &IoStatusBlock,
  845. FSCTL_SET_COMPRESSION,
  846. &CompressionState,
  847. sizeof(CompressionState),
  848. NULL,
  849. 0
  850. );
  851. if(!NT_SUCCESS(Status)) {
  852. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: SpVerifyNoCompression unable to uncompress %ws (%lx)\n", FileName, Status));
  853. }
  854. }
  855. ComprVerifyDone:
  856. ZwClose(FileHandle);
  857. return;
  858. }