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.

900 lines
25 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. spwin.c
  5. Abstract:
  6. Win32 portability layer to support windows\winstate\...\cablib.c
  7. file i/o
  8. Get/SpSetLastWin32Error
  9. see also
  10. .\spcab.c
  11. .\spbasefile.c
  12. .\spbasefile.h
  13. windows\winstate\...\cablib.c
  14. windows\winstate\cobra\utils\main\basefile.c
  15. windows\winstate\cobra\utils\inc\basefile.h
  16. Author:
  17. Jay Krell (a-JayK) November 2000
  18. Revision History:
  19. --*/
  20. #include "spprecmp.h"
  21. #include "spcab.h"
  22. #include "nt.h"
  23. #include "ntrtl.h"
  24. #include "zwapi.h"
  25. #include "spwin.h"
  26. #include "spwinp.h"
  27. #include <limits.h>
  28. #include "fci.h"
  29. NTSTATUS
  30. SpConvertWin32FileOpenOrCreateToNtFileOpenOrCreate(
  31. ULONG Win32OpenOrCreate,
  32. ULONG* NtOpenOrCreate
  33. )
  34. {
  35. //
  36. // there's no pattern here and the values all overlap
  37. // yuck; this is copied from kernel32 source
  38. //
  39. *NtOpenOrCreate = ~0;
  40. switch (Win32OpenOrCreate)
  41. {
  42. default:
  43. return STATUS_INVALID_PARAMETER;
  44. case CREATE_NEW:
  45. *NtOpenOrCreate = FILE_CREATE;
  46. break;
  47. case CREATE_ALWAYS:
  48. *NtOpenOrCreate = FILE_OVERWRITE_IF;
  49. break;
  50. case OPEN_EXISTING:
  51. *NtOpenOrCreate = FILE_OPEN;
  52. break;
  53. case OPEN_ALWAYS:
  54. *NtOpenOrCreate = FILE_OPEN_IF;
  55. break;
  56. case TRUNCATE_EXISTING :
  57. *NtOpenOrCreate = FILE_OPEN;
  58. }
  59. return STATUS_SUCCESS;
  60. }
  61. NTSTATUS
  62. SpConvertWin32FileAccessToNtFileAccess(
  63. ULONG Win32FileAccess,
  64. ULONG* NtFileAccess
  65. )
  66. {
  67. //
  68. // ZwCreateFile oddities require us to do this conversion, or at least
  69. // to add in SYNCHRONIZE.
  70. //
  71. *NtFileAccess =
  72. (Win32FileAccess & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL))
  73. | ((Win32FileAccess & GENERIC_READ) ? FILE_GENERIC_READ : 0)
  74. | ((Win32FileAccess & GENERIC_WRITE) ? FILE_GENERIC_WRITE : 0)
  75. | ((Win32FileAccess & GENERIC_EXECUTE) ? FILE_GENERIC_EXECUTE : 0)
  76. | ((Win32FileAccess & GENERIC_ALL) ? FILE_ALL_ACCESS : 0)
  77. | SYNCHRONIZE
  78. ;
  79. return STATUS_SUCCESS;
  80. }
  81. NTSTATUS
  82. SpConvertWin32FileShareToNtFileShare(
  83. ULONG Win32FileShare,
  84. ULONG* NtFileShare
  85. )
  86. {
  87. *NtFileShare = Win32FileShare;
  88. return STATUS_SUCCESS;
  89. }
  90. HANDLE
  91. SpNtCreateFileW(
  92. PCUNICODE_STRING ConstantPath,
  93. IN ULONG FileAccess,
  94. IN ULONG FileShare,
  95. IN LPSECURITY_ATTRIBUTES SecurityAttributes,
  96. IN ULONG Win32FileOpenOrCreate,
  97. IN ULONG FlagsAndAttributes,
  98. IN HANDLE TemplateFile
  99. )
  100. /*++
  101. Subset:
  102. no security
  103. no directories
  104. no async
  105. no console
  106. no ea (extended attributes)
  107. --*/
  108. {
  109. NTSTATUS Status = STATUS_SUCCESS;
  110. IO_STATUS_BLOCK IoStatusBlock = { 0 };
  111. HANDLE FileHandle = INVALID_HANDLE_VALUE;
  112. ULONG NtFileOpenOrCreate = 0;
  113. FILE_ALLOCATION_INFORMATION AllocationInfo = { 0 };
  114. PUNICODE_STRING Path = RTL_CONST_CAST(PUNICODE_STRING)(ConstantPath);
  115. /*const*/OBJECT_ATTRIBUTES ObjectAttributes = { sizeof(ObjectAttributes), NULL, Path, OBJ_CASE_INSENSITIVE };
  116. ASSERT(TemplateFile == NULL);
  117. ASSERT(SecurityAttributes == NULL);
  118. ASSERT((FlagsAndAttributes & ~(FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_ARCHIVE)) == 0);
  119. if (!NT_SUCCESS(Status = SpConvertWin32FileAccessToNtFileAccess(FileAccess, &FileAccess)))
  120. goto NtExit;
  121. if (!NT_SUCCESS(Status = SpConvertWin32FileOpenOrCreateToNtFileOpenOrCreate(Win32FileOpenOrCreate, &NtFileOpenOrCreate)))
  122. goto NtExit;
  123. if (!NT_SUCCESS(Status = SpConvertWin32FileShareToNtFileShare(FileShare, &FileShare)))
  124. goto NtExit;
  125. Status =
  126. ZwCreateFile(
  127. &FileHandle,
  128. FileAccess
  129. | SYNCHRONIZE // like kernel32
  130. | FILE_READ_ATTRIBUTES, // like kernel32
  131. &ObjectAttributes,
  132. &IoStatusBlock,
  133. NULL, // AllocationSize
  134. FlagsAndAttributes,
  135. FileShare,
  136. NtFileOpenOrCreate,
  137. FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE,
  138. NULL, // EaBuffer,
  139. 0 // EaLength
  140. );
  141. // based closely on kernel32
  142. if ( !NT_SUCCESS(Status) ) {
  143. SpSetLastWin32ErrorAndNtStatusFromNtStatus(Status);
  144. if ( Status == STATUS_OBJECT_NAME_COLLISION ) {
  145. SpSetLastWin32Error(ERROR_FILE_EXISTS);
  146. }
  147. else if ( Status == STATUS_FILE_IS_A_DIRECTORY ) {
  148. if (Path->Length != 0 && Path->Buffer[Path->Length / sizeof(Path->Buffer[0])] == '\\') {
  149. SpSetLastWin32Error(ERROR_PATH_NOT_FOUND);
  150. }
  151. else {
  152. SpSetLastWin32Error(ERROR_ACCESS_DENIED);
  153. }
  154. }
  155. FileHandle = INVALID_HANDLE_VALUE;
  156. goto Exit;
  157. }
  158. //
  159. // if NT returns supersede/overwritten, it means that a create_always, openalways
  160. // found an existing copy of the file. In this case ERROR_ALREADY_EXISTS is returned
  161. //
  162. if ( (Win32FileOpenOrCreate == CREATE_ALWAYS && IoStatusBlock.Information == FILE_OVERWRITTEN) ||
  163. (Win32FileOpenOrCreate == OPEN_ALWAYS && IoStatusBlock.Information == FILE_OPENED) ) {
  164. SpSetLastWin32Error(ERROR_ALREADY_EXISTS);
  165. }
  166. else {
  167. SpSetLastWin32Error(0);
  168. }
  169. //
  170. // Truncate the file if required
  171. //
  172. if ( Win32FileOpenOrCreate == TRUNCATE_EXISTING) {
  173. AllocationInfo.AllocationSize.QuadPart = 0;
  174. Status = ZwSetInformationFile(
  175. FileHandle,
  176. &IoStatusBlock,
  177. &AllocationInfo,
  178. sizeof(AllocationInfo),
  179. FileAllocationInformation
  180. );
  181. if ( !NT_SUCCESS(Status) ) {
  182. ZwClose(FileHandle);
  183. FileHandle = INVALID_HANDLE_VALUE;
  184. SpSetLastWin32ErrorAndNtStatusFromNtStatus(Status);
  185. }
  186. }
  187. Exit:
  188. return FileHandle;
  189. NtExit:
  190. SpSetLastWin32ErrorAndNtStatusFromNtStatus(Status);
  191. goto Exit;
  192. }
  193. HANDLE
  194. WINAPI
  195. SpWin32CreateFileW(
  196. IN PCWSTR FileName,
  197. IN ULONG FileAccess,
  198. IN ULONG FileShare,
  199. IN LPSECURITY_ATTRIBUTES SecurityAttributes,
  200. IN ULONG FileOpenOrCreate,
  201. IN ULONG FlagsAndAttributes,
  202. IN HANDLE TemplateFile
  203. )
  204. {
  205. HANDLE FileHandle = INVALID_HANDLE_VALUE;
  206. UNICODE_STRING UnicodeString = { 0 };
  207. NTSTATUS Status = STATUS_SUCCESS;
  208. RtlInitUnicodeString(&UnicodeString, FileName);
  209. FileHandle = SpNtCreateFileW(&UnicodeString, FileAccess, FileShare, SecurityAttributes, FileOpenOrCreate, FlagsAndAttributes, TemplateFile);
  210. ASSERT (FileHandle); // never NULL
  211. if (FileHandle == INVALID_HANDLE_VALUE)
  212. goto Exit;
  213. Exit:
  214. return FileHandle;
  215. }
  216. HANDLE
  217. WINAPI
  218. SpWin32CreateFileA(
  219. IN PCSTR FileName,
  220. IN ULONG FileAccess,
  221. IN ULONG FileShare,
  222. IN LPSECURITY_ATTRIBUTES SecurityAttributes,
  223. IN ULONG FileOpenOrCreate,
  224. IN ULONG dwFlagsAndAttributes,
  225. IN HANDLE TemplateFile
  226. )
  227. {
  228. ANSI_STRING AnsiString = { 0 };
  229. NTSTATUS Status = STATUS_SUCCESS;
  230. HANDLE Handle = INVALID_HANDLE_VALUE;
  231. UNICODE_STRING UnicodeString = { 0 };
  232. RtlInitAnsiString(&AnsiString, FileName);
  233. AnsiString.Length = AnsiString.MaximumLength; // include terminal nul
  234. if (!NT_SUCCESS(Status = SpAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE)))
  235. goto NtExit;
  236. UnicodeString.Length -= sizeof(UnicodeString.Buffer[0]); // remove terminal nul
  237. Handle = SpNtCreateFileW(&UnicodeString, FileAccess, FileShare, SecurityAttributes, FileOpenOrCreate, dwFlagsAndAttributes, TemplateFile);
  238. Exit:
  239. SpFreeStringW(&UnicodeString);
  240. KdPrintEx((
  241. DPFLTR_SETUP_ID,
  242. SpHandleToDbgPrintLevel(Handle),
  243. "SETUP:"__FUNCTION__"(%s) exiting with FileHandle: %p Status:0x%08lx Error:%d\n",
  244. FileName, Handle, SpGetLastNtStatus(), SpGetLastWin32Error()
  245. ));
  246. return Handle;
  247. NtExit:
  248. SpSetLastWin32ErrorAndNtStatusFromNtStatus(Status);
  249. goto Exit;
  250. }
  251. BOOL
  252. WINAPI
  253. SpWin32ReadFile(
  254. HANDLE hFile,
  255. PVOID lpBuffer,
  256. ULONG nNumberOfBytesToRead,
  257. ULONG* lpNumberOfBytesRead,
  258. LPOVERLAPPED lpOverlapped
  259. )
  260. {
  261. NTSTATUS Status;
  262. IO_STATUS_BLOCK IoStatusBlock;
  263. ASSERT(!ARGUMENT_PRESENT(lpOverlapped));
  264. if ( ARGUMENT_PRESENT(lpNumberOfBytesRead) ) {
  265. *lpNumberOfBytesRead = 0;
  266. }
  267. Status = ZwReadFile(
  268. hFile,
  269. NULL,
  270. NULL,
  271. NULL,
  272. &IoStatusBlock,
  273. lpBuffer,
  274. nNumberOfBytesToRead,
  275. NULL,
  276. NULL
  277. );
  278. if ( Status == STATUS_PENDING) {
  279. // Operation must complete before return & IoStatusBlock destroyed
  280. Status = ZwWaitForSingleObject( hFile, FALSE, NULL );
  281. if ( NT_SUCCESS(Status)) {
  282. Status = IoStatusBlock.Status;
  283. }
  284. }
  285. if ( NT_SUCCESS(Status) ) {
  286. *lpNumberOfBytesRead = (ULONG)IoStatusBlock.Information;
  287. return TRUE;
  288. }
  289. else
  290. if (Status == STATUS_END_OF_FILE) {
  291. *lpNumberOfBytesRead = 0;
  292. return TRUE;
  293. }
  294. else {
  295. if ( NT_WARNING(Status) ) {
  296. *lpNumberOfBytesRead = (ULONG)IoStatusBlock.Information;
  297. }
  298. SpSetLastWin32ErrorAndNtStatusFromNtStatus(Status);
  299. return FALSE;
  300. }
  301. }
  302. BOOL
  303. WINAPI
  304. SpWin32WriteFile(
  305. HANDLE hFile,
  306. CONST VOID* lpBuffer,
  307. ULONG nNumberOfBytesToWrite,
  308. ULONG* lpNumberOfBytesWritten,
  309. LPOVERLAPPED lpOverlapped
  310. )
  311. {
  312. NTSTATUS Status;
  313. IO_STATUS_BLOCK IoStatusBlock;
  314. PPEB Peb;
  315. ASSERT(!ARGUMENT_PRESENT( lpOverlapped ) );
  316. if ( ARGUMENT_PRESENT(lpNumberOfBytesWritten) ) {
  317. *lpNumberOfBytesWritten = 0;
  318. }
  319. Status = ZwWriteFile(
  320. hFile,
  321. NULL,
  322. NULL,
  323. NULL,
  324. &IoStatusBlock,
  325. RTL_CONST_CAST(PVOID)(lpBuffer),
  326. nNumberOfBytesToWrite,
  327. NULL,
  328. NULL
  329. );
  330. if ( Status == STATUS_PENDING) {
  331. // Operation must complete before return & IoStatusBlock destroyed
  332. Status = ZwWaitForSingleObject( hFile, FALSE, NULL );
  333. if ( NT_SUCCESS(Status)) {
  334. Status = IoStatusBlock.Status;
  335. }
  336. }
  337. if ( NT_SUCCESS(Status)) {
  338. *lpNumberOfBytesWritten = (ULONG)IoStatusBlock.Information;
  339. return TRUE;
  340. }
  341. else {
  342. if ( NT_WARNING(Status) ) {
  343. *lpNumberOfBytesWritten = (ULONG)IoStatusBlock.Information;
  344. }
  345. SpSetLastWin32ErrorAndNtStatusFromNtStatus(Status);
  346. return FALSE;
  347. }
  348. }
  349. ULONG
  350. WINAPI
  351. SpSetFilePointer(
  352. HANDLE hFile,
  353. LONG lDistanceToMove,
  354. LONG* lpDistanceToMoveHigh,
  355. ULONG dwMoveMethod
  356. )
  357. {
  358. NTSTATUS Status;
  359. IO_STATUS_BLOCK IoStatusBlock;
  360. FILE_POSITION_INFORMATION CurrentPosition;
  361. FILE_STANDARD_INFORMATION StandardInfo;
  362. LARGE_INTEGER Large;
  363. if (ARGUMENT_PRESENT(lpDistanceToMoveHigh)) {
  364. Large.HighPart = *lpDistanceToMoveHigh;
  365. Large.LowPart = lDistanceToMove;
  366. }
  367. else {
  368. Large.QuadPart = lDistanceToMove;
  369. }
  370. switch (dwMoveMethod) {
  371. case FILE_BEGIN :
  372. CurrentPosition.CurrentByteOffset = Large;
  373. break;
  374. case FILE_CURRENT :
  375. //
  376. // Get the current position of the file pointer
  377. //
  378. Status = ZwQueryInformationFile(
  379. hFile,
  380. &IoStatusBlock,
  381. &CurrentPosition,
  382. sizeof(CurrentPosition),
  383. FilePositionInformation
  384. );
  385. if ( !NT_SUCCESS(Status) ) {
  386. SpSetLastWin32ErrorAndNtStatusFromNtStatus(Status);
  387. return (ULONG)(LONG)-1;
  388. }
  389. CurrentPosition.CurrentByteOffset.QuadPart += Large.QuadPart;
  390. break;
  391. case FILE_END :
  392. Status = ZwQueryInformationFile(
  393. hFile,
  394. &IoStatusBlock,
  395. &StandardInfo,
  396. sizeof(StandardInfo),
  397. FileStandardInformation
  398. );
  399. if ( !NT_SUCCESS(Status) ) {
  400. SpSetLastWin32ErrorAndNtStatusFromNtStatus(Status);
  401. return (ULONG)(LONG)-1;
  402. }
  403. CurrentPosition.CurrentByteOffset.QuadPart =
  404. StandardInfo.EndOfFile.QuadPart + Large.QuadPart;
  405. break;
  406. default:
  407. SpSetLastWin32Error(ERROR_INVALID_PARAMETER);
  408. return (ULONG)(LONG)-1;
  409. break;
  410. }
  411. //
  412. // If the resulting file position is negative, or if the app is not
  413. // prepared for greater than
  414. // than 32 bits than fail
  415. //
  416. if ( CurrentPosition.CurrentByteOffset.QuadPart < 0 ) {
  417. SpSetLastWin32Error(ERROR_NEGATIVE_SEEK);
  418. return (ULONG)(LONG)-1;
  419. }
  420. if ( !ARGUMENT_PRESENT(lpDistanceToMoveHigh) &&
  421. (CurrentPosition.CurrentByteOffset.HighPart & MAXLONG) ) {
  422. SpSetLastWin32Error(ERROR_INVALID_PARAMETER);
  423. return (ULONG)(LONG)-1;
  424. }
  425. //
  426. // Set the current file position
  427. //
  428. Status = ZwSetInformationFile(
  429. hFile,
  430. &IoStatusBlock,
  431. &CurrentPosition,
  432. sizeof(CurrentPosition),
  433. FilePositionInformation
  434. );
  435. if ( NT_SUCCESS(Status) ) {
  436. if (ARGUMENT_PRESENT(lpDistanceToMoveHigh)){
  437. *lpDistanceToMoveHigh = CurrentPosition.CurrentByteOffset.HighPart;
  438. }
  439. if ( CurrentPosition.CurrentByteOffset.LowPart == -1 ) {
  440. SpSetLastWin32Error(0);
  441. }
  442. return CurrentPosition.CurrentByteOffset.LowPart;
  443. }
  444. else {
  445. SpSetLastWin32ErrorAndNtStatusFromNtStatus(Status);
  446. if (ARGUMENT_PRESENT(lpDistanceToMoveHigh)){
  447. *lpDistanceToMoveHigh = -1;
  448. }
  449. return (ULONG)(LONG)-1;
  450. }
  451. }
  452. BOOL
  453. WINAPI
  454. SpWin32DeleteFileA(
  455. PCSTR FileName
  456. )
  457. {
  458. BOOL Success = FALSE;
  459. NTSTATUS Status = STATUS_SUCCESS;
  460. ANSI_STRING AnsiString = { 0 };
  461. UNICODE_STRING UnicodeString = { 0 };
  462. if (FileName == NULL || FileName[0] == 0) {
  463. KdPrintEx((
  464. DPFLTR_SETUP_ID,
  465. DPFLTR_TRACE_LEVEL,
  466. "SETUP:"__FUNCTION__"(NULL or empty), claiming success\n"
  467. ));
  468. Success = TRUE;
  469. goto Exit;
  470. }
  471. RtlInitAnsiString(&AnsiString, FileName);
  472. AnsiString.Length = AnsiString.MaximumLength; // include terminal nul
  473. Status = SpAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE);
  474. if (!NT_SUCCESS(Status))
  475. goto NtExit;
  476. Status = SpDeleteFile(UnicodeString.Buffer, NULL, NULL);
  477. if (!NT_SUCCESS(Status))
  478. goto NtExit;
  479. Success = TRUE;
  480. Exit:
  481. SpFreeStringW(&UnicodeString);
  482. KdPrintEx((
  483. DPFLTR_SETUP_ID,
  484. SpBoolToDbgPrintLevel(Success),
  485. "SETUP:"__FUNCTION__"(%s) exiting with Success: %s Status:0x%08lx Error:%d\n",
  486. FileName, SpBooleanToStringA(Success), SpGetLastNtStatus(), SpGetLastWin32Error()
  487. ));
  488. return Success;
  489. NtExit:
  490. SpSetLastWin32ErrorAndNtStatusFromNtStatus(Status);
  491. goto Exit;
  492. }
  493. //
  494. // move this to ntrtl
  495. //
  496. #define AlmostTwoSeconds (2*1000*1000*10 - 1)
  497. BOOL
  498. APIENTRY
  499. SpFileTimeToDosDateTime(
  500. CONST FILETIME *lpFileTime,
  501. LPWORD lpFatDate,
  502. LPWORD lpFatTime
  503. )
  504. {
  505. TIME_FIELDS TimeFields;
  506. LARGE_INTEGER FileTime;
  507. FileTime.LowPart = lpFileTime->dwLowDateTime;
  508. FileTime.HighPart = lpFileTime->dwHighDateTime;
  509. FileTime.QuadPart = FileTime.QuadPart + (LONGLONG)AlmostTwoSeconds;
  510. if ( FileTime.QuadPart < 0 ) {
  511. SpSetLastWin32Error(ERROR_INVALID_PARAMETER);
  512. return FALSE;
  513. }
  514. RtlTimeToTimeFields(&FileTime, &TimeFields);
  515. if (TimeFields.Year < 1980 || TimeFields.Year > 2107) {
  516. SpSetLastWin32ErrorAndNtStatusFromNtStatus(STATUS_INVALID_PARAMETER);
  517. return FALSE;
  518. }
  519. *lpFatDate = (WORD)( ((USHORT)(TimeFields.Year-(CSHORT)1980) << 9) |
  520. ((USHORT)TimeFields.Month << 5) |
  521. (USHORT)TimeFields.Day
  522. );
  523. *lpFatTime = (WORD)( ((USHORT)TimeFields.Hour << 11) |
  524. ((USHORT)TimeFields.Minute << 5) |
  525. ((USHORT)TimeFields.Second >> 1)
  526. );
  527. return TRUE;
  528. }
  529. BOOL
  530. APIENTRY
  531. SpDosDateTimeToFileTime(
  532. WORD wFatDate,
  533. WORD wFatTime,
  534. LPFILETIME lpFileTime
  535. )
  536. {
  537. TIME_FIELDS TimeFields;
  538. LARGE_INTEGER FileTime;
  539. TimeFields.Year = (CSHORT)((wFatDate & 0xFE00) >> 9)+(CSHORT)1980;
  540. TimeFields.Month = (CSHORT)((wFatDate & 0x01E0) >> 5);
  541. TimeFields.Day = (CSHORT)((wFatDate & 0x001F) >> 0);
  542. TimeFields.Hour = (CSHORT)((wFatTime & 0xF800) >> 11);
  543. TimeFields.Minute = (CSHORT)((wFatTime & 0x07E0) >> 5);
  544. TimeFields.Second = (CSHORT)((wFatTime & 0x001F) << 1);
  545. TimeFields.Milliseconds = 0;
  546. if (RtlTimeFieldsToTime(&TimeFields,&FileTime)) {
  547. lpFileTime->dwLowDateTime = FileTime.LowPart;
  548. lpFileTime->dwHighDateTime = FileTime.HighPart;
  549. return TRUE;
  550. }
  551. else {
  552. SpSetLastWin32ErrorAndNtStatusFromNtStatus(STATUS_INVALID_PARAMETER);
  553. return FALSE;
  554. }
  555. }
  556. BOOL
  557. WINAPI
  558. SpFileTimeToLocalFileTime(
  559. CONST FILETIME *lpFileTime,
  560. LPFILETIME lpLocalFileTime
  561. )
  562. {
  563. //
  564. // just return it unchanged
  565. // UTC is good
  566. //
  567. *lpLocalFileTime = *lpFileTime;
  568. return TRUE;
  569. }
  570. BOOL
  571. WINAPI
  572. SpLocalFileTimeToFileTime(
  573. CONST FILETIME *lpLocalFileTime,
  574. LPFILETIME lpFileTime
  575. )
  576. {
  577. //
  578. // just return it unchanged
  579. // UTC is good
  580. //
  581. *lpFileTime = *lpLocalFileTime;
  582. return TRUE;
  583. }
  584. BOOL
  585. WINAPI
  586. SpSetFileTime(
  587. HANDLE hFile,
  588. CONST FILETIME *lpCreationTime,
  589. CONST FILETIME *lpLastAccessTime,
  590. CONST FILETIME *lpLastWriteTime
  591. )
  592. {
  593. NTSTATUS Status;
  594. IO_STATUS_BLOCK IoStatusBlock;
  595. FILE_BASIC_INFORMATION BasicInfo = { 0 };
  596. //
  597. // For each time value that is specified, copy it to the I/O system
  598. // record.
  599. //
  600. if (ARGUMENT_PRESENT( lpCreationTime )) {
  601. BasicInfo.CreationTime.LowPart = lpCreationTime->dwLowDateTime;
  602. BasicInfo.CreationTime.HighPart = lpCreationTime->dwHighDateTime;
  603. }
  604. if (ARGUMENT_PRESENT( lpLastAccessTime )) {
  605. BasicInfo.LastAccessTime.LowPart = lpLastAccessTime->dwLowDateTime;
  606. BasicInfo.LastAccessTime.HighPart = lpLastAccessTime->dwHighDateTime;
  607. }
  608. if (ARGUMENT_PRESENT( lpLastWriteTime )) {
  609. BasicInfo.LastWriteTime.LowPart = lpLastWriteTime->dwLowDateTime;
  610. BasicInfo.LastWriteTime.HighPart = lpLastWriteTime->dwHighDateTime;
  611. }
  612. //
  613. // Set the requested times.
  614. //
  615. Status = ZwSetInformationFile(
  616. hFile,
  617. &IoStatusBlock,
  618. &BasicInfo,
  619. sizeof(BasicInfo),
  620. FileBasicInformation
  621. );
  622. if ( NT_SUCCESS(Status) ) {
  623. return TRUE;
  624. }
  625. else {
  626. SpSetLastWin32ErrorAndNtStatusFromNtStatus(Status);
  627. return FALSE;
  628. }
  629. }
  630. BOOL
  631. APIENTRY
  632. SpSetFileAttributesA(
  633. PCSTR lpFileName,
  634. DWORD dwFileAttributes
  635. )
  636. {
  637. UNICODE_STRING UnicodeString = { 0 };
  638. ANSI_STRING AnsiString = { 0 };
  639. BOOL Success = FALSE;
  640. NTSTATUS Status = STATUS_SUCCESS;
  641. RtlInitAnsiString(&AnsiString, lpFileName);
  642. AnsiString.Length = AnsiString.MaximumLength; // include terminal nul
  643. if (!NT_SUCCESS(Status = SpAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE)))
  644. goto NtExit;
  645. Success = ( SpSetFileAttributesW(
  646. UnicodeString.Buffer,
  647. dwFileAttributes
  648. )
  649. );
  650. if (!Success)
  651. goto Exit;
  652. Success = TRUE;
  653. Exit:
  654. SpFreeStringW(&UnicodeString);
  655. return Success;
  656. NtExit:
  657. SpSetLastWin32ErrorAndNtStatusFromNtStatus(Status);
  658. goto Exit;
  659. }
  660. BOOL
  661. APIENTRY
  662. SpSetFileAttributesW(
  663. PCWSTR lpFileName,
  664. DWORD dwFileAttributes
  665. )
  666. {
  667. BOOL Success = FALSE;
  668. NTSTATUS Status = STATUS_SUCCESS;
  669. HANDLE Handle;
  670. UNICODE_STRING FileName;
  671. OBJECT_ATTRIBUTES ObjectAttributes = { sizeof(ObjectAttributes), NULL, &FileName, OBJ_CASE_INSENSITIVE };
  672. IO_STATUS_BLOCK IoStatusBlock;
  673. FILE_BASIC_INFORMATION BasicInfo = { 0 };
  674. RtlInitUnicodeString(&FileName, lpFileName);
  675. //
  676. // Open the file inhibiting the reparse behavior.
  677. //
  678. Status = ZwOpenFile(
  679. &Handle,
  680. (ACCESS_MASK)FILE_WRITE_ATTRIBUTES | SYNCHRONIZE,
  681. &ObjectAttributes,
  682. &IoStatusBlock,
  683. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  684. FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REPARSE_POINT
  685. );
  686. if ( !NT_SUCCESS(Status) ) {
  687. SpSetLastWin32ErrorAndNtStatusFromNtStatus(Status);
  688. goto Exit;
  689. }
  690. //
  691. // Set the attributes
  692. //
  693. BasicInfo.FileAttributes = (dwFileAttributes & FILE_ATTRIBUTE_VALID_SET_FLAGS) | FILE_ATTRIBUTE_NORMAL;
  694. Status = ZwSetInformationFile(
  695. Handle,
  696. &IoStatusBlock,
  697. &BasicInfo,
  698. sizeof(BasicInfo),
  699. FileBasicInformation
  700. );
  701. ZwClose(Handle);
  702. if ( !NT_SUCCESS(Status) ) {
  703. SpSetLastWin32ErrorAndNtStatusFromNtStatus(Status);
  704. goto Exit;
  705. }
  706. Success = TRUE;
  707. Exit:
  708. return Success;
  709. }
  710. BOOL
  711. APIENTRY
  712. SpGetFileAttributesExA(
  713. PCSTR lpFileName,
  714. GET_FILEEX_INFO_LEVELS fInfoLevelId,
  715. PVOID lpFileInformation
  716. )
  717. {
  718. UNICODE_STRING UnicodeString = { 0 };
  719. ANSI_STRING AnsiString = { 0 };
  720. BOOL Success = FALSE;
  721. NTSTATUS Status = STATUS_SUCCESS;
  722. RtlInitAnsiString(&AnsiString, lpFileName);
  723. AnsiString.Length = AnsiString.MaximumLength; // include terminal nul
  724. if (!NT_SUCCESS(Status = SpAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE))) {
  725. KdPrintEx((
  726. DPFLTR_SETUP_ID,
  727. SpNtStatusToDbgPrintLevel(Status),
  728. "SETUP:"__FUNCTION__":SpAnsiStringToUnicodeString:0x%08lx\n",
  729. Status
  730. ));
  731. goto NtExit;
  732. }
  733. Success = SpGetFileAttributesExW(
  734. UnicodeString.Buffer,
  735. fInfoLevelId,
  736. lpFileInformation
  737. );
  738. Exit:
  739. SpFreeStringW(&UnicodeString);
  740. return Success;
  741. NtExit:
  742. SpSetLastWin32ErrorAndNtStatusFromNtStatus(Status);
  743. goto Exit;
  744. }
  745. BOOL
  746. APIENTRY
  747. SpGetFileAttributesExW(
  748. LPCWSTR lpFileName,
  749. GET_FILEEX_INFO_LEVELS fInfoLevelId,
  750. LPVOID lpFileInformation
  751. )
  752. // from base\win32\client\filemisc.c
  753. {
  754. NTSTATUS Status;
  755. UNICODE_STRING FileName;
  756. /*const*/ OBJECT_ATTRIBUTES ObjectAttributes = { sizeof(ObjectAttributes), NULL, &FileName, OBJ_CASE_INSENSITIVE };
  757. FILE_NETWORK_OPEN_INFORMATION NetworkInfo;
  758. RtlInitUnicodeString(&FileName, lpFileName);
  759. if ( !RTL_SOFT_VERIFY(fInfoLevelId == GetFileExInfoStandard )) {
  760. SpSetLastWin32Error(ERROR_INVALID_PARAMETER);
  761. return FALSE;
  762. }
  763. Status = ZwQueryFullAttributesFile( &ObjectAttributes, &NetworkInfo );
  764. if ( NT_SUCCESS(Status) ) {
  765. const LPWIN32_FILE_ATTRIBUTE_DATA AttributeData = (LPWIN32_FILE_ATTRIBUTE_DATA)lpFileInformation;
  766. AttributeData->dwFileAttributes = NetworkInfo.FileAttributes;
  767. AttributeData->ftCreationTime = *(PFILETIME)&NetworkInfo.CreationTime;
  768. AttributeData->ftLastAccessTime = *(PFILETIME)&NetworkInfo.LastAccessTime;
  769. AttributeData->ftLastWriteTime = *(PFILETIME)&NetworkInfo.LastWriteTime;
  770. AttributeData->nFileSizeHigh = NetworkInfo.EndOfFile.HighPart;
  771. AttributeData->nFileSizeLow = (DWORD)NetworkInfo.EndOfFile.LowPart;
  772. return TRUE;
  773. }
  774. else {
  775. if (Status != STATUS_OBJECT_NAME_NOT_FOUND) {
  776. KdPrintEx((
  777. DPFLTR_SETUP_ID,
  778. SpNtStatusToDbgPrintLevel(Status),
  779. "SETUP:"__FUNCTION__":ZwQueryFullAttributesFile:0x%08lx\n",
  780. Status
  781. ));
  782. }
  783. SpSetLastWin32ErrorAndNtStatusFromNtStatus(Status);
  784. return FALSE;
  785. }
  786. }