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.

1283 lines
32 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. UNICODE_STRING UnicodeString;
  239. NTSTATUS NtStatus;
  240. NtStatus = RtlInitUnicodeStringEx(&UnicodeString, SrcNTPath);
  241. if (!NT_SUCCESS(NtStatus)) {
  242. goto Exit;
  243. }
  244. NtStatus = SpSetAttributes_Ustr(&UnicodeString, FileAttributes);
  245. Exit:
  246. return NtStatus;
  247. }
  248. NTSTATUS
  249. SpSetAttributes_Ustr (
  250. IN PCUNICODE_STRING SrcNTPath,
  251. IN ULONG FileAttributes
  252. )
  253. /*++
  254. Routine Description:
  255. Applies FileAttributes to the specified file.
  256. Arguments:
  257. SrcNTPath - The NT path of the file needing attribute modification
  258. FileAttributes - The FILE_ATTRIBUTE_* flags to apply.
  259. Return Value:
  260. NTSTATUS code.
  261. --*/
  262. {
  263. OBJECT_ATTRIBUTES Obja; // for ZwOpenFile
  264. IO_STATUS_BLOCK IoStatusBlock; // for ZwOpenFile
  265. NTSTATUS Status; // Return value
  266. HANDLE FileHandle; // Handle of file to be modified
  267. FILE_BASIC_INFORMATION BasicInfo; // For attribs modification
  268. InitializeObjectAttributes(&Obja, (PUNICODE_STRING)SrcNTPath, OBJ_CASE_INSENSITIVE, NULL, NULL);
  269. Status = ZwOpenFile(
  270. &FileHandle,
  271. (ACCESS_MASK)(DELETE|FILE_WRITE_ATTRIBUTES),
  272. &Obja,
  273. &IoStatusBlock,
  274. FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE,
  275. FILE_NON_DIRECTORY_FILE|FILE_OPEN_FOR_BACKUP_INTENT
  276. );
  277. if (!NT_SUCCESS (Status)) {
  278. Status = ZwOpenFile(
  279. &FileHandle,
  280. (ACCESS_MASK)(DELETE|FILE_WRITE_ATTRIBUTES),
  281. &Obja,
  282. &IoStatusBlock,
  283. FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE,
  284. FILE_DIRECTORY_FILE|FILE_OPEN_FOR_BACKUP_INTENT
  285. );
  286. }
  287. if(NT_SUCCESS(Status)) {
  288. RtlZeroMemory( &BasicInfo, sizeof( FILE_BASIC_INFORMATION ) );
  289. BasicInfo.FileAttributes = FileAttributes;
  290. Status = SpSetInformationFile(
  291. FileHandle,
  292. FileBasicInformation,
  293. sizeof(BasicInfo),
  294. &BasicInfo
  295. );
  296. ZwClose(FileHandle);
  297. }
  298. if (!NT_SUCCESS(Status)) {
  299. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: SpSetAttributes failed for %ws, Status=%lx\n", SrcNTPath, Status));
  300. }
  301. return Status;
  302. }
  303. NTSTATUS
  304. SpGetAttributes (
  305. IN PWSTR SrcNTPath,
  306. OUT PULONG FileAttributesPtr
  307. )
  308. {
  309. UNICODE_STRING UnicodeString;
  310. NTSTATUS NtStatus;
  311. NtStatus = RtlInitUnicodeStringEx(&UnicodeString, SrcNTPath);
  312. if (!NT_SUCCESS(NtStatus)) {
  313. goto Exit;
  314. }
  315. NtStatus = SpGetAttributes_Ustr(&UnicodeString, FileAttributesPtr);
  316. Exit:
  317. return NtStatus;
  318. }
  319. NTSTATUS
  320. SpGetAttributes_Ustr (
  321. IN PCUNICODE_STRING SrcNTPath,
  322. OUT PULONG FileAttributesPtr
  323. )
  324. /*++
  325. Routine Description:
  326. Obtains FileAttributes for the specified file.
  327. Arguments:
  328. SrcNTPath - The NT path of the file to obtain attributes
  329. FileAttributesPtr - A poitner to a DWORD that recieves FILE_ATTRIBUTE_*
  330. flags
  331. Return Value:
  332. NTSTATUS code. FileAttributePtr is modified only with status is NO_ERROR.
  333. --*/
  334. {
  335. OBJECT_ATTRIBUTES Obja; // for ZwOpenFile
  336. IO_STATUS_BLOCK IoStatusBlock; // for ZwOpenFile
  337. NTSTATUS Status; // Return value
  338. HANDLE FileHandle; // Handle of file to be queried
  339. FILE_BASIC_INFORMATION BasicInfo; // For attribs retrieval
  340. InitializeObjectAttributes(&Obja, (PUNICODE_STRING)SrcNTPath, OBJ_CASE_INSENSITIVE, NULL, NULL);
  341. Status = ZwOpenFile(
  342. &FileHandle,
  343. (ACCESS_MASK)(FILE_TRAVERSE | FILE_READ_ATTRIBUTES),
  344. &Obja,
  345. &IoStatusBlock,
  346. FILE_SHARE_READ,
  347. FILE_NON_DIRECTORY_FILE
  348. );
  349. if (!NT_SUCCESS (Status)) {
  350. Status = ZwOpenFile(
  351. &FileHandle,
  352. (ACCESS_MASK)(FILE_TRAVERSE | FILE_READ_ATTRIBUTES),
  353. &Obja,
  354. &IoStatusBlock,
  355. FILE_SHARE_READ,
  356. FILE_DIRECTORY_FILE
  357. );
  358. }
  359. if(NT_SUCCESS(Status)) {
  360. Status = ZwQueryInformationFile(
  361. FileHandle,
  362. &IoStatusBlock,
  363. &BasicInfo,
  364. sizeof(BasicInfo),
  365. FileBasicInformation
  366. );
  367. ZwClose(FileHandle);
  368. if (NT_SUCCESS(Status)) {
  369. *FileAttributesPtr = BasicInfo.FileAttributes;
  370. }
  371. }
  372. if (!NT_SUCCESS(Status)) {
  373. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: SpGetAttributes failed for %wZ, Status=%lx\n", SrcNTPath, Status));
  374. }
  375. return Status;
  376. }
  377. NTSTATUS
  378. SpDeleteFileOrEmptyDirectory(
  379. IN ULONG Flags,
  380. IN PCUNICODE_STRING Path
  381. )
  382. /*
  383. This is based on SpMigDeleteFile.
  384. It does not perform optimally, in terms of limiting the number of NtOpenFile calls.
  385. */
  386. {
  387. UNICODE_STRING ustr;
  388. NTSTATUS Status = STATUS_INTERNAL_ERROR;
  389. const ULONG ValidFlags = SP_DELETE_FILE_OR_EMPTY_DIRECTORY_FLAG_DO_NOT_CLEAR_ATTRIBUTES;
  390. if ((Flags & ~ValidFlags) != 0) {
  391. Status = STATUS_INVALID_PARAMETER;
  392. goto Exit;
  393. }
  394. if ((Flags & SP_DELETE_FILE_OR_EMPTY_DIRECTORY_FLAG_DO_NOT_CLEAR_ATTRIBUTES) == 0) {
  395. SpSetAttributes_Ustr (Path, FILE_ATTRIBUTE_NORMAL);
  396. }
  397. if (SpFileExists_Ustr (Path, FALSE)) {
  398. //
  399. // Delete the file
  400. //
  401. Status = SpDeleteFile_Ustr (Path, NULL, NULL);
  402. } else if (SpFileExists_Ustr (Path, TRUE)) {
  403. //
  404. // Delete the empty directory
  405. //
  406. Status = SpDeleteFileEx_Ustr (
  407. Path,
  408. NULL,
  409. NULL,
  410. FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
  411. FILE_OPEN_FOR_BACKUP_INTENT
  412. );
  413. } else {
  414. Status = STATUS_SUCCESS;
  415. }
  416. Exit:
  417. return Status;
  418. }
  419. NTSTATUS
  420. SpDeleteFileEx(
  421. IN PCWSTR Name1,
  422. IN PCWSTR Name2, OPTIONAL
  423. IN PCWSTR Name3, OPTIONAL
  424. IN ULONG ShareFlags, OPTIONAL
  425. IN ULONG OpenFlags OPTIONAL
  426. )
  427. {
  428. UNICODE_STRING UnicodeString1;
  429. UNICODE_STRING UnicodeString2;
  430. UNICODE_STRING UnicodeString3;
  431. NTSTATUS Status = STATUS_INTERNAL_ERROR;
  432. Status = RtlInitUnicodeStringEx(&UnicodeString1, Name1);
  433. if (!NT_SUCCESS(Status)) {
  434. goto Exit;
  435. }
  436. Status = RtlInitUnicodeStringEx(&UnicodeString2, Name2);
  437. if (!NT_SUCCESS(Status)) {
  438. goto Exit;
  439. }
  440. Status = RtlInitUnicodeStringEx(&UnicodeString3, Name3);
  441. if (!NT_SUCCESS(Status)) {
  442. goto Exit;
  443. }
  444. Status = SpDeleteFileEx_Ustr(&UnicodeString1, &UnicodeString2, &UnicodeString3, ShareFlags, OpenFlags);
  445. Exit:
  446. return Status;
  447. }
  448. NTSTATUS
  449. SpDeleteFileEx_Ustr(
  450. IN PCUNICODE_STRING Name1,
  451. IN PCUNICODE_STRING Name2, OPTIONAL
  452. IN PCUNICODE_STRING Name3, OPTIONAL
  453. IN ULONG ShareFlags, OPTIONAL
  454. IN ULONG OpenFlags OPTIONAL
  455. )
  456. {
  457. UNICODE_STRING p;
  458. NTSTATUS Status;
  459. IO_STATUS_BLOCK IoStatusBlock;
  460. UNICODE_STRING UnicodeString;
  461. OBJECT_ATTRIBUTES Obja;
  462. HANDLE Handle;
  463. FILE_DISPOSITION_INFORMATION Disposition;
  464. FILE_BASIC_INFORMATION BasicInfo;
  465. //
  466. // Point to temporary buffer for pathname.
  467. //
  468. p = TemporaryBufferUnicodeString;
  469. //
  470. // Build up the full name of the file to delete.
  471. //
  472. RtlMoveMemory(p.Buffer, Name1->Buffer, Name1->Length);
  473. p.Length = Name1->Length;
  474. if(Name2 != NULL && Name2->Length != 0) {
  475. SpConcatenatePaths_Ustr(&p,Name2);
  476. }
  477. if(Name3 != NULL && Name3->Length != 0) {
  478. SpConcatenatePaths_Ustr(&p,Name3);
  479. }
  480. //
  481. // Prepare to open the file.
  482. //
  483. InitializeObjectAttributes(&Obja, &p, OBJ_CASE_INSENSITIVE, NULL, NULL);
  484. //
  485. // Attempt to open the file.
  486. //
  487. Status = ZwOpenFile(
  488. &Handle,
  489. (ACCESS_MASK)(DELETE | FILE_WRITE_ATTRIBUTES),
  490. &Obja,
  491. &IoStatusBlock,
  492. ShareFlags,
  493. OpenFlags
  494. );
  495. if(!NT_SUCCESS(Status)) {
  496. if (Status != STATUS_OBJECT_NAME_NOT_FOUND) {
  497. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: Unable to open %wZ for delete (%lx)\n",p,Status));
  498. }
  499. return(Status);
  500. }
  501. //
  502. // Change the file attribute to normal
  503. //
  504. RtlZeroMemory( &BasicInfo, sizeof( FILE_BASIC_INFORMATION ) );
  505. BasicInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL;
  506. Status = SpSetInformationFile(
  507. Handle,
  508. FileBasicInformation,
  509. sizeof(BasicInfo),
  510. &BasicInfo
  511. );
  512. if(!NT_SUCCESS(Status)) {
  513. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: Unable to change attribute of %wZ, Status = (%lx)\n",p,Status));
  514. return(Status);
  515. }
  516. //
  517. // Set up for delete and call worker to do it.
  518. //
  519. #undef DeleteFile
  520. Disposition.DeleteFile = TRUE;
  521. Status = SpSetInformationFile(
  522. Handle,
  523. FileDispositionInformation,
  524. sizeof(Disposition),
  525. &Disposition
  526. );
  527. //
  528. // Clean up and return.
  529. //
  530. ZwClose(Handle);
  531. return(Status);
  532. }
  533. NTSTATUS
  534. SpDeleteFile(
  535. IN PCWSTR Name1,
  536. IN PCWSTR Name2, OPTIONAL
  537. IN PCWSTR Name3 OPTIONAL
  538. )
  539. {
  540. UNICODE_STRING UnicodeString1;
  541. UNICODE_STRING UnicodeString2;
  542. UNICODE_STRING UnicodeString3;
  543. NTSTATUS Status = STATUS_INTERNAL_ERROR;
  544. Status = RtlInitUnicodeStringEx(&UnicodeString1, Name1);
  545. if (!NT_SUCCESS(Status)) {
  546. goto Exit;
  547. }
  548. Status = RtlInitUnicodeStringEx(&UnicodeString2, Name2);
  549. if (!NT_SUCCESS(Status)) {
  550. goto Exit;
  551. }
  552. Status = RtlInitUnicodeStringEx(&UnicodeString3, Name3);
  553. if (!NT_SUCCESS(Status)) {
  554. goto Exit;
  555. }
  556. Status = SpDeleteFile_Ustr(&UnicodeString1, &UnicodeString2, &UnicodeString3);
  557. Exit:
  558. return Status;
  559. }
  560. NTSTATUS
  561. SpDeleteFile_Ustr(
  562. IN PCUNICODE_STRING Name1,
  563. IN PCUNICODE_STRING Name2, OPTIONAL
  564. IN PCUNICODE_STRING Name3 OPTIONAL
  565. )
  566. {
  567. return( SpDeleteFileEx_Ustr( Name1,
  568. Name2,
  569. Name3,
  570. FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
  571. FILE_NON_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT ) );
  572. }
  573. BOOLEAN
  574. SpFileExists(
  575. IN PCWSTR PathName,
  576. IN BOOLEAN Directory
  577. )
  578. {
  579. BOOLEAN Result;
  580. UNICODE_STRING UnicodeString;
  581. RtlInitUnicodeString(&UnicodeString, PathName);
  582. Result = SpFileExists_Ustr(&UnicodeString, Directory);
  583. return Result;
  584. }
  585. BOOLEAN
  586. SpFileExists_Ustr(
  587. IN PCUNICODE_STRING PathName,
  588. IN BOOLEAN Directory
  589. )
  590. /*++
  591. Routine Description:
  592. Determine if a file or directory exists
  593. Arguments:
  594. PathName - PathName of file or directory to check
  595. Directory - Whether PathName refers to a directory or a file
  596. Return Value:
  597. NT_SUCCESS(NTSTATUS) if file exists.
  598. --*/
  599. {
  600. OBJECT_ATTRIBUTES Obja;
  601. HANDLE Handle;
  602. IO_STATUS_BLOCK IoStatusBlock;
  603. NTSTATUS Status;
  604. InitializeObjectAttributes(&Obja, (PUNICODE_STRING)PathName, OBJ_CASE_INSENSITIVE, NULL, NULL);
  605. Status = ZwCreateFile(
  606. &Handle,
  607. FILE_READ_ATTRIBUTES,
  608. &Obja,
  609. &IoStatusBlock,
  610. NULL,
  611. 0,
  612. FILE_SHARE_READ | FILE_SHARE_WRITE,
  613. FILE_OPEN,
  614. Directory ? FILE_DIRECTORY_FILE : FILE_NON_DIRECTORY_FILE,
  615. NULL,
  616. 0
  617. );
  618. if(NT_SUCCESS(Status)) {
  619. ZwClose(Handle);
  620. return(TRUE);
  621. } else {
  622. return(FALSE);
  623. }
  624. }
  625. NTSTATUS
  626. SpRenameFile(
  627. IN PCWSTR OldName,
  628. IN PCWSTR NewName,
  629. IN BOOLEAN AllowDirectoryRename
  630. )
  631. {
  632. UNICODE_STRING OldUnicodeString;
  633. UNICODE_STRING NewUnicodeString;
  634. NTSTATUS Status = STATUS_INTERNAL_ERROR;
  635. Status = RtlInitUnicodeStringEx(&OldUnicodeString, OldName);
  636. if (!NT_SUCCESS(Status)) {
  637. goto Exit;
  638. }
  639. Status = RtlInitUnicodeStringEx(&NewUnicodeString, NewName);
  640. if (!NT_SUCCESS(Status)) {
  641. goto Exit;
  642. }
  643. Status = SpRenameFile_Ustr(&OldUnicodeString, &NewUnicodeString, AllowDirectoryRename);
  644. Exit:
  645. return Status;
  646. }
  647. NTSTATUS
  648. SpRenameFile_Ustr(
  649. IN PCUNICODE_STRING OldName,
  650. IN PCUNICODE_STRING NewName,
  651. IN BOOLEAN AllowDirectoryRename
  652. )
  653. /*++
  654. Routine Description:
  655. Rename a file or directory
  656. Arguments:
  657. OldName - Old name of file
  658. NewName - New name of file
  659. AllowDirectoryRename - if TRUE, then this routine will rename a directory,
  660. otherwise directory renames are not allowed.
  661. Return Value:
  662. NT_SUCCESS(NTSTATUS) if file successfully renamed
  663. --*/
  664. {
  665. NTSTATUS Status;
  666. IO_STATUS_BLOCK IoStatusBlock;
  667. OBJECT_ATTRIBUTES Obja;
  668. HANDLE Handle;
  669. struct {
  670. FILE_RENAME_INFORMATION NameInfo;
  671. WCHAR Buffer[ACTUAL_MAX_PATH];
  672. } Buffer;
  673. //
  674. // Prepare to open the file.
  675. //
  676. InitializeObjectAttributes(&Obja, (PUNICODE_STRING)OldName, OBJ_CASE_INSENSITIVE, NULL, NULL);
  677. //
  678. // Attempt to open the file as a file.
  679. //
  680. Status = ZwOpenFile(
  681. &Handle,
  682. (ACCESS_MASK)(DELETE | SYNCHRONIZE),
  683. &Obja,
  684. &IoStatusBlock,
  685. FILE_SHARE_READ | FILE_SHARE_WRITE,
  686. FILE_NON_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT
  687. );
  688. if(!NT_SUCCESS(Status) && AllowDirectoryRename) {
  689. //
  690. // Attempt to open the file as a directory.
  691. //
  692. Status = ZwOpenFile(
  693. &Handle,
  694. (ACCESS_MASK)(DELETE | SYNCHRONIZE),
  695. &Obja,
  696. &IoStatusBlock,
  697. FILE_SHARE_READ | FILE_SHARE_WRITE,
  698. FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT
  699. );
  700. }
  701. if(!NT_SUCCESS(Status)) {
  702. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: Unable to open %wZ for rename (%lx)\n",OldName,Status));
  703. return(Status);
  704. }
  705. //
  706. // Change the file name
  707. //
  708. RtlZeroMemory(&Buffer, sizeof(Buffer));
  709. Buffer.NameInfo.ReplaceIfExists = FALSE;
  710. Buffer.NameInfo.RootDirectory = NULL;
  711. Buffer.NameInfo.FileNameLength = NewName->Length;
  712. RtlCopyMemory( Buffer.NameInfo.FileName, NewName->Buffer, NewName->Length );
  713. Status = SpSetInformationFile(
  714. Handle,
  715. FileRenameInformation,
  716. sizeof(Buffer),
  717. (PVOID)&Buffer
  718. );
  719. if(!NT_SUCCESS(Status)) {
  720. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: Unable to change name of %wZ to %wZ. Status = (%lx)\n",OldName,NewName,Status));
  721. }
  722. //
  723. // Clean up and return.
  724. //
  725. ZwClose(Handle);
  726. return(Status);
  727. }
  728. USHORT
  729. SpChkSum(
  730. ULONG PartialSum,
  731. PUSHORT Source,
  732. ULONG Length
  733. )
  734. /*++
  735. Routine Description:
  736. Compute a partial checksum on a portion of an imagefile.
  737. Arguments:
  738. PartialSum - Supplies the initial checksum value.
  739. Sources - Supplies a pointer to the array of words for which the
  740. checksum is computed.
  741. Length - Supplies the length of the array in words.
  742. Return Value:
  743. The computed checksum value is returned as the function value.
  744. --*/
  745. {
  746. //
  747. // Compute the word wise checksum allowing carries to occur into the
  748. // high order half of the checksum longword.
  749. //
  750. while (Length--) {
  751. PartialSum += *Source++;
  752. PartialSum = (PartialSum >> 16) + (PartialSum & 0xffff);
  753. }
  754. //
  755. // Fold final carry into a single word result and return the resultant
  756. // value.
  757. //
  758. return (USHORT)(((PartialSum >> 16) + PartialSum) & 0xffff);
  759. }
  760. PIMAGE_NT_HEADERS
  761. SpChecksumMappedFile(
  762. IN PVOID BaseAddress,
  763. IN ULONG FileSize,
  764. OUT PULONG HeaderSum,
  765. OUT PULONG Checksum
  766. )
  767. {
  768. PIMAGE_NT_HEADERS NtHeaders;
  769. USHORT PartialSum;
  770. PUSHORT AdjustSum;
  771. try {
  772. //
  773. // Compute the checksum of this file and zero the header sum.
  774. //
  775. PartialSum = SpChkSum(0,BaseAddress,(FileSize+1) >> 1);
  776. *HeaderSum = 0;
  777. //
  778. // See whether this is an image.
  779. //
  780. if(NtHeaders = RtlImageNtHeader(BaseAddress)) {
  781. //
  782. // The file is an image file -- subtract the two checksum words
  783. // in the optional header from the computed checksum before adding
  784. // the file length, and set the value of the header checksum.
  785. //
  786. *HeaderSum = NtHeaders->OptionalHeader.CheckSum;
  787. AdjustSum = (PUSHORT)(&NtHeaders->OptionalHeader.CheckSum);
  788. PartialSum -= (PartialSum < AdjustSum[0]);
  789. PartialSum -= AdjustSum[0];
  790. PartialSum -= (PartialSum < AdjustSum[1]);
  791. PartialSum -= AdjustSum[1];
  792. }
  793. //
  794. // Compute the checksum.
  795. //
  796. *Checksum = (ULONG)PartialSum + FileSize;
  797. } except(EXCEPTION_EXECUTE_HANDLER) {
  798. NtHeaders = NULL;
  799. }
  800. return(NtHeaders);
  801. }
  802. NTSTATUS
  803. SpOpenNameMayBeCompressed(
  804. IN PWSTR FullPath,
  805. IN ULONG OpenAccess,
  806. IN ULONG FileAttributes,
  807. IN ULONG ShareFlags,
  808. IN ULONG Disposition,
  809. IN ULONG OpenFlags,
  810. OUT PHANDLE Handle,
  811. OUT PBOOLEAN OpenedCompressedName OPTIONAL
  812. )
  813. {
  814. NTSTATUS Status;
  815. PWSTR compname;
  816. PWSTR names[2];
  817. int compord,uncompord;
  818. static BOOLEAN PreviousWasCompressed = FALSE;
  819. BOOLEAN IsComp;
  820. int i;
  821. UNICODE_STRING UnicodeString;
  822. OBJECT_ATTRIBUTES Obja;
  823. IO_STATUS_BLOCK IoStatusBlock;
  824. //
  825. // Generate compressed name.
  826. //
  827. compname = SpGenerateCompressedName(FullPath);
  828. //
  829. // Figure out which name to try to use first. If the last successful
  830. // call to this routine opened the file using the compressed name, then
  831. // try to open the compressed name first. Otherwise try to open the
  832. // uncompressed name first.
  833. //
  834. if(PreviousWasCompressed) {
  835. compord = 0;
  836. uncompord = 1;
  837. } else {
  838. compord = 1;
  839. uncompord = 0;
  840. }
  841. names[uncompord] = FullPath;
  842. names[compord] = compname;
  843. for(i=0; i<2; i++) {
  844. INIT_OBJA(&Obja,&UnicodeString,names[i]);
  845. Status = ZwCreateFile(
  846. Handle,
  847. OpenAccess,
  848. &Obja,
  849. &IoStatusBlock,
  850. NULL,
  851. FileAttributes,
  852. ShareFlags,
  853. Disposition,
  854. OpenFlags,
  855. NULL,
  856. 0
  857. );
  858. if(NT_SUCCESS(Status)) {
  859. IsComp = (BOOLEAN)(i == compord);
  860. PreviousWasCompressed = IsComp;
  861. if(OpenedCompressedName) {
  862. *OpenedCompressedName = IsComp;
  863. }
  864. break;
  865. }
  866. }
  867. SpMemFree(compname);
  868. return(Status);
  869. }
  870. NTSTATUS
  871. SpGetFileSizeByName(
  872. IN PWSTR DevicePath OPTIONAL,
  873. IN PWSTR Directory OPTIONAL,
  874. IN PWSTR FileName,
  875. OUT PULONG Size
  876. )
  877. /*++
  878. Routine Description:
  879. Determine the size of a file. Only the low 32 bits of the size
  880. are considered.
  881. Arguments:
  882. DevicePath - Path to the device that contains the file.
  883. Directory - Name of the directory that contains the file.
  884. FileName - Name of the file.
  885. Size - receives size of file.
  886. Return Value:
  887. NTSTATUs -
  888. --*/
  889. {
  890. PWSTR CompleteFileName;
  891. HANDLE FileHandle;
  892. OBJECT_ATTRIBUTES ObjectAttributes;
  893. IO_STATUS_BLOCK IoStatusBlock;
  894. NTSTATUS Status;
  895. UNICODE_STRING UnicodeFileName;
  896. ULONG FileNameLength;
  897. FileNameLength = wcslen( FileName ) + 1;
  898. if( DevicePath != NULL ) {
  899. FileNameLength += wcslen( DevicePath ) + 1;
  900. }
  901. if( Directory != NULL ) {
  902. FileNameLength += wcslen( Directory ) + 1;
  903. }
  904. CompleteFileName = SpMemAlloc( FileNameLength*sizeof( WCHAR ) );
  905. if( CompleteFileName == NULL ) {
  906. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: Unable to allocate memory on SpGetFileSizeByName \n" ));
  907. return( STATUS_NO_MEMORY );
  908. }
  909. *CompleteFileName = (WCHAR)'\0';
  910. if( DevicePath != NULL ) {
  911. SpConcatenatePaths( CompleteFileName, DevicePath );
  912. }
  913. if( Directory != NULL ) {
  914. SpConcatenatePaths( CompleteFileName, Directory );
  915. }
  916. SpConcatenatePaths( CompleteFileName, FileName );
  917. RtlInitUnicodeString( &UnicodeFileName,
  918. CompleteFileName );
  919. InitializeObjectAttributes( &ObjectAttributes,
  920. &UnicodeFileName,
  921. OBJ_CASE_INSENSITIVE,
  922. NULL,
  923. NULL );
  924. Status = ZwOpenFile( &FileHandle,
  925. STANDARD_RIGHTS_READ | FILE_READ_ATTRIBUTES | SYNCHRONIZE,
  926. &ObjectAttributes,
  927. &IoStatusBlock,
  928. 0,
  929. FILE_SYNCHRONOUS_IO_NONALERT );
  930. if( !NT_SUCCESS( Status ) ) {
  931. SpMemFree( CompleteFileName );
  932. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: ZwOpenFile() failed. File = %ls, Status = %x\n",FileName, Status ) );
  933. return( Status );
  934. }
  935. Status = SpGetFileSize( FileHandle, Size );
  936. ZwClose( FileHandle );
  937. SpMemFree( CompleteFileName );
  938. if( !NT_SUCCESS( Status ) ) {
  939. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: SpGetFileSize() failed. File = %ls, Status = %x\n",FileName, Status ) );
  940. return( Status );
  941. }
  942. return( Status );
  943. }
  944. VOID
  945. SpVerifyNoCompression(
  946. IN PWSTR FileName
  947. )
  948. /*++
  949. Routine Description:
  950. Determine if the file is compressed (via NTFS compression), and if so,
  951. uncompress it.
  952. Arguments:
  953. FileName - Name of the file that must be uncompressed.
  954. Return Value:
  955. none
  956. --*/
  957. {
  958. HANDLE FileHandle;
  959. IO_STATUS_BLOCK IoStatusBlock;
  960. UNICODE_STRING UnicodeString;
  961. OBJECT_ATTRIBUTES Obja;
  962. NTSTATUS Status;
  963. FILE_BASIC_INFORMATION BasicFileInfo;
  964. INIT_OBJA(&Obja, &UnicodeString, FileName);
  965. Status = ZwCreateFile(
  966. &FileHandle,
  967. 0,
  968. &Obja,
  969. &IoStatusBlock,
  970. NULL,
  971. FILE_ATTRIBUTE_NORMAL,
  972. FILE_SHARE_READ | FILE_SHARE_WRITE,
  973. FILE_OPEN,
  974. 0,
  975. NULL,
  976. 0
  977. );
  978. if(!NT_SUCCESS(Status)) {
  979. //
  980. // Ignore error.
  981. //
  982. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: SpVerifyNoCompression unable to open file %ws (%lx)\n", FileName, Status));
  983. return;
  984. }
  985. Status = ZwQueryInformationFile(
  986. FileHandle,
  987. &IoStatusBlock,
  988. &BasicFileInfo,
  989. sizeof(BasicFileInfo),
  990. FileBasicInformation
  991. );
  992. if(!NT_SUCCESS(Status)) {
  993. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: SpVerifyNoCompression unable to get basic file info for %ws (%lx)\n", FileName, Status));
  994. goto ComprVerifyDone;
  995. }
  996. if(BasicFileInfo.FileAttributes & FILE_ATTRIBUTE_COMPRESSED) {
  997. USHORT CompressionState = 0;
  998. Status = ZwFsControlFile(
  999. FileHandle,
  1000. NULL,
  1001. NULL,
  1002. NULL,
  1003. &IoStatusBlock,
  1004. FSCTL_SET_COMPRESSION,
  1005. &CompressionState,
  1006. sizeof(CompressionState),
  1007. NULL,
  1008. 0
  1009. );
  1010. if(!NT_SUCCESS(Status)) {
  1011. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: SpVerifyNoCompression unable to uncompress %ws (%lx)\n", FileName, Status));
  1012. }
  1013. }
  1014. ComprVerifyDone:
  1015. ZwClose(FileHandle);
  1016. return;
  1017. }