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.

1134 lines
30 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. //
  30. // fold with rtl..
  31. //
  32. extern const UNICODE_STRING SpWin32NtRoot = RTL_CONSTANT_STRING( L"\\\\?" );
  33. extern const UNICODE_STRING SpWin32NtRootSlash = RTL_CONSTANT_STRING( L"\\\\?\\" );
  34. extern const UNICODE_STRING SpWin32NtUncRoot = RTL_CONSTANT_STRING( L"\\\\?\\UNC" );
  35. extern const UNICODE_STRING SpWin32NtUncRootSlash = RTL_CONSTANT_STRING( L"\\\\?\\UNC\\" );
  36. NTSTATUS
  37. SpConvertWin32FileOpenOrCreateToNtFileOpenOrCreate(
  38. ULONG Win32OpenOrCreate,
  39. ULONG* NtOpenOrCreate
  40. )
  41. {
  42. //
  43. // there's no pattern here and the values all overlap
  44. // yuck; this is copied from kernel32 source
  45. //
  46. *NtOpenOrCreate = ~0;
  47. switch (Win32OpenOrCreate)
  48. {
  49. default:
  50. return STATUS_INVALID_PARAMETER;
  51. case CREATE_NEW:
  52. *NtOpenOrCreate = FILE_CREATE;
  53. break;
  54. case CREATE_ALWAYS:
  55. *NtOpenOrCreate = FILE_OVERWRITE_IF;
  56. break;
  57. case OPEN_EXISTING:
  58. *NtOpenOrCreate = FILE_OPEN;
  59. break;
  60. case OPEN_ALWAYS:
  61. *NtOpenOrCreate = FILE_OPEN_IF;
  62. break;
  63. case TRUNCATE_EXISTING :
  64. *NtOpenOrCreate = FILE_OPEN;
  65. }
  66. return STATUS_SUCCESS;
  67. }
  68. NTSTATUS
  69. SpConvertWin32FileAccessToNtFileAccess(
  70. ULONG Win32FileAccess,
  71. ULONG* NtFileAccess
  72. )
  73. {
  74. //
  75. // ZwCreateFile oddities require us to do this conversion, or at least
  76. // to add in SYNCHRONIZE.
  77. //
  78. *NtFileAccess =
  79. (Win32FileAccess & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL))
  80. | ((Win32FileAccess & GENERIC_READ) ? FILE_GENERIC_READ : 0)
  81. | ((Win32FileAccess & GENERIC_WRITE) ? FILE_GENERIC_WRITE : 0)
  82. | ((Win32FileAccess & GENERIC_EXECUTE) ? FILE_GENERIC_EXECUTE : 0)
  83. | ((Win32FileAccess & GENERIC_ALL) ? FILE_ALL_ACCESS : 0)
  84. | SYNCHRONIZE
  85. ;
  86. return STATUS_SUCCESS;
  87. }
  88. NTSTATUS
  89. SpConvertWin32FileShareToNtFileShare(
  90. ULONG Win32FileShare,
  91. ULONG* NtFileShare
  92. )
  93. {
  94. *NtFileShare = Win32FileShare;
  95. return STATUS_SUCCESS;
  96. }
  97. NTSTATUS
  98. SpGetLastNtStatus(
  99. VOID
  100. )
  101. {
  102. return NtCurrentTeb()->LastStatusValue;
  103. }
  104. ULONG
  105. WINAPI
  106. SpGetLastWin32Error(
  107. VOID
  108. )
  109. {
  110. return NtCurrentTeb()->LastErrorValue;
  111. }
  112. VOID
  113. WINAPI
  114. SpSetLastWin32Error(
  115. ULONG Error
  116. )
  117. {
  118. #if DBG
  119. if (NtCurrentTeb()->LastErrorValue != Error)
  120. #endif
  121. NtCurrentTeb()->LastErrorValue = Error;
  122. }
  123. VOID
  124. SpSetLastWin32ErrorAndNtStatusFromNtStatus(
  125. NTSTATUS Status
  126. )
  127. {
  128. SpSetLastWin32Error(RtlNtStatusToDosError(Status));
  129. }
  130. HANDLE
  131. SpNtCreateFileW(
  132. PCUNICODE_STRING ConstantPath,
  133. IN ULONG FileAccess,
  134. IN ULONG FileShare,
  135. IN LPSECURITY_ATTRIBUTES SecurityAttributes,
  136. IN ULONG Win32FileOpenOrCreate,
  137. IN ULONG FlagsAndAttributes,
  138. IN HANDLE TemplateFile
  139. )
  140. /*++
  141. Subset:
  142. no security
  143. no directories
  144. no async
  145. no console
  146. no ea (extended attributes)
  147. --*/
  148. {
  149. NTSTATUS Status = STATUS_SUCCESS;
  150. IO_STATUS_BLOCK IoStatusBlock = { 0 };
  151. HANDLE FileHandle = INVALID_HANDLE_VALUE;
  152. ULONG NtFileOpenOrCreate = 0;
  153. FILE_ALLOCATION_INFORMATION AllocationInfo = { 0 };
  154. PUNICODE_STRING Path = RTL_CONST_CAST(PUNICODE_STRING)(ConstantPath);
  155. /*const*/OBJECT_ATTRIBUTES ObjectAttributes = { sizeof(ObjectAttributes), NULL, Path, OBJ_CASE_INSENSITIVE };
  156. ASSERT(TemplateFile == NULL);
  157. ASSERT(SecurityAttributes == NULL);
  158. ASSERT((FlagsAndAttributes & ~(FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_ARCHIVE)) == 0);
  159. if (!NT_SUCCESS(Status = SpConvertWin32FileAccessToNtFileAccess(FileAccess, &FileAccess)))
  160. goto NtExit;
  161. if (!NT_SUCCESS(Status = SpConvertWin32FileOpenOrCreateToNtFileOpenOrCreate(Win32FileOpenOrCreate, &NtFileOpenOrCreate)))
  162. goto NtExit;
  163. if (!NT_SUCCESS(Status = SpConvertWin32FileShareToNtFileShare(FileShare, &FileShare)))
  164. goto NtExit;
  165. Status =
  166. ZwCreateFile(
  167. &FileHandle,
  168. FileAccess
  169. | SYNCHRONIZE // like kernel32
  170. | FILE_READ_ATTRIBUTES, // like kernel32
  171. &ObjectAttributes,
  172. &IoStatusBlock,
  173. NULL, // AllocationSize
  174. FlagsAndAttributes,
  175. FileShare,
  176. NtFileOpenOrCreate,
  177. FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE,
  178. NULL, // EaBuffer,
  179. 0 // EaLength
  180. );
  181. // based closely on kernel32
  182. if ( !NT_SUCCESS(Status) ) {
  183. SpSetLastWin32ErrorAndNtStatusFromNtStatus(Status);
  184. if ( Status == STATUS_OBJECT_NAME_COLLISION ) {
  185. SpSetLastWin32Error(ERROR_FILE_EXISTS);
  186. }
  187. else if ( Status == STATUS_FILE_IS_A_DIRECTORY ) {
  188. if (Path->Length != 0 && Path->Buffer[Path->Length / sizeof(Path->Buffer[0])] == '\\') {
  189. SpSetLastWin32Error(ERROR_PATH_NOT_FOUND);
  190. }
  191. else {
  192. SpSetLastWin32Error(ERROR_ACCESS_DENIED);
  193. }
  194. }
  195. FileHandle = INVALID_HANDLE_VALUE;
  196. goto Exit;
  197. }
  198. //
  199. // if NT returns supersede/overwritten, it means that a create_always, openalways
  200. // found an existing copy of the file. In this case ERROR_ALREADY_EXISTS is returned
  201. //
  202. if ( (Win32FileOpenOrCreate == CREATE_ALWAYS && IoStatusBlock.Information == FILE_OVERWRITTEN) ||
  203. (Win32FileOpenOrCreate == OPEN_ALWAYS && IoStatusBlock.Information == FILE_OPENED) ) {
  204. SpSetLastWin32Error(ERROR_ALREADY_EXISTS);
  205. }
  206. else {
  207. SpSetLastWin32Error(0);
  208. }
  209. //
  210. // Truncate the file if required
  211. //
  212. if ( Win32FileOpenOrCreate == TRUNCATE_EXISTING) {
  213. AllocationInfo.AllocationSize.QuadPart = 0;
  214. Status = ZwSetInformationFile(
  215. FileHandle,
  216. &IoStatusBlock,
  217. &AllocationInfo,
  218. sizeof(AllocationInfo),
  219. FileAllocationInformation
  220. );
  221. if ( !NT_SUCCESS(Status) ) {
  222. ZwClose(FileHandle);
  223. FileHandle = INVALID_HANDLE_VALUE;
  224. SpSetLastWin32ErrorAndNtStatusFromNtStatus(Status);
  225. }
  226. }
  227. Exit:
  228. return FileHandle;
  229. NtExit:
  230. SpSetLastWin32ErrorAndNtStatusFromNtStatus(Status);
  231. goto Exit;
  232. }
  233. HANDLE
  234. WINAPI
  235. SpWin32CreateFileW(
  236. IN PCWSTR FileName,
  237. IN ULONG FileAccess,
  238. IN ULONG FileShare,
  239. IN LPSECURITY_ATTRIBUTES SecurityAttributes,
  240. IN ULONG FileOpenOrCreate,
  241. IN ULONG FlagsAndAttributes,
  242. IN HANDLE TemplateFile
  243. )
  244. {
  245. HANDLE FileHandle = INVALID_HANDLE_VALUE;
  246. UNICODE_STRING UnicodeString = { 0 };
  247. NTSTATUS Status = STATUS_SUCCESS;
  248. RtlInitUnicodeString(&UnicodeString, FileName);
  249. FileHandle = SpNtCreateFileW(&UnicodeString, FileAccess, FileShare, SecurityAttributes, FileOpenOrCreate, FlagsAndAttributes, TemplateFile);
  250. ASSERT (FileHandle); // never NULL
  251. if (FileHandle == INVALID_HANDLE_VALUE)
  252. goto Exit;
  253. Exit:
  254. return FileHandle;
  255. }
  256. HANDLE
  257. WINAPI
  258. SpWin32CreateFileA(
  259. IN PCSTR FileName,
  260. IN ULONG FileAccess,
  261. IN ULONG FileShare,
  262. IN LPSECURITY_ATTRIBUTES SecurityAttributes,
  263. IN ULONG FileOpenOrCreate,
  264. IN ULONG dwFlagsAndAttributes,
  265. IN HANDLE TemplateFile
  266. )
  267. {
  268. ANSI_STRING AnsiString = { 0 };
  269. NTSTATUS Status = STATUS_SUCCESS;
  270. HANDLE Handle = INVALID_HANDLE_VALUE;
  271. UNICODE_STRING UnicodeString = { 0 };
  272. RtlInitAnsiString(&AnsiString, FileName);
  273. AnsiString.Length = AnsiString.MaximumLength; // include terminal nul
  274. if (!NT_SUCCESS(Status = SpAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE)))
  275. goto NtExit;
  276. UnicodeString.Length -= sizeof(UnicodeString.Buffer[0]); // remove terminal nul
  277. Handle = SpNtCreateFileW(&UnicodeString, FileAccess, FileShare, SecurityAttributes, FileOpenOrCreate, dwFlagsAndAttributes, TemplateFile);
  278. Exit:
  279. SpFreeStringW(&UnicodeString);
  280. KdPrintEx((
  281. DPFLTR_SETUP_ID,
  282. SpHandleToDbgPrintLevel(Handle),
  283. "SETUP:"__FUNCTION__"(%s) exiting with FileHandle: %p Status:0x%08lx Error:%d\n",
  284. FileName, Handle, SpGetLastNtStatus(), SpGetLastWin32Error()
  285. ));
  286. return Handle;
  287. NtExit:
  288. SpSetLastWin32ErrorAndNtStatusFromNtStatus(Status);
  289. goto Exit;
  290. }
  291. BOOL
  292. WINAPI
  293. SpWin32ReadFile(
  294. HANDLE hFile,
  295. PVOID lpBuffer,
  296. ULONG nNumberOfBytesToRead,
  297. ULONG* lpNumberOfBytesRead,
  298. LPOVERLAPPED lpOverlapped
  299. )
  300. {
  301. NTSTATUS Status;
  302. IO_STATUS_BLOCK IoStatusBlock;
  303. ASSERT(!ARGUMENT_PRESENT(lpOverlapped));
  304. if ( ARGUMENT_PRESENT(lpNumberOfBytesRead) ) {
  305. *lpNumberOfBytesRead = 0;
  306. }
  307. Status = ZwReadFile(
  308. hFile,
  309. NULL,
  310. NULL,
  311. NULL,
  312. &IoStatusBlock,
  313. lpBuffer,
  314. nNumberOfBytesToRead,
  315. NULL,
  316. NULL
  317. );
  318. if ( Status == STATUS_PENDING) {
  319. // Operation must complete before return & IoStatusBlock destroyed
  320. Status = ZwWaitForSingleObject( hFile, FALSE, NULL );
  321. if ( NT_SUCCESS(Status)) {
  322. Status = IoStatusBlock.Status;
  323. }
  324. }
  325. if ( NT_SUCCESS(Status) ) {
  326. *lpNumberOfBytesRead = (ULONG)IoStatusBlock.Information;
  327. return TRUE;
  328. }
  329. else
  330. if (Status == STATUS_END_OF_FILE) {
  331. *lpNumberOfBytesRead = 0;
  332. return TRUE;
  333. }
  334. else {
  335. if ( NT_WARNING(Status) ) {
  336. *lpNumberOfBytesRead = (ULONG)IoStatusBlock.Information;
  337. }
  338. SpSetLastWin32ErrorAndNtStatusFromNtStatus(Status);
  339. return FALSE;
  340. }
  341. }
  342. BOOL
  343. WINAPI
  344. SpWin32WriteFile(
  345. HANDLE hFile,
  346. CONST VOID* lpBuffer,
  347. ULONG nNumberOfBytesToWrite,
  348. ULONG* lpNumberOfBytesWritten,
  349. LPOVERLAPPED lpOverlapped
  350. )
  351. {
  352. NTSTATUS Status;
  353. IO_STATUS_BLOCK IoStatusBlock;
  354. PPEB Peb;
  355. ASSERT(!ARGUMENT_PRESENT( lpOverlapped ) );
  356. if ( ARGUMENT_PRESENT(lpNumberOfBytesWritten) ) {
  357. *lpNumberOfBytesWritten = 0;
  358. }
  359. Status = ZwWriteFile(
  360. hFile,
  361. NULL,
  362. NULL,
  363. NULL,
  364. &IoStatusBlock,
  365. RTL_CONST_CAST(PVOID)(lpBuffer),
  366. nNumberOfBytesToWrite,
  367. NULL,
  368. NULL
  369. );
  370. if ( Status == STATUS_PENDING) {
  371. // Operation must complete before return & IoStatusBlock destroyed
  372. Status = ZwWaitForSingleObject( hFile, FALSE, NULL );
  373. if ( NT_SUCCESS(Status)) {
  374. Status = IoStatusBlock.Status;
  375. }
  376. }
  377. if ( NT_SUCCESS(Status)) {
  378. *lpNumberOfBytesWritten = (ULONG)IoStatusBlock.Information;
  379. return TRUE;
  380. }
  381. else {
  382. if ( NT_WARNING(Status) ) {
  383. *lpNumberOfBytesWritten = (ULONG)IoStatusBlock.Information;
  384. }
  385. SpSetLastWin32ErrorAndNtStatusFromNtStatus(Status);
  386. return FALSE;
  387. }
  388. }
  389. ULONG
  390. WINAPI
  391. SpSetFilePointer(
  392. HANDLE hFile,
  393. LONG lDistanceToMove,
  394. LONG* lpDistanceToMoveHigh,
  395. ULONG dwMoveMethod
  396. )
  397. {
  398. NTSTATUS Status;
  399. IO_STATUS_BLOCK IoStatusBlock;
  400. FILE_POSITION_INFORMATION CurrentPosition;
  401. FILE_STANDARD_INFORMATION StandardInfo;
  402. LARGE_INTEGER Large;
  403. if (ARGUMENT_PRESENT(lpDistanceToMoveHigh)) {
  404. Large.HighPart = *lpDistanceToMoveHigh;
  405. Large.LowPart = lDistanceToMove;
  406. }
  407. else {
  408. Large.QuadPart = lDistanceToMove;
  409. }
  410. switch (dwMoveMethod) {
  411. case FILE_BEGIN :
  412. CurrentPosition.CurrentByteOffset = Large;
  413. break;
  414. case FILE_CURRENT :
  415. //
  416. // Get the current position of the file pointer
  417. //
  418. Status = ZwQueryInformationFile(
  419. hFile,
  420. &IoStatusBlock,
  421. &CurrentPosition,
  422. sizeof(CurrentPosition),
  423. FilePositionInformation
  424. );
  425. if ( !NT_SUCCESS(Status) ) {
  426. SpSetLastWin32ErrorAndNtStatusFromNtStatus(Status);
  427. return (ULONG)(LONG)-1;
  428. }
  429. CurrentPosition.CurrentByteOffset.QuadPart += Large.QuadPart;
  430. break;
  431. case FILE_END :
  432. Status = ZwQueryInformationFile(
  433. hFile,
  434. &IoStatusBlock,
  435. &StandardInfo,
  436. sizeof(StandardInfo),
  437. FileStandardInformation
  438. );
  439. if ( !NT_SUCCESS(Status) ) {
  440. SpSetLastWin32ErrorAndNtStatusFromNtStatus(Status);
  441. return (ULONG)(LONG)-1;
  442. }
  443. CurrentPosition.CurrentByteOffset.QuadPart =
  444. StandardInfo.EndOfFile.QuadPart + Large.QuadPart;
  445. break;
  446. default:
  447. SpSetLastWin32Error(ERROR_INVALID_PARAMETER);
  448. return (ULONG)(LONG)-1;
  449. break;
  450. }
  451. //
  452. // If the resulting file position is negative, or if the app is not
  453. // prepared for greater than
  454. // than 32 bits than fail
  455. //
  456. if ( CurrentPosition.CurrentByteOffset.QuadPart < 0 ) {
  457. SpSetLastWin32Error(ERROR_NEGATIVE_SEEK);
  458. return (ULONG)(LONG)-1;
  459. }
  460. if ( !ARGUMENT_PRESENT(lpDistanceToMoveHigh) &&
  461. (CurrentPosition.CurrentByteOffset.HighPart & MAXLONG) ) {
  462. SpSetLastWin32Error(ERROR_INVALID_PARAMETER);
  463. return (ULONG)(LONG)-1;
  464. }
  465. //
  466. // Set the current file position
  467. //
  468. Status = ZwSetInformationFile(
  469. hFile,
  470. &IoStatusBlock,
  471. &CurrentPosition,
  472. sizeof(CurrentPosition),
  473. FilePositionInformation
  474. );
  475. if ( NT_SUCCESS(Status) ) {
  476. if (ARGUMENT_PRESENT(lpDistanceToMoveHigh)){
  477. *lpDistanceToMoveHigh = CurrentPosition.CurrentByteOffset.HighPart;
  478. }
  479. if ( CurrentPosition.CurrentByteOffset.LowPart == -1 ) {
  480. SpSetLastWin32Error(0);
  481. }
  482. return CurrentPosition.CurrentByteOffset.LowPart;
  483. }
  484. else {
  485. SpSetLastWin32ErrorAndNtStatusFromNtStatus(Status);
  486. if (ARGUMENT_PRESENT(lpDistanceToMoveHigh)){
  487. *lpDistanceToMoveHigh = -1;
  488. }
  489. return (ULONG)(LONG)-1;
  490. }
  491. }
  492. BOOL
  493. WINAPI
  494. SpWin32DeleteFileA(
  495. PCSTR FileName
  496. )
  497. {
  498. BOOL Success = FALSE;
  499. NTSTATUS Status = STATUS_SUCCESS;
  500. ANSI_STRING AnsiString = { 0 };
  501. UNICODE_STRING UnicodeString = { 0 };
  502. if (FileName == NULL || FileName[0] == 0) {
  503. KdPrintEx((
  504. DPFLTR_SETUP_ID,
  505. DPFLTR_TRACE_LEVEL,
  506. "SETUP:"__FUNCTION__"(NULL or empty), claiming success\n"
  507. ));
  508. Success = TRUE;
  509. goto Exit;
  510. }
  511. RtlInitAnsiString(&AnsiString, FileName);
  512. AnsiString.Length = AnsiString.MaximumLength; // include terminal nul
  513. Status = SpAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE);
  514. if (!NT_SUCCESS(Status))
  515. goto NtExit;
  516. Status = SpDeleteFile(UnicodeString.Buffer, NULL, NULL);
  517. if (!NT_SUCCESS(Status))
  518. goto NtExit;
  519. Success = TRUE;
  520. Exit:
  521. SpFreeStringW(&UnicodeString);
  522. KdPrintEx((
  523. DPFLTR_SETUP_ID,
  524. SpBoolToDbgPrintLevel(Success),
  525. "SETUP:"__FUNCTION__"(%s) exiting with Success: %s Status:0x%08lx Error:%d\n",
  526. FileName, SpBooleanToStringA(Success), SpGetLastNtStatus(), SpGetLastWin32Error()
  527. ));
  528. return Success;
  529. NtExit:
  530. SpSetLastWin32ErrorAndNtStatusFromNtStatus(Status);
  531. goto Exit;
  532. }
  533. //
  534. // move this to ntrtl
  535. //
  536. #define AlmostTwoSeconds (2*1000*1000*10 - 1)
  537. BOOL
  538. APIENTRY
  539. SpFileTimeToDosDateTime(
  540. CONST FILETIME *lpFileTime,
  541. LPWORD lpFatDate,
  542. LPWORD lpFatTime
  543. )
  544. {
  545. TIME_FIELDS TimeFields;
  546. LARGE_INTEGER FileTime;
  547. FileTime.LowPart = lpFileTime->dwLowDateTime;
  548. FileTime.HighPart = lpFileTime->dwHighDateTime;
  549. FileTime.QuadPart = FileTime.QuadPart + (LONGLONG)AlmostTwoSeconds;
  550. if ( FileTime.QuadPart < 0 ) {
  551. SpSetLastWin32Error(ERROR_INVALID_PARAMETER);
  552. return FALSE;
  553. }
  554. RtlTimeToTimeFields(&FileTime, &TimeFields);
  555. if (TimeFields.Year < 1980 || TimeFields.Year > 2107) {
  556. SpSetLastWin32ErrorAndNtStatusFromNtStatus(STATUS_INVALID_PARAMETER);
  557. return FALSE;
  558. }
  559. *lpFatDate = (WORD)( ((USHORT)(TimeFields.Year-(CSHORT)1980) << 9) |
  560. ((USHORT)TimeFields.Month << 5) |
  561. (USHORT)TimeFields.Day
  562. );
  563. *lpFatTime = (WORD)( ((USHORT)TimeFields.Hour << 11) |
  564. ((USHORT)TimeFields.Minute << 5) |
  565. ((USHORT)TimeFields.Second >> 1)
  566. );
  567. return TRUE;
  568. }
  569. BOOL
  570. APIENTRY
  571. SpDosDateTimeToFileTime(
  572. WORD wFatDate,
  573. WORD wFatTime,
  574. LPFILETIME lpFileTime
  575. )
  576. {
  577. TIME_FIELDS TimeFields;
  578. LARGE_INTEGER FileTime;
  579. TimeFields.Year = (CSHORT)((wFatDate & 0xFE00) >> 9)+(CSHORT)1980;
  580. TimeFields.Month = (CSHORT)((wFatDate & 0x01E0) >> 5);
  581. TimeFields.Day = (CSHORT)((wFatDate & 0x001F) >> 0);
  582. TimeFields.Hour = (CSHORT)((wFatTime & 0xF800) >> 11);
  583. TimeFields.Minute = (CSHORT)((wFatTime & 0x07E0) >> 5);
  584. TimeFields.Second = (CSHORT)((wFatTime & 0x001F) << 1);
  585. TimeFields.Milliseconds = 0;
  586. if (RtlTimeFieldsToTime(&TimeFields,&FileTime)) {
  587. lpFileTime->dwLowDateTime = FileTime.LowPart;
  588. lpFileTime->dwHighDateTime = FileTime.HighPart;
  589. return TRUE;
  590. }
  591. else {
  592. SpSetLastWin32ErrorAndNtStatusFromNtStatus(STATUS_INVALID_PARAMETER);
  593. return FALSE;
  594. }
  595. }
  596. BOOL
  597. WINAPI
  598. SpFileTimeToLocalFileTime(
  599. CONST FILETIME *lpFileTime,
  600. LPFILETIME lpLocalFileTime
  601. )
  602. {
  603. //
  604. // just return it unchanged
  605. // UTC is good
  606. //
  607. *lpLocalFileTime = *lpFileTime;
  608. return TRUE;
  609. }
  610. BOOL
  611. WINAPI
  612. SpLocalFileTimeToFileTime(
  613. CONST FILETIME *lpLocalFileTime,
  614. LPFILETIME lpFileTime
  615. )
  616. {
  617. //
  618. // just return it unchanged
  619. // UTC is good
  620. //
  621. *lpFileTime = *lpLocalFileTime;
  622. return TRUE;
  623. }
  624. BOOL
  625. WINAPI
  626. SpSetFileTime(
  627. HANDLE hFile,
  628. CONST FILETIME *lpCreationTime,
  629. CONST FILETIME *lpLastAccessTime,
  630. CONST FILETIME *lpLastWriteTime
  631. )
  632. {
  633. NTSTATUS Status;
  634. IO_STATUS_BLOCK IoStatusBlock;
  635. FILE_BASIC_INFORMATION BasicInfo = { 0 };
  636. //
  637. // For each time value that is specified, copy it to the I/O system
  638. // record.
  639. //
  640. if (ARGUMENT_PRESENT( lpCreationTime )) {
  641. BasicInfo.CreationTime.LowPart = lpCreationTime->dwLowDateTime;
  642. BasicInfo.CreationTime.HighPart = lpCreationTime->dwHighDateTime;
  643. }
  644. if (ARGUMENT_PRESENT( lpLastAccessTime )) {
  645. BasicInfo.LastAccessTime.LowPart = lpLastAccessTime->dwLowDateTime;
  646. BasicInfo.LastAccessTime.HighPart = lpLastAccessTime->dwHighDateTime;
  647. }
  648. if (ARGUMENT_PRESENT( lpLastWriteTime )) {
  649. BasicInfo.LastWriteTime.LowPart = lpLastWriteTime->dwLowDateTime;
  650. BasicInfo.LastWriteTime.HighPart = lpLastWriteTime->dwHighDateTime;
  651. }
  652. //
  653. // Set the requested times.
  654. //
  655. Status = ZwSetInformationFile(
  656. hFile,
  657. &IoStatusBlock,
  658. &BasicInfo,
  659. sizeof(BasicInfo),
  660. FileBasicInformation
  661. );
  662. if ( NT_SUCCESS(Status) ) {
  663. return TRUE;
  664. }
  665. else {
  666. SpSetLastWin32ErrorAndNtStatusFromNtStatus(Status);
  667. return FALSE;
  668. }
  669. }
  670. BOOL
  671. APIENTRY
  672. SpSetFileAttributesA(
  673. PCSTR lpFileName,
  674. DWORD dwFileAttributes
  675. )
  676. {
  677. UNICODE_STRING UnicodeString = { 0 };
  678. ANSI_STRING AnsiString = { 0 };
  679. BOOL Success = FALSE;
  680. NTSTATUS Status = STATUS_SUCCESS;
  681. RtlInitAnsiString(&AnsiString, lpFileName);
  682. AnsiString.Length = AnsiString.MaximumLength; // include terminal nul
  683. if (!NT_SUCCESS(Status = SpAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE)))
  684. goto NtExit;
  685. Success = ( SpSetFileAttributesW(
  686. UnicodeString.Buffer,
  687. dwFileAttributes
  688. )
  689. );
  690. if (!Success)
  691. goto Exit;
  692. Success = TRUE;
  693. Exit:
  694. SpFreeStringW(&UnicodeString);
  695. return Success;
  696. NtExit:
  697. SpSetLastWin32ErrorAndNtStatusFromNtStatus(Status);
  698. goto Exit;
  699. }
  700. BOOL
  701. APIENTRY
  702. SpSetFileAttributesW(
  703. PCWSTR lpFileName,
  704. DWORD dwFileAttributes
  705. )
  706. {
  707. BOOL Success = FALSE;
  708. NTSTATUS Status = STATUS_SUCCESS;
  709. HANDLE Handle;
  710. UNICODE_STRING FileName;
  711. OBJECT_ATTRIBUTES ObjectAttributes = { sizeof(ObjectAttributes), NULL, &FileName, OBJ_CASE_INSENSITIVE };
  712. IO_STATUS_BLOCK IoStatusBlock;
  713. FILE_BASIC_INFORMATION BasicInfo = { 0 };
  714. RtlInitUnicodeString(&FileName, lpFileName);
  715. //
  716. // Open the file inhibiting the reparse behavior.
  717. //
  718. Status = ZwOpenFile(
  719. &Handle,
  720. (ACCESS_MASK)FILE_WRITE_ATTRIBUTES | SYNCHRONIZE,
  721. &ObjectAttributes,
  722. &IoStatusBlock,
  723. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  724. FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REPARSE_POINT
  725. );
  726. if ( !NT_SUCCESS(Status) ) {
  727. SpSetLastWin32ErrorAndNtStatusFromNtStatus(Status);
  728. goto Exit;
  729. }
  730. //
  731. // Set the attributes
  732. //
  733. BasicInfo.FileAttributes = (dwFileAttributes & FILE_ATTRIBUTE_VALID_SET_FLAGS) | FILE_ATTRIBUTE_NORMAL;
  734. Status = ZwSetInformationFile(
  735. Handle,
  736. &IoStatusBlock,
  737. &BasicInfo,
  738. sizeof(BasicInfo),
  739. FileBasicInformation
  740. );
  741. ZwClose(Handle);
  742. if ( !NT_SUCCESS(Status) ) {
  743. SpSetLastWin32ErrorAndNtStatusFromNtStatus(Status);
  744. goto Exit;
  745. }
  746. Success = TRUE;
  747. Exit:
  748. return Success;
  749. }
  750. NTSTATUS
  751. SpAllocateLocallyUniqueId(
  752. PLUID Luid
  753. )
  754. /*
  755. hack until ZwAllocateLocallyUniqueId is exported
  756. */
  757. {
  758. static LUID Counter = { 0, 0 };
  759. //
  760. // This does not actually correctly deal with wrapperaround in a multithreaded environment.
  761. // That's ok with us, and we can switch to ZwAllocateLocallyUniqueId.
  762. //
  763. Luid->LowPart = InterlockedIncrement(&Counter.LowPart);
  764. if (Luid->LowPart == 0)
  765. Luid->HighPart = 0; /*InterlockedIncrement(&Counter.HighPart);*/
  766. else
  767. Luid->HighPart = 0; /*Counter.HighPart;*/
  768. return STATUS_SUCCESS;
  769. }
  770. #if 0
  771. UINT
  772. WINAPI
  773. SpWin32GetTempFileNameW(
  774. PCWSTR TempDirectory,
  775. PCWSTR Prefix, // oops, I forgot to handle this..
  776. UINT IgnoredNumber,
  777. PWSTR File
  778. )
  779. {
  780. NTSTATUS Status = STATUS_SUCCESS;
  781. LUID Luid = { 0 };
  782. UNICODE_STRING UnicodeString = { 0 };
  783. WCHAR LuidStringBuffer[sizeof(LUID) * CHAR_BIT];
  784. UNICODE_STRING LuidString = { 0, sizeof(LuidStringBuffer), LuidStringBuffer };
  785. /*const*/ static UNICODE_STRING BackSlashString = RTL_CONSTANT_STRING(L"\\");
  786. LARGE_INTEGER LargeInteger = { 0 };
  787. UINT Length = 0;
  788. ASSERT(TempDirectory != NULL && TempDirectory[0] != 0);
  789. Status = SpAllocateLocallyUniqueId(&Luid);
  790. if (!NT_SUCCESS(Status)) {
  791. KdPrintEx((
  792. DPFLTR_SETUP_ID,
  793. SpNtStatusToDbgPrintLevel(Status),
  794. "SETUP:"__FUNCTION__":AllocateLocallyUniqueId:0x%08lx\n",
  795. Status
  796. ));
  797. goto NtExit;
  798. }
  799. LargeInteger.LowPart = Luid.LowPart;
  800. LargeInteger.HighPart = Luid.HighPart;
  801. UnicodeString.Buffer = File;
  802. UnicodeString.Length = 0;
  803. UnicodeString.MaximumLength = (CB_MAX_CAB_PATH - 1) * sizeof(UnicodeString.Buffer[0]);
  804. Status = RtlAppendUnicodeToString(&UnicodeString, TempDirectory);
  805. if (!NT_SUCCESS(Status)) {
  806. KdPrintEx((
  807. DPFLTR_SETUP_ID,
  808. SpNtStatusToDbgPrintLevel(Status),
  809. "SETUP:"__FUNCTION__":RtlAppendUnicodeToString:0x%08lx\n",
  810. Status
  811. ));
  812. goto NtExit;
  813. }
  814. if (UnicodeString.Buffer[UnicodeString.Length / sizeof(UnicodeString.Buffer[0]) - 1] != BackSlashString.Buffer[0]) {
  815. Status = RtlAppendUnicodeStringToString(&UnicodeString, &BackSlashString);
  816. if (!NT_SUCCESS(Status)) {
  817. KdPrintEx((
  818. DPFLTR_SETUP_ID,
  819. SpNtStatusToDbgPrintLevel(Status),
  820. "SETUP:"__FUNCTION__":RtlAppendUnicodeStringToString:0x%08lx\n",
  821. Status
  822. ));
  823. goto NtExit;
  824. }
  825. }
  826. Status = RtlInt64ToUnicodeString(LargeInteger.QuadPart, 10, &LuidString);
  827. if (!NT_SUCCESS(Status)) {
  828. KdPrintEx((
  829. DPFLTR_SETUP_ID,
  830. SpNtStatusToDbgPrintLevel(Status),
  831. "SETUP:"__FUNCTION__":RtlInt64ToUnicodeString:0x%08lx\n",
  832. Status
  833. ));
  834. goto NtExit;
  835. }
  836. Status = RtlAppendUnicodeStringToString(&UnicodeString, &LuidString);
  837. if (!NT_SUCCESS(Status)) {
  838. KdPrintEx((
  839. DPFLTR_SETUP_ID,
  840. SpNtStatusToDbgPrintLevel(Status),
  841. "SETUP:"__FUNCTION__":RtlAppendUnicodeStringToString:0x%08lx\n",
  842. Status
  843. ));
  844. goto NtExit;
  845. }
  846. Length = UnicodeString.Length / sizeof(UnicodeString.Buffer[0]);
  847. UnicodeString.Buffer[Length] = 0;
  848. Exit:
  849. KdPrintEx((
  850. DPFLTR_SETUP_ID,
  851. SpBoolToDbgPrintLevel(Length != 0),
  852. "SETUP:"__FUNCTION__":Length:0x%08lx\n",
  853. Length
  854. ));
  855. return Length;
  856. NtExit:
  857. SpSetLastWin32ErrorAndNtStatusFromNtStatus(Status);
  858. goto Exit;
  859. }
  860. #endif
  861. BOOL
  862. APIENTRY
  863. SpGetFileAttributesExA(
  864. PCSTR lpFileName,
  865. GET_FILEEX_INFO_LEVELS fInfoLevelId,
  866. PVOID lpFileInformation
  867. )
  868. {
  869. UNICODE_STRING UnicodeString = { 0 };
  870. ANSI_STRING AnsiString = { 0 };
  871. BOOL Success = FALSE;
  872. NTSTATUS Status = STATUS_SUCCESS;
  873. RtlInitAnsiString(&AnsiString, lpFileName);
  874. AnsiString.Length = AnsiString.MaximumLength; // include terminal nul
  875. if (!NT_SUCCESS(Status = SpAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE))) {
  876. KdPrintEx((
  877. DPFLTR_SETUP_ID,
  878. SpNtStatusToDbgPrintLevel(Status),
  879. "SETUP:"__FUNCTION__":SpAnsiStringToUnicodeString:0x%08lx\n",
  880. Status
  881. ));
  882. goto NtExit;
  883. }
  884. Success = SpGetFileAttributesExW(
  885. UnicodeString.Buffer,
  886. fInfoLevelId,
  887. lpFileInformation
  888. );
  889. Exit:
  890. SpFreeStringW(&UnicodeString);
  891. return Success;
  892. NtExit:
  893. SpSetLastWin32ErrorAndNtStatusFromNtStatus(Status);
  894. goto Exit;
  895. }
  896. #if 0
  897. NTSTATUS
  898. SpQueryFullAttributesFile(
  899. IN POBJECT_ATTRIBUTES ObjectAttributes,
  900. OUT PFILE_NETWORK_OPEN_INFORMATION FileInformation
  901. )
  902. /*
  903. cut dependency for now on NtQueryFullAttributesFile, since it isn't yet exported
  904. and I'm having problems with the kernel I built, use Jim's instead..
  905. */
  906. {
  907. HANDLE FileHandle = INVALID_HANDLE_VALUE;
  908. NTSTATUS Status = STATUS_SUCCESS;
  909. IO_STATUS_BLOCK IoStatusBlock;
  910. Status =
  911. ZwCreateFile(
  912. &FileHandle,
  913. FILE_READ_ATTRIBUTES,
  914. ObjectAttributes,
  915. &IoStatusBlock,
  916. NULL, // AllocationSize
  917. 0, // FileAttributes
  918. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  919. FILE_OPEN, // CreateDisposition
  920. FILE_OPEN_REPARSE_POINT | FILE_OPEN_FOR_BACKUP_INTENT, // CreateOptions
  921. NULL, // ea
  922. 0 // ea
  923. );
  924. if (!NT_SUCCESS(Status)) {
  925. KdPrintEx((
  926. DPFLTR_SETUP_ID,
  927. SpNtStatusToDbgPrintLevel(Status),
  928. "SETUP:"__FUNCTION__":ZwCreateFile:0x%08lx\n",
  929. Status
  930. ));
  931. goto Exit;
  932. }
  933. Status =
  934. ZwQueryInformationFile(
  935. FileHandle,
  936. &IoStatusBlock,
  937. FileInformation,
  938. sizeof(*FileInformation),
  939. FileNetworkOpenInformation
  940. );
  941. if (!NT_SUCCESS(Status)) {
  942. KdPrintEx((
  943. DPFLTR_SETUP_ID,
  944. SpNtStatusToDbgPrintLevel(Status),
  945. "SETUP:"__FUNCTION__":ZwQueryInformationFile:0x%08lx\n",
  946. Status
  947. ));
  948. goto Exit;
  949. }
  950. Status = STATUS_SUCCESS;
  951. Exit:
  952. if (FileHandle != INVALID_HANDLE_VALUE) {
  953. ZwClose(FileHandle);
  954. }
  955. return Status;
  956. }
  957. #else
  958. #define SpQueryFullAttributesFile ZwQueryFullAttributesFile
  959. #endif
  960. BOOL
  961. APIENTRY
  962. SpGetFileAttributesExW(
  963. LPCWSTR lpFileName,
  964. GET_FILEEX_INFO_LEVELS fInfoLevelId,
  965. LPVOID lpFileInformation
  966. )
  967. // from base\win32\client\filemisc.c
  968. {
  969. NTSTATUS Status;
  970. UNICODE_STRING FileName;
  971. /*const*/ OBJECT_ATTRIBUTES ObjectAttributes = { sizeof(ObjectAttributes), NULL, &FileName, OBJ_CASE_INSENSITIVE };
  972. FILE_NETWORK_OPEN_INFORMATION NetworkInfo;
  973. RtlInitUnicodeString(&FileName, lpFileName);
  974. if ( !RTL_SOFT_VERIFY(fInfoLevelId == GetFileExInfoStandard )) {
  975. SpSetLastWin32Error(ERROR_INVALID_PARAMETER);
  976. return FALSE;
  977. }
  978. Status = SpQueryFullAttributesFile( &ObjectAttributes, &NetworkInfo );
  979. if ( NT_SUCCESS(Status) ) {
  980. const LPWIN32_FILE_ATTRIBUTE_DATA AttributeData = (LPWIN32_FILE_ATTRIBUTE_DATA)lpFileInformation;
  981. AttributeData->dwFileAttributes = NetworkInfo.FileAttributes;
  982. AttributeData->ftCreationTime = *(PFILETIME)&NetworkInfo.CreationTime;
  983. AttributeData->ftLastAccessTime = *(PFILETIME)&NetworkInfo.LastAccessTime;
  984. AttributeData->ftLastWriteTime = *(PFILETIME)&NetworkInfo.LastWriteTime;
  985. AttributeData->nFileSizeHigh = NetworkInfo.EndOfFile.HighPart;
  986. AttributeData->nFileSizeLow = (DWORD)NetworkInfo.EndOfFile.LowPart;
  987. return TRUE;
  988. }
  989. else {
  990. if (Status != STATUS_OBJECT_NAME_NOT_FOUND) {
  991. KdPrintEx((
  992. DPFLTR_SETUP_ID,
  993. SpNtStatusToDbgPrintLevel(Status),
  994. "SETUP:"__FUNCTION__":SpQueryFullAttributesFile:0x%08lx\n",
  995. Status
  996. ));
  997. }
  998. SpSetLastWin32ErrorAndNtStatusFromNtStatus(Status);
  999. return FALSE;
  1000. }
  1001. }