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.

3288 lines
99 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. filehops.c
  5. Abstract:
  6. This module implements Win32 file handle APIs
  7. Author:
  8. Mark Lucovsky (markl) 25-Sep-1990
  9. Revision History:
  10. --*/
  11. #include "basedll.h"
  12. #include "winioctl.h"
  13. HANDLE
  14. WINAPI
  15. GetStdHandle(
  16. DWORD nStdHandle
  17. )
  18. {
  19. PPEB Peb;
  20. HANDLE rv;
  21. Peb = NtCurrentPeb();
  22. switch( nStdHandle ) {
  23. case STD_INPUT_HANDLE:
  24. rv = Peb->ProcessParameters->StandardInput;
  25. break;
  26. case STD_OUTPUT_HANDLE:
  27. rv = Peb->ProcessParameters->StandardOutput;
  28. break;
  29. case STD_ERROR_HANDLE:
  30. rv = Peb->ProcessParameters->StandardError;
  31. break;
  32. default:
  33. rv = INVALID_HANDLE_VALUE;
  34. break;
  35. }
  36. if ( rv == INVALID_HANDLE_VALUE ) {
  37. BaseSetLastNTError(STATUS_INVALID_HANDLE);
  38. }
  39. return rv;
  40. }
  41. BOOL
  42. WINAPI
  43. SetStdHandle(
  44. DWORD nStdHandle,
  45. HANDLE hHandle
  46. )
  47. {
  48. PPEB Peb;
  49. Peb = NtCurrentPeb();
  50. switch( nStdHandle ) {
  51. case STD_INPUT_HANDLE:
  52. Peb->ProcessParameters->StandardInput = hHandle;
  53. break;
  54. case STD_OUTPUT_HANDLE:
  55. Peb->ProcessParameters->StandardOutput = hHandle;
  56. break;
  57. case STD_ERROR_HANDLE:
  58. Peb->ProcessParameters->StandardError = hHandle;
  59. break;
  60. default:
  61. BaseSetLastNTError(STATUS_INVALID_HANDLE);
  62. return FALSE;
  63. }
  64. return( TRUE );
  65. }
  66. DWORD
  67. WINAPI
  68. GetFileType(
  69. HANDLE hFile
  70. )
  71. /*++
  72. Routine Description:
  73. GetFileType is used to determine the file type of the specified file.
  74. Arguments:
  75. hFile - Supplies an open handle to a file whose type is to be
  76. determined
  77. Return Value:
  78. FILE_TYPE_UNKNOWN - The type of the specified file is unknown.
  79. FILE_TYPE_DISK - The specified file is a disk file.
  80. FILE_TYPE_CHAR - The specified file is a character file (LPT,
  81. console...)
  82. FILE_TYPE_PIPE - The specified file is a pipe (either a named pipe or
  83. a pipe created by CreatePipe).
  84. --*/
  85. {
  86. NTSTATUS Status;
  87. FILE_FS_DEVICE_INFORMATION DeviceInformation;
  88. IO_STATUS_BLOCK IoStatusBlock;
  89. PPEB Peb;
  90. Peb = NtCurrentPeb();
  91. switch( HandleToUlong(hFile) ) {
  92. case STD_INPUT_HANDLE:
  93. hFile = Peb->ProcessParameters->StandardInput;
  94. break;
  95. case STD_OUTPUT_HANDLE:
  96. hFile = Peb->ProcessParameters->StandardOutput;
  97. break;
  98. case STD_ERROR_HANDLE:
  99. hFile = Peb->ProcessParameters->StandardError;
  100. break;
  101. }
  102. if (CONSOLE_HANDLE(hFile) && VerifyConsoleIoHandle(hFile)) {
  103. return( FILE_TYPE_CHAR );
  104. }
  105. if (hFile == NULL) {
  106. BaseSetLastNTError( STATUS_INVALID_HANDLE );
  107. return( FILE_TYPE_UNKNOWN );
  108. }
  109. //
  110. // If handle cannot be a real kernel handle we will fail
  111. // the call instead of calling with a bogus value NtQuery.
  112. //
  113. if (((ULONG_PTR)hFile & 0x01)) {
  114. BaseSetLastNTError( STATUS_INVALID_HANDLE );
  115. return( FILE_TYPE_UNKNOWN );
  116. }
  117. Status = NtQueryVolumeInformationFile( hFile,
  118. &IoStatusBlock,
  119. &DeviceInformation,
  120. sizeof( DeviceInformation ),
  121. FileFsDeviceInformation
  122. );
  123. if (!NT_SUCCESS( Status )) {
  124. BaseSetLastNTError( Status );
  125. return( FILE_TYPE_UNKNOWN );
  126. }
  127. switch( DeviceInformation.DeviceType ) {
  128. case FILE_DEVICE_SCREEN:
  129. case FILE_DEVICE_KEYBOARD:
  130. case FILE_DEVICE_MOUSE:
  131. case FILE_DEVICE_PARALLEL_PORT:
  132. case FILE_DEVICE_PRINTER:
  133. case FILE_DEVICE_SERIAL_PORT:
  134. case FILE_DEVICE_MODEM:
  135. case FILE_DEVICE_SOUND:
  136. case FILE_DEVICE_NULL:
  137. return( FILE_TYPE_CHAR );
  138. case FILE_DEVICE_CD_ROM:
  139. case FILE_DEVICE_CD_ROM_FILE_SYSTEM:
  140. case FILE_DEVICE_CONTROLLER:
  141. case FILE_DEVICE_DATALINK:
  142. case FILE_DEVICE_DFS:
  143. case FILE_DEVICE_DISK:
  144. case FILE_DEVICE_DISK_FILE_SYSTEM:
  145. case FILE_DEVICE_VIRTUAL_DISK:
  146. return( FILE_TYPE_DISK );
  147. case FILE_DEVICE_NAMED_PIPE:
  148. return( FILE_TYPE_PIPE );
  149. case FILE_DEVICE_NETWORK:
  150. case FILE_DEVICE_NETWORK_FILE_SYSTEM:
  151. case FILE_DEVICE_PHYSICAL_NETCARD:
  152. case FILE_DEVICE_TAPE:
  153. case FILE_DEVICE_TAPE_FILE_SYSTEM:
  154. case FILE_DEVICE_TRANSPORT:
  155. // NTRAID#589623-2002/03/28-earhart - changed to NTRAID marker
  156. // how should we handle tapes, network devices, etc...?
  157. case FILE_DEVICE_UNKNOWN:
  158. default:
  159. SetLastError( NO_ERROR );
  160. return( FILE_TYPE_UNKNOWN );
  161. }
  162. }
  163. BOOL
  164. WINAPI
  165. ReadFile(
  166. HANDLE hFile,
  167. LPVOID lpBuffer,
  168. DWORD nNumberOfBytesToRead,
  169. LPDWORD lpNumberOfBytesRead,
  170. LPOVERLAPPED lpOverlapped
  171. )
  172. /*++
  173. Routine Description:
  174. Data can be read from a file using ReadFile.
  175. This API is used to read data from a file. Data is read from the
  176. file from the position indicated by the file pointer. After the
  177. read completes, the file pointer is adjusted by the number of bytes
  178. actually read. A return value of TRUE coupled with a bytes read of
  179. 0 indicates that the file pointer was beyond the current end of the
  180. file at the time of the read.
  181. Arguments:
  182. hFile - Supplies an open handle to a file that is to be read. The
  183. file handle must have been created with GENERIC_READ access to
  184. the file.
  185. lpBuffer - Supplies the address of a buffer to receive the data read
  186. from the file.
  187. nNumberOfBytesToRead - Supplies the number of bytes to read from the
  188. file.
  189. lpNumberOfBytesRead - Returns the number of bytes read by this call.
  190. This parameter is always set to 0 before doing any IO or error
  191. checking.
  192. lpOverlapped - Optionally points to an OVERLAPPED structure to be used with the
  193. request. If NULL then the transfer starts at the current file position
  194. and ReadFile will not return until the operation completes.
  195. If the handle hFile was created without specifying FILE_FLAG_OVERLAPPED
  196. the file pointer is moved to the specified offset plus
  197. lpNumberOfBytesRead before ReadFile returns. ReadFile will wait for the
  198. request to complete before returning (it will not return
  199. ERROR_IO_PENDING).
  200. When FILE_FLAG_OVERLAPPED is specified, ReadFile may return
  201. ERROR_IO_PENDING to allow the calling function to continue processing
  202. while the operation completes. The event (or hFile if hEvent is NULL) will
  203. be set to the signalled state upon completion of the request.
  204. When the handle is created with FILE_FLAG_OVERLAPPED and lpOverlapped
  205. is set to NULL, ReadFile will return ERROR_INVALID_PARAMTER because
  206. the file offset is required.
  207. Return Value:
  208. TRUE - The operation was successul.
  209. FALSE - The operation failed. Extended error status is available
  210. using GetLastError.
  211. --*/
  212. {
  213. NTSTATUS Status;
  214. IO_STATUS_BLOCK IoStatusBlock;
  215. PPEB Peb;
  216. DWORD InputMode;
  217. if ( ARGUMENT_PRESENT(lpNumberOfBytesRead) ) {
  218. *lpNumberOfBytesRead = 0;
  219. }
  220. Peb = NtCurrentPeb();
  221. switch( HandleToUlong(hFile) ) {
  222. case STD_INPUT_HANDLE: hFile = Peb->ProcessParameters->StandardInput;
  223. break;
  224. case STD_OUTPUT_HANDLE: hFile = Peb->ProcessParameters->StandardOutput;
  225. break;
  226. case STD_ERROR_HANDLE: hFile = Peb->ProcessParameters->StandardError;
  227. break;
  228. }
  229. if (CONSOLE_HANDLE(hFile)) {
  230. if (ReadConsoleA(hFile,
  231. lpBuffer,
  232. nNumberOfBytesToRead,
  233. lpNumberOfBytesRead,
  234. lpOverlapped
  235. )
  236. ) {
  237. Status = STATUS_SUCCESS;
  238. if (!GetConsoleMode( hFile, &InputMode )) {
  239. InputMode = 0;
  240. }
  241. if (InputMode & ENABLE_PROCESSED_INPUT) {
  242. try {
  243. if (*(PCHAR)lpBuffer == 0x1A) {
  244. *lpNumberOfBytesRead = 0;
  245. }
  246. }
  247. except( EXCEPTION_EXECUTE_HANDLER ) {
  248. Status = GetExceptionCode();
  249. }
  250. }
  251. if (NT_SUCCESS(Status)) {
  252. return TRUE;
  253. }
  254. else {
  255. BaseSetLastNTError(Status);
  256. return FALSE;
  257. }
  258. }
  259. else {
  260. return FALSE;
  261. }
  262. }
  263. if ( ARGUMENT_PRESENT( lpOverlapped ) ) {
  264. LARGE_INTEGER Li;
  265. lpOverlapped->Internal = (DWORD)STATUS_PENDING;
  266. Li.LowPart = lpOverlapped->Offset;
  267. Li.HighPart = lpOverlapped->OffsetHigh;
  268. Status = NtReadFile(
  269. hFile,
  270. lpOverlapped->hEvent,
  271. NULL,
  272. (ULONG_PTR)lpOverlapped->hEvent & 1 ? NULL : lpOverlapped,
  273. (PIO_STATUS_BLOCK)&lpOverlapped->Internal,
  274. lpBuffer,
  275. nNumberOfBytesToRead,
  276. &Li,
  277. NULL
  278. );
  279. if ( NT_SUCCESS(Status) && Status != STATUS_PENDING) {
  280. if ( ARGUMENT_PRESENT(lpNumberOfBytesRead) ) {
  281. try {
  282. *lpNumberOfBytesRead = (DWORD)lpOverlapped->InternalHigh;
  283. }
  284. except(EXCEPTION_EXECUTE_HANDLER) {
  285. *lpNumberOfBytesRead = 0;
  286. }
  287. }
  288. return TRUE;
  289. }
  290. else
  291. if (Status == STATUS_END_OF_FILE) {
  292. if ( ARGUMENT_PRESENT(lpNumberOfBytesRead) ) {
  293. *lpNumberOfBytesRead = 0;
  294. }
  295. BaseSetLastNTError(Status);
  296. return FALSE;
  297. }
  298. else {
  299. BaseSetLastNTError(Status);
  300. return FALSE;
  301. }
  302. }
  303. else
  304. {
  305. Status = NtReadFile(
  306. hFile,
  307. NULL,
  308. NULL,
  309. NULL,
  310. &IoStatusBlock,
  311. lpBuffer,
  312. nNumberOfBytesToRead,
  313. NULL,
  314. NULL
  315. );
  316. if ( Status == STATUS_PENDING) {
  317. // Operation must complete before return & IoStatusBlock destroyed
  318. Status = NtWaitForSingleObject( hFile, FALSE, NULL );
  319. if ( NT_SUCCESS(Status)) {
  320. Status = IoStatusBlock.Status;
  321. }
  322. }
  323. if ( NT_SUCCESS(Status) ) {
  324. *lpNumberOfBytesRead = (DWORD)IoStatusBlock.Information;
  325. return TRUE;
  326. }
  327. else
  328. if (Status == STATUS_END_OF_FILE) {
  329. *lpNumberOfBytesRead = 0;
  330. return TRUE;
  331. }
  332. else {
  333. if ( NT_WARNING(Status) ) {
  334. *lpNumberOfBytesRead = (DWORD)IoStatusBlock.Information;
  335. }
  336. BaseSetLastNTError(Status);
  337. return FALSE;
  338. }
  339. }
  340. }
  341. BOOL
  342. WINAPI
  343. WriteFile(
  344. HANDLE hFile,
  345. LPCVOID lpBuffer,
  346. DWORD nNumberOfBytesToWrite,
  347. LPDWORD lpNumberOfBytesWritten,
  348. LPOVERLAPPED lpOverlapped
  349. )
  350. /*++
  351. Routine Description:
  352. Data can be written to a file using WriteFile.
  353. This API is used to write data to a file. Data is written to the
  354. file from the position indicated by the file pointer. After the
  355. write completes, the file pointer is adjusted by the number of bytes
  356. actually written.
  357. Unlike DOS, a NumberOfBytesToWrite value of zero does not truncate
  358. or extend the file. If this function is required, SetEndOfFile
  359. should be used.
  360. Arguments:
  361. hFile - Supplies an open handle to a file that is to be written. The
  362. file handle must have been created with GENERIC_WRITE access to
  363. the file.
  364. lpBuffer - Supplies the address of the data that is to be written to
  365. the file.
  366. nNumberOfBytesToWrite - Supplies the number of bytes to write to the
  367. file. Unlike DOS, a value of zero is interpreted a null write.
  368. lpNumberOfBytesWritten - Returns the number of bytes written by this
  369. call. Before doing any work or error processing, the API sets this
  370. to zero.
  371. lpOverlapped - Optionally points to an OVERLAPPED structure to be
  372. used with the request. If NULL then the transfer starts at the
  373. current file position and WriteFile will not return until the
  374. operation completes.
  375. If the handle <hFile> was created without specifying
  376. FILE_FLAG_OVERLAPPED the file pointer is moved to the specified
  377. offset plus lpNumberOfBytesWritten before WriteFile returns.
  378. WriteFile will wait for the request to complete before returning
  379. (it will not set ERROR_IO_PENDING).
  380. When FILE_FLAG_OVERLAPPED is specified, WriteFile may return
  381. ERROR_IO_PENDING to allow the calling function to continue processing
  382. while the operation completes. The event (or hFile if hEvent is NULL) will
  383. be set to the signalled state upon completion of the request.
  384. When the handle is created with FILE_FLAG_OVERLAPPED and lpOverlapped
  385. is set to NULL, WriteFile will return ERROR_INVALID_PARAMTER because
  386. the file offset is required.
  387. Return Value:
  388. TRUE - The operation was a success.
  389. FALSE - The operation failed. Extended error status is
  390. available using GetLastError.
  391. --*/
  392. {
  393. NTSTATUS Status;
  394. IO_STATUS_BLOCK IoStatusBlock;
  395. PPEB Peb;
  396. if ( ARGUMENT_PRESENT(lpNumberOfBytesWritten) ) {
  397. *lpNumberOfBytesWritten = 0;
  398. }
  399. Peb = NtCurrentPeb();
  400. switch( HandleToUlong(hFile) ) {
  401. case STD_INPUT_HANDLE: hFile = Peb->ProcessParameters->StandardInput;
  402. break;
  403. case STD_OUTPUT_HANDLE: hFile = Peb->ProcessParameters->StandardOutput;
  404. break;
  405. case STD_ERROR_HANDLE: hFile = Peb->ProcessParameters->StandardError;
  406. break;
  407. }
  408. if (CONSOLE_HANDLE(hFile)) {
  409. return WriteConsoleA(hFile,
  410. (LPVOID)lpBuffer,
  411. nNumberOfBytesToWrite,
  412. lpNumberOfBytesWritten,
  413. lpOverlapped
  414. );
  415. }
  416. if ( ARGUMENT_PRESENT( lpOverlapped ) ) {
  417. LARGE_INTEGER Li;
  418. lpOverlapped->Internal = (DWORD)STATUS_PENDING;
  419. Li.LowPart = lpOverlapped->Offset;
  420. Li.HighPart = lpOverlapped->OffsetHigh;
  421. Status = NtWriteFile(
  422. hFile,
  423. lpOverlapped->hEvent,
  424. NULL,
  425. (ULONG_PTR)lpOverlapped->hEvent & 1 ? NULL : lpOverlapped,
  426. (PIO_STATUS_BLOCK)&lpOverlapped->Internal,
  427. (PVOID)lpBuffer,
  428. nNumberOfBytesToWrite,
  429. &Li,
  430. NULL
  431. );
  432. if ( !NT_ERROR(Status) && Status != STATUS_PENDING) {
  433. if ( ARGUMENT_PRESENT(lpNumberOfBytesWritten) ) {
  434. try {
  435. *lpNumberOfBytesWritten = (DWORD)lpOverlapped->InternalHigh;
  436. }
  437. except(EXCEPTION_EXECUTE_HANDLER) {
  438. *lpNumberOfBytesWritten = 0;
  439. }
  440. }
  441. return TRUE;
  442. }
  443. else {
  444. BaseSetLastNTError(Status);
  445. return FALSE;
  446. }
  447. }
  448. else {
  449. Status = NtWriteFile(
  450. hFile,
  451. NULL,
  452. NULL,
  453. NULL,
  454. &IoStatusBlock,
  455. (PVOID)lpBuffer,
  456. nNumberOfBytesToWrite,
  457. NULL,
  458. NULL
  459. );
  460. if ( Status == STATUS_PENDING) {
  461. // Operation must complete before return & IoStatusBlock destroyed
  462. Status = NtWaitForSingleObject( hFile, FALSE, NULL );
  463. if ( NT_SUCCESS(Status)) {
  464. Status = IoStatusBlock.Status;
  465. }
  466. }
  467. if ( NT_SUCCESS(Status)) {
  468. *lpNumberOfBytesWritten = (DWORD)IoStatusBlock.Information;
  469. return TRUE;
  470. }
  471. else {
  472. if ( NT_WARNING(Status) ) {
  473. *lpNumberOfBytesWritten = (DWORD)IoStatusBlock.Information;
  474. }
  475. BaseSetLastNTError(Status);
  476. return FALSE;
  477. }
  478. }
  479. }
  480. BOOL
  481. WINAPI
  482. SetEndOfFile(
  483. HANDLE hFile
  484. )
  485. /*++
  486. Routine Description:
  487. The end of file position of an open file can be set to the current
  488. file pointer using SetEndOfFile.
  489. This API is used to set the end of file position of a file to the
  490. same value as the current file pointer. This has the effect of
  491. truncating or extending a file. This functionality is similar to
  492. DOS (int 21h, function 40H with CX=0).
  493. Arguments:
  494. hFile - Supplies an open handle to a file that is to be extended or
  495. truncated. The file handle must have been created with
  496. GENERIC_WRITE access to the file.
  497. Return Value:
  498. TRUE - The operation was successful.
  499. FALSE/NULL - The operation failed. Extended error status is available
  500. using GetLastError.
  501. --*/
  502. {
  503. NTSTATUS Status;
  504. IO_STATUS_BLOCK IoStatusBlock;
  505. FILE_POSITION_INFORMATION CurrentPosition;
  506. FILE_END_OF_FILE_INFORMATION EndOfFile;
  507. FILE_ALLOCATION_INFORMATION Allocation;
  508. if (CONSOLE_HANDLE(hFile)) {
  509. BaseSetLastNTError(STATUS_INVALID_HANDLE);
  510. return FALSE;
  511. }
  512. //
  513. // Get the current position of the file pointer
  514. //
  515. Status = NtQueryInformationFile(
  516. hFile,
  517. &IoStatusBlock,
  518. &CurrentPosition,
  519. sizeof(CurrentPosition),
  520. FilePositionInformation
  521. );
  522. if ( !NT_SUCCESS(Status) ) {
  523. BaseSetLastNTError(Status);
  524. return FALSE;
  525. }
  526. //
  527. // Set the end of file based on the current file position
  528. //
  529. EndOfFile.EndOfFile = CurrentPosition.CurrentByteOffset;
  530. Status = NtSetInformationFile(
  531. hFile,
  532. &IoStatusBlock,
  533. &EndOfFile,
  534. sizeof(EndOfFile),
  535. FileEndOfFileInformation
  536. );
  537. if ( !NT_SUCCESS(Status) ) {
  538. BaseSetLastNTError(Status);
  539. return FALSE;
  540. }
  541. //
  542. // Set the allocation based on the current file size
  543. //
  544. Allocation.AllocationSize = CurrentPosition.CurrentByteOffset;
  545. Status = NtSetInformationFile(
  546. hFile,
  547. &IoStatusBlock,
  548. &Allocation,
  549. sizeof(Allocation),
  550. FileAllocationInformation
  551. );
  552. if ( NT_SUCCESS(Status) ) {
  553. return TRUE;
  554. }
  555. else {
  556. BaseSetLastNTError(Status);
  557. return FALSE;
  558. }
  559. }
  560. DWORD
  561. WINAPI
  562. SetFilePointer(
  563. HANDLE hFile,
  564. LONG lDistanceToMove,
  565. PLONG lpDistanceToMoveHigh,
  566. DWORD dwMoveMethod
  567. )
  568. /*++
  569. Routine Description:
  570. An open file's file pointer can be set using SetFilePointer.
  571. The purpose of this function is to update the current value of a
  572. file's file pointer. Care should be taken in multi-threaded
  573. applications that have multiple threads sharing a file handle with
  574. each thread updating the file pointer and then doing a read. This
  575. sequence should be treated as a critical section of code and should
  576. be protected using either a critical section object or a mutex
  577. object.
  578. This API provides the same functionality as DOS (int 21h, function
  579. 42h) and OS/2's DosSetFilePtr.
  580. Arguments:
  581. hFile - Supplies an open handle to a file whose file pointer is to be
  582. moved. The file handle must have been created with
  583. GENERIC_READ or GENERIC_WRITE access to the file.
  584. lDistanceToMove - Supplies the number of bytes to move the file
  585. pointer. A positive value moves the pointer forward in the file
  586. and a negative value moves backwards in the file.
  587. lpDistanceToMoveHigh - An optional parameter that if specified
  588. supplies the high order 32-bits of the 64-bit distance to move.
  589. If the value of this parameter is NULL, this API can only
  590. operate on files whose maximum size is (2**32)-2. If this
  591. parameter is specified, than the maximum file size is (2**64)-2.
  592. This value also returns the high order 32-bits of the new value
  593. of the file pointer. If this value, and the return value
  594. are 0xffffffff, then an error is indicated.
  595. dwMoveMethod - Supplies a value that specifies the starting point
  596. for the file pointer move.
  597. FILE_BEGIN - The starting point is zero or the beginning of the
  598. file. If FILE_BEGIN is specified, then DistanceToMove is
  599. interpreted as an unsigned location for the new
  600. file pointer.
  601. FILE_CURRENT - The current value of the file pointer is used as
  602. the starting point.
  603. FILE_END - The current end of file position is used as the
  604. starting point.
  605. Return Value:
  606. Not -1 - Returns the low order 32-bits of the new value of the file
  607. pointer.
  608. 0xffffffff - If the value of lpDistanceToMoveHigh was NULL, then The
  609. operation failed. Extended error status is available using
  610. GetLastError. Otherwise, this is the low order 32-bits of the
  611. new value of the file pointer.
  612. --*/
  613. {
  614. NTSTATUS Status;
  615. IO_STATUS_BLOCK IoStatusBlock;
  616. FILE_POSITION_INFORMATION CurrentPosition;
  617. FILE_STANDARD_INFORMATION StandardInfo;
  618. LARGE_INTEGER Large;
  619. if (CONSOLE_HANDLE(hFile)) {
  620. BaseSetLastNTError(STATUS_INVALID_HANDLE);
  621. return (DWORD)-1;
  622. }
  623. if (ARGUMENT_PRESENT(lpDistanceToMoveHigh)) {
  624. Large.HighPart = *lpDistanceToMoveHigh;
  625. Large.LowPart = lDistanceToMove;
  626. }
  627. else {
  628. Large.QuadPart = lDistanceToMove;
  629. }
  630. switch (dwMoveMethod) {
  631. case FILE_BEGIN :
  632. CurrentPosition.CurrentByteOffset = Large;
  633. break;
  634. case FILE_CURRENT :
  635. //
  636. // Get the current position of the file pointer
  637. //
  638. Status = NtQueryInformationFile(
  639. hFile,
  640. &IoStatusBlock,
  641. &CurrentPosition,
  642. sizeof(CurrentPosition),
  643. FilePositionInformation
  644. );
  645. if ( !NT_SUCCESS(Status) ) {
  646. BaseSetLastNTError(Status);
  647. return (DWORD)-1;
  648. }
  649. CurrentPosition.CurrentByteOffset.QuadPart += Large.QuadPart;
  650. break;
  651. case FILE_END :
  652. Status = NtQueryInformationFile(
  653. hFile,
  654. &IoStatusBlock,
  655. &StandardInfo,
  656. sizeof(StandardInfo),
  657. FileStandardInformation
  658. );
  659. if ( !NT_SUCCESS(Status) ) {
  660. BaseSetLastNTError(Status);
  661. return (DWORD)-1;
  662. }
  663. CurrentPosition.CurrentByteOffset.QuadPart =
  664. StandardInfo.EndOfFile.QuadPart + Large.QuadPart;
  665. break;
  666. default:
  667. SetLastError(ERROR_INVALID_PARAMETER);
  668. return (DWORD)-1;
  669. break;
  670. }
  671. //
  672. // If the resulting file position is negative, or if the app is not
  673. // prepared for greater than
  674. // then 32 bits than fail
  675. //
  676. if ( CurrentPosition.CurrentByteOffset.QuadPart < 0 ) {
  677. SetLastError(ERROR_NEGATIVE_SEEK);
  678. return (DWORD)-1;
  679. }
  680. if ( !ARGUMENT_PRESENT(lpDistanceToMoveHigh) &&
  681. (CurrentPosition.CurrentByteOffset.HighPart & MAXLONG) ) {
  682. SetLastError(ERROR_INVALID_PARAMETER);
  683. return (DWORD)-1;
  684. }
  685. //
  686. // Set the current file position
  687. //
  688. Status = NtSetInformationFile(
  689. hFile,
  690. &IoStatusBlock,
  691. &CurrentPosition,
  692. sizeof(CurrentPosition),
  693. FilePositionInformation
  694. );
  695. if ( NT_SUCCESS(Status) ) {
  696. if (ARGUMENT_PRESENT(lpDistanceToMoveHigh)){
  697. *lpDistanceToMoveHigh = CurrentPosition.CurrentByteOffset.HighPart;
  698. }
  699. if ( CurrentPosition.CurrentByteOffset.LowPart == -1 ) {
  700. SetLastError(0);
  701. }
  702. return CurrentPosition.CurrentByteOffset.LowPart;
  703. }
  704. else {
  705. BaseSetLastNTError(Status);
  706. if (ARGUMENT_PRESENT(lpDistanceToMoveHigh)){
  707. *lpDistanceToMoveHigh = -1;
  708. }
  709. return (DWORD)-1;
  710. }
  711. }
  712. BOOL
  713. WINAPI
  714. SetFilePointerEx(
  715. HANDLE hFile,
  716. LARGE_INTEGER liDistanceToMove,
  717. PLARGE_INTEGER lpNewFilePointer,
  718. DWORD dwMoveMethod
  719. )
  720. /*++
  721. Routine Description:
  722. An open file's file pointer can be set using SetFilePointer.
  723. The purpose of this function is to update the current value of a
  724. file's file pointer. Care should be taken in multi-threaded
  725. applications that have multiple threads sharing a file handle with
  726. each thread updating the file pointer and then doing a read. This
  727. sequence should be treated as a critical section of code and should
  728. be protected using either a critical section object or a mutex
  729. object.
  730. This API provides the same functionality as DOS (int 21h, function
  731. 42h) and OS/2's DosSetFilePtr.
  732. Arguments:
  733. hFile - Supplies an open handle to a file whose file pointer is to be
  734. moved. The file handle must have been created with
  735. GENERIC_READ or GENERIC_WRITE access to the file.
  736. liDistanceToMove - Supplies the number of bytes to move the file
  737. pointer. A positive value moves the pointer forward in the file
  738. and a negative value moves backwards in the file.
  739. lpNewFilePointer - An optional parameter that if specified returns
  740. the new file pointer
  741. dwMoveMethod - Supplies a value that specifies the starting point
  742. for the file pointer move.
  743. FILE_BEGIN - The starting point is zero or the beginning of the
  744. file. If FILE_BEGIN is specified, then DistanceToMove is
  745. interpreted as an unsigned location for the new
  746. file pointer.
  747. FILE_CURRENT - The current value of the file pointer is used as
  748. the starting point.
  749. FILE_END - The current end of file position is used as the
  750. starting point.
  751. Return Value:
  752. TRUE - The operation was successful
  753. FALSE - The operation failed. Extended error status is available using
  754. GetLastError.
  755. --*/
  756. {
  757. NTSTATUS Status;
  758. IO_STATUS_BLOCK IoStatusBlock;
  759. FILE_POSITION_INFORMATION CurrentPosition;
  760. FILE_STANDARD_INFORMATION StandardInfo;
  761. LARGE_INTEGER Large;
  762. if (CONSOLE_HANDLE(hFile)) {
  763. BaseSetLastNTError(STATUS_INVALID_HANDLE);
  764. return FALSE;
  765. }
  766. Large = liDistanceToMove;
  767. switch (dwMoveMethod) {
  768. case FILE_BEGIN :
  769. CurrentPosition.CurrentByteOffset = Large;
  770. break;
  771. case FILE_CURRENT :
  772. //
  773. // Get the current position of the file pointer
  774. //
  775. Status = NtQueryInformationFile(
  776. hFile,
  777. &IoStatusBlock,
  778. &CurrentPosition,
  779. sizeof(CurrentPosition),
  780. FilePositionInformation
  781. );
  782. if ( !NT_SUCCESS(Status) ) {
  783. BaseSetLastNTError(Status);
  784. return FALSE;
  785. }
  786. CurrentPosition.CurrentByteOffset.QuadPart += Large.QuadPart;
  787. break;
  788. case FILE_END :
  789. Status = NtQueryInformationFile(
  790. hFile,
  791. &IoStatusBlock,
  792. &StandardInfo,
  793. sizeof(StandardInfo),
  794. FileStandardInformation
  795. );
  796. if ( !NT_SUCCESS(Status) ) {
  797. BaseSetLastNTError(Status);
  798. return FALSE;
  799. }
  800. CurrentPosition.CurrentByteOffset.QuadPart =
  801. StandardInfo.EndOfFile.QuadPart + Large.QuadPart;
  802. break;
  803. default:
  804. SetLastError(ERROR_INVALID_PARAMETER);
  805. return FALSE;
  806. break;
  807. }
  808. //
  809. // If the resulting file position is negative fail
  810. //
  811. if ( CurrentPosition.CurrentByteOffset.QuadPart < 0 ) {
  812. SetLastError(ERROR_NEGATIVE_SEEK);
  813. return FALSE;
  814. }
  815. //
  816. // Set the current file position
  817. //
  818. Status = NtSetInformationFile(
  819. hFile,
  820. &IoStatusBlock,
  821. &CurrentPosition,
  822. sizeof(CurrentPosition),
  823. FilePositionInformation
  824. );
  825. if ( NT_SUCCESS(Status) ) {
  826. if (ARGUMENT_PRESENT(lpNewFilePointer)){
  827. *lpNewFilePointer = CurrentPosition.CurrentByteOffset;
  828. }
  829. return TRUE;
  830. }
  831. else {
  832. BaseSetLastNTError(Status);
  833. return FALSE;
  834. }
  835. }
  836. BOOL
  837. WINAPI
  838. GetFileInformationByHandle(
  839. HANDLE hFile,
  840. LPBY_HANDLE_FILE_INFORMATION lpFileInformation
  841. )
  842. /*++
  843. Routine Description:
  844. Arguments:
  845. hFile - Supplies an open handle to a file whose modification date and
  846. times are to be read. The file handle must have been created with
  847. GENERIC_READ access to the file.
  848. lpCreationTime - An optional parameter that if specified points to
  849. the location to return the date and time the file was created.
  850. A returned time of all zero indicates that the file system
  851. containing the file does not support this time value.
  852. Return Value:
  853. TRUE - The operation was successful.
  854. FALSE/NULL - The operation failed. Extended error status is available
  855. using GetLastError.
  856. --*/
  857. {
  858. NTSTATUS Status;
  859. IO_STATUS_BLOCK IoStatusBlock;
  860. BY_HANDLE_FILE_INFORMATION LocalFileInformation;
  861. FILE_ALL_INFORMATION FileInformation;
  862. FILE_FS_VOLUME_INFORMATION VolumeInfo;
  863. if (CONSOLE_HANDLE(hFile)) {
  864. BaseSetLastNTError(STATUS_INVALID_HANDLE);
  865. return FALSE;
  866. }
  867. Status = NtQueryVolumeInformationFile(
  868. hFile,
  869. &IoStatusBlock,
  870. &VolumeInfo,
  871. sizeof(VolumeInfo),
  872. FileFsVolumeInformation
  873. );
  874. if ( !NT_ERROR(Status) ) {
  875. LocalFileInformation.dwVolumeSerialNumber = VolumeInfo.VolumeSerialNumber;
  876. }
  877. else {
  878. BaseSetLastNTError(Status);
  879. return FALSE;
  880. }
  881. Status = NtQueryInformationFile(
  882. hFile,
  883. &IoStatusBlock,
  884. &FileInformation,
  885. sizeof(FileInformation),
  886. FileAllInformation
  887. );
  888. //
  889. // we really plan for buffer overflow
  890. //
  891. if ( !NT_ERROR(Status) ) {
  892. LocalFileInformation.dwFileAttributes = FileInformation.BasicInformation.FileAttributes;
  893. LocalFileInformation.ftCreationTime = *(LPFILETIME)&FileInformation.BasicInformation.CreationTime;
  894. LocalFileInformation.ftLastAccessTime = *(LPFILETIME)&FileInformation.BasicInformation.LastAccessTime;
  895. LocalFileInformation.ftLastWriteTime = *(LPFILETIME)&FileInformation.BasicInformation.LastWriteTime;
  896. LocalFileInformation.nFileSizeHigh = FileInformation.StandardInformation.EndOfFile.HighPart;
  897. LocalFileInformation.nFileSizeLow = FileInformation.StandardInformation.EndOfFile.LowPart;
  898. LocalFileInformation.nNumberOfLinks = FileInformation.StandardInformation.NumberOfLinks;
  899. LocalFileInformation.nFileIndexHigh = FileInformation.InternalInformation.IndexNumber.HighPart;
  900. LocalFileInformation.nFileIndexLow = FileInformation.InternalInformation.IndexNumber.LowPart;
  901. }
  902. else {
  903. BaseSetLastNTError(Status);
  904. return FALSE;
  905. }
  906. *lpFileInformation = LocalFileInformation;
  907. return TRUE;
  908. }
  909. BOOL
  910. APIENTRY
  911. GetFileTime(
  912. HANDLE hFile,
  913. LPFILETIME lpCreationTime,
  914. LPFILETIME lpLastAccessTime,
  915. LPFILETIME lpLastWriteTime
  916. )
  917. /*++
  918. Routine Description:
  919. The date and time that a file was created, last accessed or last
  920. modified can be read using GetFileTime. File time stamps are
  921. returned as 64-bit values, that represent the number of 100
  922. nanoseconds since January 1st, 1601. This date was chosen because
  923. it is the start of a new quadricentury. At 100ns resolution 32 bits
  924. is good for about 429 seconds (or 7 minutes) and a 63-bit integer is
  925. good for about 29,247 years, or around 10,682,247 days.
  926. This API provides the same functionality as DOS (int 21h, function
  927. 47H with AL=0), and provides a subset of OS/2's DosQueryFileInfo.
  928. Arguments:
  929. hFile - Supplies an open handle to a file whose modification date and
  930. times are to be read. The file handle must have been created with
  931. GENERIC_READ access to the file.
  932. lpCreationTime - An optional parameter that if specified points to
  933. the location to return the date and time the file was created.
  934. A returned time of all zero indicates that the file system
  935. containing the file does not support this time value.
  936. lpLastAccessTime - An optional parameter that if specified points to
  937. the location to return the date and time the file was last accessed.
  938. A returned time of all zero indicates that the file system
  939. containing the file does not support this time value.
  940. lpLastWriteTime - An optional parameter that if specified points to
  941. the location to return the date and time the file was last written.
  942. A file system must support this time and thus a valid value will
  943. always be returned for this time value.
  944. Return Value:
  945. TRUE - The operation was successful.
  946. FALSE/NULL - The operation failed. Extended error status is available
  947. using GetLastError.
  948. --*/
  949. {
  950. NTSTATUS Status;
  951. IO_STATUS_BLOCK IoStatusBlock;
  952. FILE_BASIC_INFORMATION BasicInfo;
  953. if (CONSOLE_HANDLE(hFile)) {
  954. BaseSetLastNTError(STATUS_INVALID_HANDLE);
  955. return FALSE;
  956. }
  957. //
  958. // Get the attributes
  959. //
  960. Status = NtQueryInformationFile(
  961. hFile,
  962. &IoStatusBlock,
  963. &BasicInfo,
  964. sizeof(BasicInfo),
  965. FileBasicInformation
  966. );
  967. if ( NT_SUCCESS(Status) ) {
  968. if (ARGUMENT_PRESENT( lpCreationTime )) {
  969. *lpCreationTime = *(LPFILETIME)&BasicInfo.CreationTime;
  970. }
  971. if (ARGUMENT_PRESENT( lpLastAccessTime )) {
  972. *lpLastAccessTime = *(LPFILETIME)&BasicInfo.LastAccessTime;
  973. }
  974. if (ARGUMENT_PRESENT( lpLastWriteTime )) {
  975. *lpLastWriteTime = *(LPFILETIME)&BasicInfo.LastWriteTime;
  976. }
  977. return TRUE;
  978. }
  979. else {
  980. BaseSetLastNTError(Status);
  981. return FALSE;
  982. }
  983. }
  984. BOOL
  985. WINAPI
  986. SetFileTime(
  987. HANDLE hFile,
  988. CONST FILETIME *lpCreationTime,
  989. CONST FILETIME *lpLastAccessTime,
  990. CONST FILETIME *lpLastWriteTime
  991. )
  992. /*++
  993. Routine Description:
  994. The date and time that a file was created, last accessed or last
  995. modified can be modified using SetFileTime. File time stamps are
  996. returned as 64-bit values, that represent the number of 100
  997. nanoseconds since January 1st, 1601. This date was chosen because
  998. it is the start of a new quadricentury. At 100ns resolution 32 bits
  999. is good for about 429 seconds (or 7 minutes) and a 63-bit integer is
  1000. good for about 29,247 years, or around 10,682,247 days.
  1001. This API provides the same functionality as DOS (int 21h, function
  1002. 47H with AL=1), and provides a subset of OS/2's DosSetFileInfo.
  1003. Arguments:
  1004. hFile - Supplies an open handle to a file whose modification date and
  1005. times are to be written. The file handle must have been created
  1006. with GENERIC_WRITE access to the file.
  1007. lpCreationTime - An optional parameter, that if specified supplies
  1008. the new creation time for the file. Some file system's do not
  1009. support this time value, so this parameter may be ignored.
  1010. lpLastAccessTime - An optional parameter, that if specified supplies
  1011. the new last access time for the file. Some file system's do
  1012. not support this time value, so this parameter may be ignored.
  1013. lpLastWriteTime - An optional parameter, that if specified supplies
  1014. the new last write time for the file. A file system must support
  1015. this time value.
  1016. Return Value:
  1017. TRUE - The operation was successful.
  1018. FALSE/NULL - The operation failed. Extended error status is available
  1019. using GetLastError.
  1020. --*/
  1021. {
  1022. NTSTATUS Status;
  1023. IO_STATUS_BLOCK IoStatusBlock;
  1024. FILE_BASIC_INFORMATION BasicInfo;
  1025. if (CONSOLE_HANDLE(hFile)) {
  1026. BaseSetLastNTError(STATUS_INVALID_HANDLE);
  1027. return FALSE;
  1028. }
  1029. //
  1030. // Zero all the time values we can set.
  1031. //
  1032. RtlZeroMemory(&BasicInfo,sizeof(BasicInfo));
  1033. //
  1034. // For each time value that is specified, copy it to the I/O system
  1035. // record.
  1036. //
  1037. if (ARGUMENT_PRESENT( lpCreationTime )) {
  1038. BasicInfo.CreationTime.LowPart = lpCreationTime->dwLowDateTime;
  1039. BasicInfo.CreationTime.HighPart = lpCreationTime->dwHighDateTime;
  1040. }
  1041. if (ARGUMENT_PRESENT( lpLastAccessTime )) {
  1042. BasicInfo.LastAccessTime.LowPart = lpLastAccessTime->dwLowDateTime;
  1043. BasicInfo.LastAccessTime.HighPart = lpLastAccessTime->dwHighDateTime;
  1044. }
  1045. if (ARGUMENT_PRESENT( lpLastWriteTime )) {
  1046. BasicInfo.LastWriteTime.LowPart = lpLastWriteTime->dwLowDateTime;
  1047. BasicInfo.LastWriteTime.HighPart = lpLastWriteTime->dwHighDateTime;
  1048. }
  1049. //
  1050. // Set the requested times.
  1051. //
  1052. Status = NtSetInformationFile(
  1053. hFile,
  1054. &IoStatusBlock,
  1055. &BasicInfo,
  1056. sizeof(BasicInfo),
  1057. FileBasicInformation
  1058. );
  1059. if ( NT_SUCCESS(Status) ) {
  1060. return TRUE;
  1061. }
  1062. else {
  1063. BaseSetLastNTError(Status);
  1064. return FALSE;
  1065. }
  1066. }
  1067. BOOL
  1068. WINAPI
  1069. FlushFileBuffers(
  1070. HANDLE hFile
  1071. )
  1072. /*++
  1073. Routine Description:
  1074. Buffered data may be flushed out to the file using the
  1075. FlushFileBuffers service.
  1076. The FlushFileBuffers service causes all buffered data to be written
  1077. to the specified file.
  1078. Arguments:
  1079. hFile - Supplies an open handle to a file whose buffers are to be
  1080. flushed. The file handle must have been created with
  1081. GENERIC_WRITE access to the file.
  1082. Return Value:
  1083. TRUE - The operation was successful.
  1084. FALSE/NULL - The operation failed. Extended error status is available
  1085. using GetLastError.
  1086. --*/
  1087. {
  1088. NTSTATUS Status;
  1089. IO_STATUS_BLOCK IoStatusBlock;
  1090. PPEB Peb;
  1091. Peb = NtCurrentPeb();
  1092. switch( HandleToUlong(hFile) ) {
  1093. case STD_INPUT_HANDLE: hFile = Peb->ProcessParameters->StandardInput;
  1094. break;
  1095. case STD_OUTPUT_HANDLE: hFile = Peb->ProcessParameters->StandardOutput;
  1096. break;
  1097. case STD_ERROR_HANDLE: hFile = Peb->ProcessParameters->StandardError;
  1098. break;
  1099. }
  1100. if (CONSOLE_HANDLE(hFile)) {
  1101. return( FlushConsoleInputBuffer( hFile ) );
  1102. }
  1103. Status = NtFlushBuffersFile(hFile,&IoStatusBlock);
  1104. if ( NT_SUCCESS(Status) ) {
  1105. return TRUE;
  1106. }
  1107. else {
  1108. BaseSetLastNTError(Status);
  1109. return FALSE;
  1110. }
  1111. }
  1112. BOOL
  1113. WINAPI
  1114. LockFile(
  1115. HANDLE hFile,
  1116. DWORD dwFileOffsetLow,
  1117. DWORD dwFileOffsetHigh,
  1118. DWORD nNumberOfBytesToLockLow,
  1119. DWORD nNumberOfBytesToLockHigh
  1120. )
  1121. /*++
  1122. Routine Description:
  1123. A byte range within an open file may be locked for exclusive access
  1124. using LockFile.
  1125. Locking a region of a file is used to aquire exclusive access to the
  1126. specified region of the file. File locks are not inherited by the
  1127. new process during process creation.
  1128. Locking a portion of a file denies all other processes both read and
  1129. write access to the specified region of the file. Locking a region
  1130. that goes beyond the current end-of-file position is not an error.
  1131. Locks may not overlap an existing locked region of the file.
  1132. For DOS based systems running share.exe the lock semantics work as
  1133. described above. Without share.exe, all attempts to lock or unlock
  1134. a file will fail.
  1135. Arguments:
  1136. hFile - Supplies an open handle to a file that is to have a range of
  1137. bytes locked for exclusive access. The handle must have been
  1138. created with either GENERIC_READ or GENERIC_WRITE access to the
  1139. file.
  1140. dwFileOffsetLow - Supplies the low order 32-bits of the starting
  1141. byte offset of the file where the lock should begin.
  1142. dwFileOffsetHigh - Supplies the high order 32-bits of the starting
  1143. byte offset of the file where the lock should begin.
  1144. nNumberOfBytesToLockLow - Supplies the low order 32-bits of the length
  1145. of the byte range to be locked.
  1146. nNumberOfBytesToLockHigh - Supplies the high order 32-bits of the length
  1147. of the byte range to be locked.
  1148. Return Value:
  1149. TRUE - The operation was successful.
  1150. FALSE/NULL - The operation failed. Extended error status is available
  1151. using GetLastError.
  1152. --*/
  1153. {
  1154. NTSTATUS Status;
  1155. LARGE_INTEGER ByteOffset;
  1156. LARGE_INTEGER Length;
  1157. IO_STATUS_BLOCK IoStatusBlock;
  1158. if (CONSOLE_HANDLE(hFile)) {
  1159. BaseSetLastNTError(STATUS_INVALID_HANDLE);
  1160. return FALSE;
  1161. }
  1162. ByteOffset.LowPart = dwFileOffsetLow;
  1163. ByteOffset.HighPart = dwFileOffsetHigh;
  1164. Length.LowPart = nNumberOfBytesToLockLow;
  1165. Length.HighPart = nNumberOfBytesToLockHigh;
  1166. Status = NtLockFile( hFile,
  1167. NULL,
  1168. NULL,
  1169. NULL,
  1170. &IoStatusBlock,
  1171. &ByteOffset,
  1172. &Length,
  1173. 0,
  1174. TRUE,
  1175. TRUE
  1176. );
  1177. if (Status == STATUS_PENDING) {
  1178. Status = NtWaitForSingleObject( hFile, FALSE, NULL );
  1179. if (NT_SUCCESS( Status )) {
  1180. Status = IoStatusBlock.Status;
  1181. }
  1182. }
  1183. if ( NT_SUCCESS(Status) ) {
  1184. return TRUE;
  1185. }
  1186. else {
  1187. BaseSetLastNTError(Status);
  1188. return FALSE;
  1189. }
  1190. }
  1191. BOOL
  1192. WINAPI
  1193. LockFileEx(
  1194. HANDLE hFile,
  1195. DWORD dwFlags,
  1196. DWORD dwReserved,
  1197. DWORD nNumberOfBytesToLockLow,
  1198. DWORD nNumberOfBytesToLockHigh,
  1199. LPOVERLAPPED lpOverlapped
  1200. )
  1201. /*++
  1202. Routine Description:
  1203. A byte range within an open file may be locked for shared or
  1204. exclusive access using LockFileEx.
  1205. Locking a region of a file is used to aquire shared or exclusive
  1206. access to the specified region of the file. File locks are not
  1207. inherited by the new process during process creation.
  1208. Locking a portion of a file for exclusive access denies all other
  1209. processes both read and write access to the specified region of the
  1210. file. Locking a region that goes beyond the current end-of-file
  1211. position is not an error.
  1212. Locking a portion of a file for shared access denies all other
  1213. processes write access to the specified region of the file, but
  1214. allows other processes to read the locked region.
  1215. If requesting an exclusive lock for a file that is already locked
  1216. shared or exclusively by other threads, then this call will wait
  1217. until the lock is granted unless the LOCKFILE_FAIL_IMMEDIATELY
  1218. flag is specified.
  1219. Locks may not overlap an existing locked region of the file.
  1220. Arguments:
  1221. hFile - Supplies an open handle to a file that is to have a range of
  1222. bytes locked for exclusive access. The handle must have been
  1223. created with either GENERIC_READ or GENERIC_WRITE access to the
  1224. file.
  1225. dwFlags - Supplies flag bits that modify the behavior of this function.
  1226. LOCKFILE_FAIL_IMMEDIATELY - if set, then this function will return
  1227. immediately if it is unable to acquire the requested lock.
  1228. Otherwise it will wait.
  1229. LOCKFILE_EXCLUSIVE_LOCK - if set, then this function requests an
  1230. exclusive lock, otherwise it requested a shared lock.
  1231. dwReserved - Reserved parameter that must be zero.
  1232. nNumberOfBytesToLockLow - Supplies the low order 32-bits of the length
  1233. of the byte range to be locked.
  1234. nNumberOfBytesToLockHigh - Supplies the high order 32-bits of the length
  1235. of the byte range to be locked.
  1236. lpOverlapped - Required pointer to an OVERLAPPED structure to be
  1237. used with the request. It contains the file offset of the
  1238. beginning of the lock range.
  1239. Return Value:
  1240. TRUE - The operation was successful.
  1241. FALSE/NULL - The operation failed. Extended error status is available
  1242. using GetLastError.
  1243. --*/
  1244. {
  1245. NTSTATUS Status;
  1246. LARGE_INTEGER ByteOffset;
  1247. LARGE_INTEGER Length;
  1248. if (CONSOLE_HANDLE(hFile)) {
  1249. BaseSetLastNTError(STATUS_INVALID_HANDLE);
  1250. return FALSE;
  1251. }
  1252. if (dwReserved != 0) {
  1253. SetLastError(ERROR_INVALID_PARAMETER);
  1254. return FALSE;
  1255. }
  1256. ByteOffset.LowPart = lpOverlapped->Offset;
  1257. ByteOffset.HighPart = lpOverlapped->OffsetHigh;
  1258. Length.LowPart = nNumberOfBytesToLockLow;
  1259. Length.HighPart = nNumberOfBytesToLockHigh;
  1260. lpOverlapped->Internal = (DWORD)STATUS_PENDING;
  1261. Status = NtLockFile( hFile,
  1262. lpOverlapped->hEvent,
  1263. NULL,
  1264. (ULONG_PTR)lpOverlapped->hEvent & 1 ? NULL : lpOverlapped,
  1265. (PIO_STATUS_BLOCK)&lpOverlapped->Internal,
  1266. &ByteOffset,
  1267. &Length,
  1268. 0,
  1269. (BOOLEAN)((dwFlags & LOCKFILE_FAIL_IMMEDIATELY) ? TRUE : FALSE),
  1270. (BOOLEAN)((dwFlags & LOCKFILE_EXCLUSIVE_LOCK) ? TRUE : FALSE)
  1271. );
  1272. if ( NT_SUCCESS(Status) && Status != STATUS_PENDING) {
  1273. return TRUE;
  1274. }
  1275. else {
  1276. BaseSetLastNTError(Status);
  1277. return FALSE;
  1278. }
  1279. }
  1280. BOOL
  1281. WINAPI
  1282. UnlockFile(
  1283. HANDLE hFile,
  1284. DWORD dwFileOffsetLow,
  1285. DWORD dwFileOffsetHigh,
  1286. DWORD nNumberOfBytesToUnlockLow,
  1287. DWORD nNumberOfBytesToUnlockHigh
  1288. )
  1289. /*++
  1290. Routine Description:
  1291. A previously locked byte range within an open file may be Unlocked
  1292. using UnlockFile.
  1293. Unlocking a region of a file is used release a previously aquired
  1294. lock on a file. The region to unlock must exactly correspond to an
  1295. existing locked region. Two adjacent regions of a file can not be
  1296. locked seperately and then be unlocked using a single region that
  1297. spans both locked regions.
  1298. If a process terminates with a portion of a file locked, or closes a
  1299. file that has outstanding locks, the behavior is not specified.
  1300. For DOS based systems running share.exe the lock semantics work as
  1301. described above. Without share.exe, all attempts to lock or unlock
  1302. a file will fail.
  1303. Arguments:
  1304. hFile - Supplies an open handle to a file that is to have an
  1305. existing locked region unlocked. The handle must have been
  1306. created with either GENERIC_READ or GENERIC_WRITE access to the
  1307. file.
  1308. dwFileOffsetLow - Supplies the low order 32-bits of an existing
  1309. locked region to be unlocked.
  1310. dwFileOffsetHigh - Supplies the high order 32-bits of an existing
  1311. locked region to be unlocked.
  1312. nNumberOfBytesToUnlockLow - Supplies the low order 32-bits of the
  1313. length of the byte range to be unlocked.
  1314. nNumberOfBytesToUnlockHigh - Supplies the high order 32-bits of the
  1315. length of the byte range to be unlocked.
  1316. Return Value:
  1317. TRUE - The operation was successful.
  1318. FALSE/NULL - The operation failed. Extended error status is available
  1319. using GetLastError.
  1320. --*/
  1321. {
  1322. BOOL bResult;
  1323. OVERLAPPED Overlapped;
  1324. NTSTATUS Status;
  1325. Overlapped.Offset = dwFileOffsetLow;
  1326. Overlapped.OffsetHigh = dwFileOffsetHigh;
  1327. bResult = UnlockFileEx( hFile,
  1328. 0,
  1329. nNumberOfBytesToUnlockLow,
  1330. nNumberOfBytesToUnlockHigh,
  1331. &Overlapped
  1332. );
  1333. if (!bResult && GetLastError() == ERROR_IO_PENDING) {
  1334. Status = NtWaitForSingleObject( hFile, FALSE, NULL );
  1335. if (NT_SUCCESS( Status )) {
  1336. Status = (NTSTATUS)Overlapped.Internal;
  1337. }
  1338. if ( NT_SUCCESS(Status) ) {
  1339. return TRUE;
  1340. }
  1341. else {
  1342. BaseSetLastNTError(Status);
  1343. return FALSE;
  1344. }
  1345. }
  1346. else {
  1347. return bResult;
  1348. }
  1349. }
  1350. BOOL
  1351. WINAPI
  1352. UnlockFileEx(
  1353. HANDLE hFile,
  1354. DWORD dwReserved,
  1355. DWORD nNumberOfBytesToUnlockLow,
  1356. DWORD nNumberOfBytesToUnlockHigh,
  1357. LPOVERLAPPED lpOverlapped
  1358. )
  1359. /*++
  1360. Routine Description:
  1361. A previously locked byte range within an open file may be Unlocked
  1362. using UnlockFile.
  1363. Unlocking a region of a file is used release a previously aquired
  1364. lock on a file. The region to unlock must exactly correspond to an
  1365. existing locked region. Two adjacent regions of a file can not be
  1366. locked seperately and then be unlocked using a single region that
  1367. spans both locked regions.
  1368. If a process terminates with a portion of a file locked, or closes a
  1369. file that has outstanding locks, the behavior is not specified.
  1370. Arguments:
  1371. hFile - Supplies an open handle to a file that is to have an
  1372. existing locked region unlocked. The handle must have been
  1373. created with either GENERIC_READ or GENERIC_WRITE access to the
  1374. file.
  1375. dwReserved - Reserved parameter that must be zero.
  1376. nNumberOfBytesToUnlockLow - Supplies the low order 32-bits of the
  1377. length of the byte range to be unlocked.
  1378. nNumberOfBytesToUnlockHigh - Supplies the high order 32-bits of the
  1379. length of the byte range to be unlocked.
  1380. lpOverlapped - Required pointer to an OVERLAPPED structure to be
  1381. used with the request. It contains the file offset of the
  1382. beginning of the lock range.
  1383. Return Value:
  1384. TRUE - The operation was successful.
  1385. FALSE/NULL - The operation failed. Extended error status is available
  1386. using GetLastError.
  1387. --*/
  1388. {
  1389. NTSTATUS Status;
  1390. LARGE_INTEGER ByteOffset;
  1391. LARGE_INTEGER Length;
  1392. if (CONSOLE_HANDLE(hFile)) {
  1393. BaseSetLastNTError(STATUS_INVALID_HANDLE);
  1394. return FALSE;
  1395. }
  1396. if (dwReserved != 0) {
  1397. SetLastError(ERROR_INVALID_PARAMETER);
  1398. return FALSE;
  1399. }
  1400. ByteOffset.LowPart = lpOverlapped->Offset;
  1401. ByteOffset.HighPart = lpOverlapped->OffsetHigh;
  1402. Length.LowPart = nNumberOfBytesToUnlockLow;
  1403. Length.HighPart = nNumberOfBytesToUnlockHigh;
  1404. Status = NtUnlockFile(
  1405. hFile,
  1406. (PIO_STATUS_BLOCK)&lpOverlapped->Internal,
  1407. &ByteOffset,
  1408. &Length,
  1409. 0
  1410. );
  1411. if ( NT_SUCCESS(Status) ) {
  1412. return TRUE;
  1413. }
  1414. else {
  1415. BaseSetLastNTError(Status);
  1416. return FALSE;
  1417. }
  1418. }
  1419. UINT
  1420. WINAPI
  1421. SetHandleCount(
  1422. UINT uNumber
  1423. )
  1424. /*++
  1425. Routine Description:
  1426. This function changes the number of file handles available to a
  1427. process. For DOS based Win32, the default maximum number of file
  1428. handles available to a process is 20. For NT/Win32 systems, this
  1429. API has no effect.
  1430. Arguments:
  1431. uNumber - Specifies the number of file handles needed by the
  1432. application. The maximum is 255.
  1433. Return Value:
  1434. The return value specifies the number of file handles actually
  1435. available to the application. It may be less than the number
  1436. specified by the wNumber parameter.
  1437. --*/
  1438. {
  1439. return uNumber;
  1440. }
  1441. DWORD
  1442. WINAPI
  1443. GetFileSize(
  1444. HANDLE hFile,
  1445. LPDWORD lpFileSizeHigh
  1446. )
  1447. /*++
  1448. Routine Description:
  1449. This function returns the size of the file specified by
  1450. hFile. It is capable of returning 64-bits worth of file size.
  1451. The return value contains the low order 32-bits of the file's size.
  1452. The optional lpFileSizeHigh returns the high order 32-bits of the
  1453. file's size.
  1454. Arguments:
  1455. hFile - Supplies an open handle to a file whose size is to be
  1456. returned. The handle must have been created with either
  1457. GENERIC_READ or GENERIC_WRITE access to the file.
  1458. lpFileSizeHigh - An optional parameter, that if specified, returns
  1459. the high order 64-bits of the file's size.
  1460. Return Value:
  1461. Not -1 - Returns the low order 32-bits of the specified file's size.
  1462. 0xffffffff - If the value of size of the file cannot be determined,
  1463. or an invalid handle or handle with inappropriate access, or a
  1464. handle to a non-file is specified, this error is returned. If
  1465. the file's size (low 32-bits) is -1, then this value is
  1466. returned, and GetLastError() will return 0. Extended error
  1467. status is available using GetLastError.
  1468. --*/
  1469. {
  1470. BOOL b;
  1471. LARGE_INTEGER Li;
  1472. b = GetFileSizeEx(hFile,&Li);
  1473. if ( b ) {
  1474. if ( ARGUMENT_PRESENT(lpFileSizeHigh) ) {
  1475. *lpFileSizeHigh = (DWORD)Li.HighPart;
  1476. }
  1477. if (Li.LowPart == -1 ) {
  1478. SetLastError(0);
  1479. }
  1480. }
  1481. else {
  1482. Li.LowPart = -1;
  1483. }
  1484. return Li.LowPart;
  1485. }
  1486. BOOL
  1487. WINAPI
  1488. GetFileSizeEx(
  1489. HANDLE hFile,
  1490. PLARGE_INTEGER lpFileSize
  1491. )
  1492. /*++
  1493. Routine Description:
  1494. This function returns the size of the file specified by
  1495. hFile. It is capable of returning 64-bits worth of file size.
  1496. Arguments:
  1497. hFile - Supplies an open handle to a file whose size is to be
  1498. returned. The handle must have been created with either
  1499. GENERIC_READ or GENERIC_WRITE access to the file.
  1500. lpFileSize - Returns the files size
  1501. Return Value:
  1502. TRUE - The operation was successful
  1503. FALSE - The operation failed. Extended error
  1504. status is available using GetLastError.
  1505. --*/
  1506. {
  1507. NTSTATUS Status;
  1508. IO_STATUS_BLOCK IoStatusBlock;
  1509. FILE_STANDARD_INFORMATION StandardInfo;
  1510. Status = NtQueryInformationFile(
  1511. hFile,
  1512. &IoStatusBlock,
  1513. &StandardInfo,
  1514. sizeof(StandardInfo),
  1515. FileStandardInformation
  1516. );
  1517. if ( !NT_SUCCESS(Status) ) {
  1518. BaseSetLastNTError(Status);
  1519. return FALSE;
  1520. }
  1521. else {
  1522. *lpFileSize = StandardInfo.EndOfFile;
  1523. return TRUE;
  1524. }
  1525. }
  1526. VOID
  1527. WINAPI
  1528. BasepIoCompletion(
  1529. PVOID ApcContext,
  1530. PIO_STATUS_BLOCK IoStatusBlock,
  1531. DWORD Reserved
  1532. )
  1533. /*++
  1534. Routine Description:
  1535. This procedure is called to complete ReadFileEx and WriteFileEx
  1536. asynchronous I/O. Its primary function is to extract the
  1537. appropriate information from the passed IoStatusBlock and call the
  1538. users completion routine.
  1539. The users completion routine is called as:
  1540. Routine Description:
  1541. When an outstanding I/O completes with a callback, this
  1542. function is called. This function is only called while the
  1543. thread is in an alertable wait (SleepEx,
  1544. WaitForSingleObjectEx, or WaitForMultipleObjectsEx with the
  1545. bAlertable flag set to TRUE). Returning from this function
  1546. allows another pendiong I/O completion callback to be
  1547. processed. If this is the case, this callback is entered
  1548. before the termination of the thread's wait with a return
  1549. code of WAIT_IO_COMPLETION.
  1550. Note that each time your completion routine is called, the
  1551. system uses some of your stack. If you code your completion
  1552. logic to do additional ReadFileEx's and WriteFileEx's within
  1553. your completion routine, AND you do alertable waits in your
  1554. completion routine, you may grow your stack without ever
  1555. trimming it back.
  1556. Arguments:
  1557. dwErrorCode - Supplies the I/O completion status for the
  1558. related I/O. A value of 0 indicates that the I/O was
  1559. successful. Note that end of file is indicated by a
  1560. non-zero dwErrorCode value of ERROR_HANDLE_EOF.
  1561. dwNumberOfBytesTransfered - Supplies the number of bytes
  1562. transfered during the associated I/O. If an error
  1563. occured, a value of 0 is supplied.
  1564. lpOverlapped - Supplies the address of the OVERLAPPED
  1565. structure used to initiate the associated I/O. The
  1566. hEvent field of this structure is not used by the system
  1567. and may be used by the application to provide additional
  1568. I/O context. Once a completion routine is called, the
  1569. system will not use the OVERLAPPED structure. The
  1570. completion routine is free to deallocate the overlapped
  1571. structure.
  1572. Arguments:
  1573. ApcContext - Supplies the users completion routine. The format of
  1574. this routine is an LPOVERLAPPED_COMPLETION_ROUTINE.
  1575. IoStatusBlock - Supplies the address of the IoStatusBlock that
  1576. contains the I/O completion status. The IoStatusBlock is
  1577. contained within the OVERLAPPED structure.
  1578. Reserved - Not used; reserved for future use.
  1579. Return Value:
  1580. None.
  1581. --*/
  1582. {
  1583. PBASE_ACTIVATION_CONTEXT_ACTIVATION_BLOCK ActivationBlock;
  1584. LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine;
  1585. DWORD dwErrorCode;
  1586. DWORD dwNumberOfBytesTransfered;
  1587. LPOVERLAPPED lpOverlapped;
  1588. NTSTATUS Status;
  1589. RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME ActivationFrame = { sizeof(ActivationFrame), RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_FORMAT_WHISTLER };
  1590. PACTIVATION_CONTEXT ActivationContext = NULL;
  1591. if ( NT_ERROR(IoStatusBlock->Status) ) {
  1592. dwErrorCode = RtlNtStatusToDosError(IoStatusBlock->Status);
  1593. dwNumberOfBytesTransfered = 0;
  1594. } else {
  1595. dwErrorCode = 0;
  1596. dwNumberOfBytesTransfered = (DWORD)IoStatusBlock->Information;
  1597. }
  1598. ActivationBlock = (PBASE_ACTIVATION_CONTEXT_ACTIVATION_BLOCK) ApcContext;
  1599. ActivationContext = ActivationBlock->ActivationContext;
  1600. CompletionRoutine = (LPOVERLAPPED_COMPLETION_ROUTINE) ActivationBlock->CallbackFunction;
  1601. lpOverlapped = (LPOVERLAPPED) CONTAINING_RECORD(IoStatusBlock, OVERLAPPED, Internal);
  1602. if (!(ActivationBlock->Flags & BASE_ACTIVATION_CONTEXT_ACTIVATION_BLOCK_FLAG_DO_NOT_FREE_AFTER_CALLBACK))
  1603. BasepFreeActivationContextActivationBlock(ActivationBlock);
  1604. RtlActivateActivationContextUnsafeFast(&ActivationFrame, ActivationContext);
  1605. __try {
  1606. (*CompletionRoutine)(dwErrorCode, dwNumberOfBytesTransfered, lpOverlapped);
  1607. } __finally {
  1608. RtlDeactivateActivationContextUnsafeFast(&ActivationFrame);
  1609. }
  1610. Reserved;
  1611. }
  1612. VOID
  1613. WINAPI
  1614. BasepIoCompletionSimple(
  1615. PVOID ApcContext,
  1616. PIO_STATUS_BLOCK IoStatusBlock,
  1617. DWORD Reserved
  1618. )
  1619. /*++
  1620. Routine Description:
  1621. This procedure is called to complete ReadFileEx and WriteFileEx
  1622. asynchronous I/O. Its primary function is to extract the
  1623. appropriate information from the passed IoStatusBlock and call the
  1624. users completion routine.
  1625. The users completion routine is called as:
  1626. Routine Description:
  1627. When an outstanding I/O completes with a callback, this
  1628. function is called. This function is only called while the
  1629. thread is in an alertable wait (SleepEx,
  1630. WaitForSingleObjectEx, or WaitForMultipleObjectsEx with the
  1631. bAlertable flag set to TRUE). Returning from this function
  1632. allows another pendiong I/O completion callback to be
  1633. processed. If this is the case, this callback is entered
  1634. before the termination of the thread's wait with a return
  1635. code of WAIT_IO_COMPLETION.
  1636. Note that each time your completion routine is called, the
  1637. system uses some of your stack. If you code your completion
  1638. logic to do additional ReadFileEx's and WriteFileEx's within
  1639. your completion routine, AND you do alertable waits in your
  1640. completion routine, you may grow your stack without ever
  1641. trimming it back.
  1642. Arguments:
  1643. dwErrorCode - Supplies the I/O completion status for the
  1644. related I/O. A value of 0 indicates that the I/O was
  1645. successful. Note that end of file is indicated by a
  1646. non-zero dwErrorCode value of ERROR_HANDLE_EOF.
  1647. dwNumberOfBytesTransfered - Supplies the number of bytes
  1648. transfered during the associated I/O. If an error
  1649. occured, a value of 0 is supplied.
  1650. lpOverlapped - Supplies the address of the OVERLAPPED
  1651. structure used to initiate the associated I/O. The
  1652. hEvent field of this structure is not used by the system
  1653. and may be used by the application to provide additional
  1654. I/O context. Once a completion routine is called, the
  1655. system will not use the OVERLAPPED structure. The
  1656. completion routine is free to deallocate the overlapped
  1657. structure.
  1658. Arguments:
  1659. ApcContext - Supplies the users completion routine. The format of
  1660. this routine is an LPOVERLAPPED_COMPLETION_ROUTINE.
  1661. IoStatusBlock - Supplies the address of the IoStatusBlock that
  1662. contains the I/O completion status. The IoStatusBlock is
  1663. contained within the OVERLAPPED structure.
  1664. Reserved - Not used; reserved for future use.
  1665. Return Value:
  1666. None.
  1667. --*/
  1668. {
  1669. LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine;
  1670. DWORD dwErrorCode;
  1671. DWORD dwNumberOfBytesTransfered;
  1672. LPOVERLAPPED lpOverlapped;
  1673. dwErrorCode = 0;
  1674. if ( NT_ERROR(IoStatusBlock->Status) ) {
  1675. dwErrorCode = RtlNtStatusToDosError(IoStatusBlock->Status);
  1676. dwNumberOfBytesTransfered = 0;
  1677. }
  1678. else {
  1679. dwErrorCode = 0;
  1680. dwNumberOfBytesTransfered = (DWORD)IoStatusBlock->Information;
  1681. }
  1682. CompletionRoutine = (LPOVERLAPPED_COMPLETION_ROUTINE)ApcContext;
  1683. lpOverlapped = (LPOVERLAPPED)CONTAINING_RECORD(IoStatusBlock,OVERLAPPED,Internal);
  1684. (CompletionRoutine)(dwErrorCode,dwNumberOfBytesTransfered,lpOverlapped);
  1685. Reserved;
  1686. }
  1687. BOOL
  1688. WINAPI
  1689. ReadFileEx(
  1690. HANDLE hFile,
  1691. LPVOID lpBuffer,
  1692. DWORD nNumberOfBytesToRead,
  1693. LPOVERLAPPED lpOverlapped,
  1694. LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
  1695. )
  1696. /*++
  1697. Routine Description:
  1698. Data can be read from a file using ReadFileEx.
  1699. This API reports its completion status asynchronously by calling the
  1700. specified lpCompletionRoutine.
  1701. The caller of this routine uses the lpOverlappedStructure to specify
  1702. the byte offset within the file where the read is to begin from.
  1703. For files that do not support this concept (pipes...), the starting
  1704. file offset is ignored.
  1705. Upon successful completion of this API (return value of TRUE), the
  1706. calling thread has an I/O outstanding. When the I/O completes, and
  1707. the thread is blocked in an alertable wait, the lpCompletionRoutine
  1708. will be called and the wait will return with a return code of
  1709. WAIT_IO_COMPLETION. If the I/O completes, but the thread issuing
  1710. the I/O is not in an alertable wait, the call to the completion
  1711. routine is queued until the thread executes an alertable wait.
  1712. If this API fails (by returning FALSE), GetLastError can be used to
  1713. get additional error information. If this call fails because the
  1714. thread issued a read beyond the end of file, GetLastError will
  1715. return a value of ERROR_HANDLE_EOF.
  1716. Arguments:
  1717. hFile - Supplies an open handle to a file that is to be read. The
  1718. file handle must have been created with GENERIC_READ access to
  1719. the file. The file must have been created with the
  1720. FILE_FLAG_OVERLAPPED flag.
  1721. lpBuffer - Supplies the address of a buffer to receive the data read
  1722. from the file.
  1723. nNumberOfBytesToRead - Supplies the number of bytes to read from the
  1724. file.
  1725. lpOverlapped - Supplies the address of an OVERLAPPED structure to be
  1726. used with the request. The caller of this function must specify
  1727. a starting byte offset within the file to start the read from.
  1728. It does this using the Offset and OffsetHigh fields of the
  1729. overlapped structure. This call does not use or modify the
  1730. hEvent field of the overlapped structure. The caller may use
  1731. this field for any purpose. This API does use the Internal and
  1732. InternalHigh fields of the overlapped structure, the thread
  1733. should not manipulate this. The lpOverlapped structure must
  1734. remain valid for the duration of the I/O. It is not a good idea
  1735. to make it a local variable and then possibly returning from the
  1736. routine with the I/O that is using this structure still pending.
  1737. Return Value:
  1738. TRUE - The operation was successul. Completion status will be
  1739. propagated to the caller using the completion callback
  1740. mechanism. Note that this information is only made available to
  1741. the thread that issued the I/O, and only when the I/O completes,
  1742. and the thread is executing in an alertable wait.
  1743. FALSE - The operation failed. Extended error status is available
  1744. using GetLastError. Note that end of file is treated as a failure
  1745. with an error code of ERROR_HANDLE_EOF.
  1746. --*/
  1747. {
  1748. NTSTATUS Status;
  1749. LARGE_INTEGER Li;
  1750. PBASE_ACTIVATION_CONTEXT_ACTIVATION_BLOCK ActivationBlock = NULL;
  1751. PIO_APC_ROUTINE IoApcRoutine = &BasepIoCompletionSimple;
  1752. PVOID ApcContext = lpCompletionRoutine;
  1753. Li.LowPart = lpOverlapped->Offset;
  1754. Li.HighPart = lpOverlapped->OffsetHigh;
  1755. // If there's an APC routine to call we need to allocate a little chunk of heap
  1756. // to pass the activation context to the APC callback.
  1757. if (lpCompletionRoutine != NULL) {
  1758. Status = BasepAllocateActivationContextActivationBlock(
  1759. BASEP_ALLOCATE_ACTIVATION_CONTEXT_ACTIVATION_BLOCK_FLAG_DO_NOT_ALLOCATE_IF_PROCESS_DEFAULT,
  1760. lpCompletionRoutine,
  1761. lpOverlapped,
  1762. &ActivationBlock);
  1763. if (!NT_SUCCESS(Status)) {
  1764. BaseSetLastNTError(Status);
  1765. return FALSE;
  1766. }
  1767. // If there's nothing to do, call the simpler one that doesn't try to do activation context stuff
  1768. if (ActivationBlock != NULL) {
  1769. IoApcRoutine = &BasepIoCompletion;
  1770. ApcContext = ActivationBlock;
  1771. }
  1772. }
  1773. Status = NtReadFile(
  1774. hFile,
  1775. NULL,
  1776. IoApcRoutine,
  1777. ApcContext,
  1778. (PIO_STATUS_BLOCK) &lpOverlapped->Internal,
  1779. lpBuffer,
  1780. nNumberOfBytesToRead,
  1781. &Li,
  1782. NULL
  1783. );
  1784. if ( NT_ERROR(Status) ) {
  1785. if (ActivationBlock != NULL)
  1786. BasepFreeActivationContextActivationBlock(ActivationBlock);
  1787. BaseSetLastNTError(Status);
  1788. return FALSE;
  1789. }
  1790. return TRUE;
  1791. }
  1792. BOOL
  1793. WINAPI
  1794. WriteFileEx(
  1795. HANDLE hFile,
  1796. LPCVOID lpBuffer,
  1797. DWORD nNumberOfBytesToWrite,
  1798. LPOVERLAPPED lpOverlapped,
  1799. LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
  1800. )
  1801. /*++
  1802. Routine Description:
  1803. Data can be written to a file using WriteFileEx.
  1804. This API reports its completion status asynchronously by calling the
  1805. specified lpCompletionRoutine.
  1806. The caller of this routine uses the lpOverlappedStructure to specify
  1807. the byte offset within the file where the write is to begin.
  1808. For files that do not support this concept (pipes...), the starting
  1809. file offset is ignored.
  1810. Upon successful completion of this API (return value of TRUE), the
  1811. calling thread has an I/O outstanding. When the I/O completes, and
  1812. the thread is blocked in an alertable wait, the lpCompletionRoutine
  1813. will be called and the wait will return with a return code of
  1814. WAIT_IO_COMPLETION. If the I/O completes, but the thread issuing
  1815. the I/O is not in an alertable wait, the call to the completion
  1816. routine is queued until the thread executes an alertable wait.
  1817. If this API fails (by returning FALSE), GetLastError can be used to
  1818. get additional error information.
  1819. Unlike DOS, a NumberOfBytesToWrite value of zero does not truncate
  1820. or extend the file. If this function is required, SetEndOfFile
  1821. should be used.
  1822. Arguments:
  1823. hFile - Supplies an open handle to a file that is to be written. The
  1824. file handle must have been created with GENERIC_WRITE access to
  1825. the file.
  1826. lpBuffer - Supplies the address of the data that is to be written to
  1827. the file.
  1828. nNumberOfBytesToWrite - Supplies the number of bytes to write to the
  1829. file. Unlike DOS, a value of zero is interpreted a null write.
  1830. lpOverlapped - Supplies the address of an OVERLAPPED structure to be
  1831. used with the request. The caller of this function must specify
  1832. a starting byte offset within the file to start the write to.
  1833. It does this using the Offset and OffsetHigh fields of the
  1834. overlapped structure. This call does not use or modify the
  1835. hEvent field of the overlapped structure. The caller may use
  1836. this field for any purpose. This API does use the Internal and
  1837. InternalHigh fields of the overlapped structure, the thread
  1838. should not manipulate this. The lpOverlapped structure must
  1839. remain valid for the duration of the I/O. It is not a good idea
  1840. to make it a local variable and then possibly returning from the
  1841. routine with the I/O that is using this structure still pending.
  1842. Return Value:
  1843. TRUE - The operation was successul. Completion status will be
  1844. propagated to the caller using the completion callback
  1845. mechanism. Note that this information is only made available to
  1846. the thread that issued the I/O, and only when the I/O completes,
  1847. and the thread is executing in an alertable wait.
  1848. FALSE - The operation failed. Extended error status is available
  1849. using GetLastError. Note that end of file is treated as a failure
  1850. with an error code of ERROR_HANDLE_EOF.
  1851. --*/
  1852. {
  1853. NTSTATUS Status;
  1854. LARGE_INTEGER Li;
  1855. PBASE_ACTIVATION_CONTEXT_ACTIVATION_BLOCK ActivationBlock = NULL;
  1856. PIO_APC_ROUTINE IoApcRoutine = &BasepIoCompletionSimple;
  1857. PVOID ApcContext = lpCompletionRoutine;
  1858. Li.LowPart = lpOverlapped->Offset;
  1859. Li.HighPart = lpOverlapped->OffsetHigh;
  1860. // If there's an APC routine to call we may need to allocate a little chunk of heap
  1861. // to pass to the APC callback.
  1862. //
  1863. // we'll replace the parameters to the common NtWriteFile call below so that
  1864. // the control flow is obvious.
  1865. //
  1866. if (lpCompletionRoutine != NULL) {
  1867. Status = BasepAllocateActivationContextActivationBlock(
  1868. BASEP_ALLOCATE_ACTIVATION_CONTEXT_ACTIVATION_BLOCK_FLAG_DO_NOT_ALLOCATE_IF_PROCESS_DEFAULT,
  1869. lpCompletionRoutine,
  1870. lpOverlapped,
  1871. &ActivationBlock);
  1872. if (!NT_SUCCESS(Status)) {
  1873. BaseSetLastNTError(Status);
  1874. return FALSE;
  1875. }
  1876. // If there's nothing to do, call the simpler one that doesn't try to do activation context stuff
  1877. if (ActivationBlock != NULL) {
  1878. IoApcRoutine = &BasepIoCompletion;
  1879. ApcContext = ActivationBlock;
  1880. }
  1881. }
  1882. Status = NtWriteFile(
  1883. hFile,
  1884. NULL,
  1885. IoApcRoutine,
  1886. ApcContext,
  1887. (PIO_STATUS_BLOCK)&lpOverlapped->Internal,
  1888. (LPVOID)lpBuffer,
  1889. nNumberOfBytesToWrite,
  1890. &Li,
  1891. NULL
  1892. );
  1893. if ( NT_ERROR(Status) ) {
  1894. if (ActivationBlock != NULL) {
  1895. BasepFreeActivationContextActivationBlock(ActivationBlock);
  1896. }
  1897. BaseSetLastNTError(Status);
  1898. return FALSE;
  1899. }
  1900. return TRUE;
  1901. }
  1902. BOOL
  1903. WINAPI
  1904. DeviceIoControl(
  1905. HANDLE hDevice,
  1906. DWORD dwIoControlCode,
  1907. LPVOID lpInBuffer,
  1908. DWORD nInBufferSize,
  1909. LPVOID lpOutBuffer,
  1910. DWORD nOutBufferSize,
  1911. LPDWORD lpBytesReturned,
  1912. LPOVERLAPPED lpOverlapped
  1913. )
  1914. /*++
  1915. Routine Description:
  1916. An operation on a device may be performed by calling the device driver
  1917. directly using the DeviceIoContrl function.
  1918. The device driver must first be opened to get a valid handle.
  1919. Arguments:
  1920. hDevice - Supplies an open handle a device on which the operation is to
  1921. be performed.
  1922. dwIoControlCode - Supplies the control code for the operation. This
  1923. control code determines on which type of device the operation must
  1924. be performed and determines exactly what operation is to be
  1925. performed.
  1926. lpInBuffer - Suplies an optional pointer to an input buffer that contains
  1927. the data required to perform the operation. Whether or not the
  1928. buffer is actually optional is dependent on the IoControlCode.
  1929. nInBufferSize - Supplies the length of the input buffer in bytes.
  1930. lpOutBuffer - Suplies an optional pointer to an output buffer into which
  1931. the output data will be copied. Whether or not the buffer is actually
  1932. optional is dependent on the IoControlCode.
  1933. nOutBufferSize - Supplies the length of the output buffer in bytes.
  1934. lpBytesReturned - Supplies a pointer to a dword which will receive the
  1935. actual length of the data returned in the output buffer.
  1936. lpOverlapped - An optional parameter that supplies an overlap structure to
  1937. be used with the request. If NULL or the handle was created without
  1938. FILE_FLAG_OVERLAPPED then the DeviceIoControl will not return until
  1939. the operation completes.
  1940. When lpOverlapped is supplied and FILE_FLAG_OVERLAPPED was specified
  1941. when the handle was created, DeviceIoControl may return
  1942. ERROR_IO_PENDING to allow the caller to continue processing while the
  1943. operation completes. The event (or File handle if hEvent == NULL) will
  1944. be set to the not signalled state before ERROR_IO_PENDING is
  1945. returned. The event will be set to the signalled state upon completion
  1946. of the request. GetOverlappedResult is used to determine the result
  1947. when ERROR_IO_PENDING is returned.
  1948. Return Value:
  1949. TRUE -- The operation was successful.
  1950. FALSE -- The operation failed. Extended error status is available using
  1951. GetLastError.
  1952. --*/
  1953. {
  1954. NTSTATUS Status;
  1955. BOOLEAN DevIoCtl;
  1956. // On terminal Services TS-app-server, only allow admins to eject media while connected remotely
  1957. if ( ( dwIoControlCode == IOCTL_STORAGE_EJECT_MEDIA ) ||
  1958. ( dwIoControlCode == IOCTL_DISK_EJECT_MEDIA ) ||
  1959. ( dwIoControlCode == FSCTL_DISMOUNT_VOLUME ) )
  1960. {
  1961. if ( (NtCurrentPeb()->SessionId != USER_SHARED_DATA->ActiveConsoleId))
  1962. {
  1963. BOOL TSAppCompatEnabled;
  1964. NTSTATUS Status;
  1965. Status = IsTSAppCompatEnabled(&TSAppCompatEnabled);
  1966. if (!NT_SUCCESS(Status)) {
  1967. BaseSetLastNTError(Status);
  1968. return FALSE;
  1969. }
  1970. if (TSAppCompatEnabled && !IsCallerAdminOrSystem()) {
  1971. BaseSetLastNTError(STATUS_ACCESS_DENIED);
  1972. return FALSE;
  1973. }
  1974. }
  1975. }
  1976. if ( dwIoControlCode >> 16 == FILE_DEVICE_FILE_SYSTEM ) {
  1977. DevIoCtl = FALSE;
  1978. }
  1979. else {
  1980. DevIoCtl = TRUE;
  1981. }
  1982. if ( ARGUMENT_PRESENT( lpOverlapped ) ) {
  1983. lpOverlapped->Internal = (DWORD)STATUS_PENDING;
  1984. if ( DevIoCtl ) {
  1985. Status = NtDeviceIoControlFile(
  1986. hDevice,
  1987. lpOverlapped->hEvent,
  1988. NULL, // APC routine
  1989. (ULONG_PTR)lpOverlapped->hEvent & 1 ? NULL : lpOverlapped,
  1990. (PIO_STATUS_BLOCK)&lpOverlapped->Internal,
  1991. dwIoControlCode, // IoControlCode
  1992. lpInBuffer, // Buffer for data to the FS
  1993. nInBufferSize,
  1994. lpOutBuffer, // OutputBuffer for data from the FS
  1995. nOutBufferSize // OutputBuffer Length
  1996. );
  1997. }
  1998. else {
  1999. Status = NtFsControlFile(
  2000. hDevice,
  2001. lpOverlapped->hEvent,
  2002. NULL, // APC routine
  2003. (ULONG_PTR)lpOverlapped->hEvent & 1 ? NULL : lpOverlapped,
  2004. (PIO_STATUS_BLOCK)&lpOverlapped->Internal,
  2005. dwIoControlCode, // IoControlCode
  2006. lpInBuffer, // Buffer for data to the FS
  2007. nInBufferSize,
  2008. lpOutBuffer, // OutputBuffer for data from the FS
  2009. nOutBufferSize // OutputBuffer Length
  2010. );
  2011. }
  2012. // handle warning value STATUS_BUFFER_OVERFLOW somewhat correctly
  2013. if ( !NT_ERROR(Status) && ARGUMENT_PRESENT(lpBytesReturned) ) {
  2014. try {
  2015. *lpBytesReturned = (DWORD)lpOverlapped->InternalHigh;
  2016. }
  2017. except(EXCEPTION_EXECUTE_HANDLER) {
  2018. *lpBytesReturned = 0;
  2019. }
  2020. }
  2021. if ( NT_SUCCESS(Status) && Status != STATUS_PENDING) {
  2022. return TRUE;
  2023. }
  2024. else {
  2025. BaseSetLastNTError(Status);
  2026. return FALSE;
  2027. }
  2028. }
  2029. else
  2030. {
  2031. IO_STATUS_BLOCK Iosb;
  2032. if ( DevIoCtl ) {
  2033. Status = NtDeviceIoControlFile(
  2034. hDevice,
  2035. NULL,
  2036. NULL, // APC routine
  2037. NULL, // APC Context
  2038. &Iosb,
  2039. dwIoControlCode, // IoControlCode
  2040. lpInBuffer, // Buffer for data to the FS
  2041. nInBufferSize,
  2042. lpOutBuffer, // OutputBuffer for data from the FS
  2043. nOutBufferSize // OutputBuffer Length
  2044. );
  2045. }
  2046. else {
  2047. Status = NtFsControlFile(
  2048. hDevice,
  2049. NULL,
  2050. NULL, // APC routine
  2051. NULL, // APC Context
  2052. &Iosb,
  2053. dwIoControlCode, // IoControlCode
  2054. lpInBuffer, // Buffer for data to the FS
  2055. nInBufferSize,
  2056. lpOutBuffer, // OutputBuffer for data from the FS
  2057. nOutBufferSize // OutputBuffer Length
  2058. );
  2059. }
  2060. if ( Status == STATUS_PENDING) {
  2061. // Operation must complete before return & Iosb destroyed
  2062. Status = NtWaitForSingleObject( hDevice, FALSE, NULL );
  2063. if ( NT_SUCCESS(Status)) {
  2064. Status = Iosb.Status;
  2065. }
  2066. }
  2067. if ( NT_SUCCESS(Status) ) {
  2068. *lpBytesReturned = (DWORD)Iosb.Information;
  2069. return TRUE;
  2070. }
  2071. else {
  2072. // handle warning value STATUS_BUFFER_OVERFLOW somewhat correctly
  2073. if ( !NT_ERROR(Status) ) {
  2074. *lpBytesReturned = (DWORD)Iosb.Information;
  2075. }
  2076. BaseSetLastNTError(Status);
  2077. return FALSE;
  2078. }
  2079. }
  2080. }
  2081. BOOL
  2082. WINAPI
  2083. CancelIo(
  2084. HANDLE hFile
  2085. )
  2086. /*++
  2087. Routine Description:
  2088. This routine cancels all of the outstanding I/O for the specified handle
  2089. for the specified file.
  2090. Arguments:
  2091. hFile - Supplies the handle to the file whose pending I/O is to be
  2092. canceled.
  2093. Return Value:
  2094. TRUE -- The operation was successful.
  2095. FALSE -- The operation failed. Extended error status is available using
  2096. GetLastError.
  2097. --*/
  2098. {
  2099. NTSTATUS Status;
  2100. IO_STATUS_BLOCK IoStatusBlock;
  2101. //
  2102. // Simply cancel the I/O for the specified file.
  2103. //
  2104. Status = NtCancelIoFile(hFile, &IoStatusBlock);
  2105. if ( NT_SUCCESS(Status) ) {
  2106. return TRUE;
  2107. }
  2108. else {
  2109. BaseSetLastNTError(Status);
  2110. return FALSE;
  2111. }
  2112. }
  2113. BOOL
  2114. WINAPI
  2115. ReadFileScatter(
  2116. HANDLE hFile,
  2117. FILE_SEGMENT_ELEMENT aSegementArray[],
  2118. DWORD nNumberOfBytesToRead,
  2119. LPDWORD lpReserved,
  2120. LPOVERLAPPED lpOverlapped
  2121. )
  2122. /*++
  2123. Routine Description:
  2124. Data can be read from a file using ReadFileScatter. The data
  2125. is then scatter to specified buffer segements.
  2126. This API is used to read data from a file. Data is read from the
  2127. file from the position indicated by the file pointer. After the
  2128. read completes, the file pointer is adjusted by the number of bytes
  2129. actually read. A return value of TRUE coupled with a bytes read of
  2130. 0 indicates that the file pointer was beyond the current end of the
  2131. file at the time of the read.
  2132. Arguments:
  2133. hFile - Supplies an open handle to a file that is to be read. The
  2134. file handle must have been created with GENERIC_READ access to
  2135. the file.
  2136. aSegementArray - Supplies a pointer an array of virtual segments.
  2137. A virtual segment is a memory buffer where part of the transferred data
  2138. should be placed. Segments are have a fix size of PAGE_SIZE
  2139. and must be aligned on a PAGE_SIZE boundary.
  2140. nNumberOfBytesToRead - Supplies the number of bytes to read from the file.
  2141. lpReserved - Reserved for now.
  2142. lpOverlapped - Optionally points to an OVERLAPPED structure to be used with the
  2143. request. If NULL then the transfer starts at the current file position
  2144. and ReadFile will not return until the operation completes.
  2145. If the handle hFile was created without specifying FILE_FLAG_OVERLAPPED
  2146. the file pointer is moved to the specified offset plus
  2147. lpNumberOfBytesRead before ReadFile returns. ReadFile will wait for the
  2148. request to complete before returning (it will not return
  2149. ERROR_IO_PENDING).
  2150. When FILE_FLAG_OVERLAPPED is specified, ReadFile may return
  2151. ERROR_IO_PENDING to allow the calling function to continue processing
  2152. while the operation completes. The event (or hFile if hEvent is NULL) will
  2153. be set to the signalled state upon completion of the request.
  2154. When the handle is created with FILE_FLAG_OVERLAPPED and lpOverlapped
  2155. is set to NULL, ReadFile will return ERROR_INVALID_PARAMTER because
  2156. the file offset is required.
  2157. Return Value:
  2158. TRUE - The operation was successul.
  2159. FALSE - The operation failed. Extended error status is available
  2160. using GetLastError.
  2161. --*/
  2162. {
  2163. NTSTATUS Status;
  2164. IO_STATUS_BLOCK IoStatusBlock;
  2165. LPDWORD lpNumberOfBytesRead = NULL;
  2166. if ( ARGUMENT_PRESENT(lpReserved) ||
  2167. !ARGUMENT_PRESENT( lpOverlapped )) {
  2168. SetLastError(ERROR_INVALID_PARAMETER);
  2169. return FALSE;
  2170. }
  2171. if (CONSOLE_HANDLE(hFile)) {
  2172. BaseSetLastNTError(STATUS_INVALID_HANDLE);
  2173. return FALSE;
  2174. }
  2175. if ( ARGUMENT_PRESENT(lpNumberOfBytesRead) ) {
  2176. *lpNumberOfBytesRead = 0;
  2177. }
  2178. if ( ARGUMENT_PRESENT( lpOverlapped ) ) {
  2179. LARGE_INTEGER Li;
  2180. lpOverlapped->Internal = (DWORD)STATUS_PENDING;
  2181. Li.LowPart = lpOverlapped->Offset;
  2182. Li.HighPart = lpOverlapped->OffsetHigh;
  2183. Status = NtReadFileScatter(
  2184. hFile,
  2185. lpOverlapped->hEvent,
  2186. NULL,
  2187. (ULONG_PTR)lpOverlapped->hEvent & 1 ? NULL : lpOverlapped,
  2188. (PIO_STATUS_BLOCK)&lpOverlapped->Internal,
  2189. aSegementArray,
  2190. nNumberOfBytesToRead,
  2191. &Li,
  2192. NULL
  2193. );
  2194. if ( NT_SUCCESS(Status) && Status != STATUS_PENDING) {
  2195. if ( ARGUMENT_PRESENT(lpNumberOfBytesRead) ) {
  2196. try {
  2197. *lpNumberOfBytesRead = (DWORD)lpOverlapped->InternalHigh;
  2198. }
  2199. except(EXCEPTION_EXECUTE_HANDLER) {
  2200. *lpNumberOfBytesRead = 0;
  2201. }
  2202. }
  2203. return TRUE;
  2204. }
  2205. else
  2206. if (Status == STATUS_END_OF_FILE) {
  2207. if ( ARGUMENT_PRESENT(lpNumberOfBytesRead) ) {
  2208. *lpNumberOfBytesRead = 0;
  2209. }
  2210. BaseSetLastNTError(Status);
  2211. return FALSE;
  2212. }
  2213. else {
  2214. BaseSetLastNTError(Status);
  2215. return FALSE;
  2216. }
  2217. }
  2218. else
  2219. {
  2220. Status = NtReadFileScatter(
  2221. hFile,
  2222. NULL,
  2223. NULL,
  2224. NULL,
  2225. &IoStatusBlock,
  2226. aSegementArray,
  2227. nNumberOfBytesToRead,
  2228. NULL,
  2229. NULL
  2230. );
  2231. if ( Status == STATUS_PENDING) {
  2232. // Operation must complete before return & IoStatusBlock destroyed
  2233. Status = NtWaitForSingleObject( hFile, FALSE, NULL );
  2234. if ( NT_SUCCESS(Status)) {
  2235. Status = IoStatusBlock.Status;
  2236. }
  2237. }
  2238. if ( NT_SUCCESS(Status) ) {
  2239. *lpNumberOfBytesRead = (DWORD)IoStatusBlock.Information;
  2240. return TRUE;
  2241. }
  2242. else
  2243. if (Status == STATUS_END_OF_FILE) {
  2244. *lpNumberOfBytesRead = 0;
  2245. return TRUE;
  2246. }
  2247. else {
  2248. if ( NT_WARNING(Status) ) {
  2249. *lpNumberOfBytesRead = (DWORD)IoStatusBlock.Information;
  2250. }
  2251. BaseSetLastNTError(Status);
  2252. return FALSE;
  2253. }
  2254. }
  2255. }
  2256. BOOL
  2257. WINAPI
  2258. WriteFileGather(
  2259. HANDLE hFile,
  2260. FILE_SEGMENT_ELEMENT aSegementArray[],
  2261. DWORD nNumberOfBytesToWrite,
  2262. LPDWORD lpReserved,
  2263. LPOVERLAPPED lpOverlapped
  2264. )
  2265. /*++
  2266. Routine Description:
  2267. Data can be written to a file using WriteFileGather. The data can
  2268. be in multple file segement buffers.
  2269. This API is used to write data to a file. Data is written to the
  2270. file from the position indicated by the file pointer. After the
  2271. write completes, the file pointer is adjusted by the number of bytes
  2272. actually written.
  2273. Unlike DOS, a NumberOfBytesToWrite value of zero does not truncate
  2274. or extend the file. If this function is required, SetEndOfFile
  2275. should be used.
  2276. Arguments:
  2277. hFile - Supplies an open handle to a file that is to be written. The
  2278. file handle must have been created with GENERIC_WRITE access to
  2279. the file.
  2280. aSegementArray - Supplies a pointer an array of virtual segments.
  2281. A virtual segment is a memory buffer where part of the transferred data
  2282. should be placed. Segments are have a fix size of PAGE_SIZE
  2283. and must be aligned on a PAGE_SIZE boundary. The number of
  2284. entries in the array must be equal to nNumberOfBytesToRead /
  2285. PAGE_SIZE.
  2286. nNumberOfBytesToWrite - Supplies the number of bytes to write to the
  2287. file. Unlike DOS, a value of zero is interpreted a null write.
  2288. lpReserved - Unused for now.
  2289. lpOverlapped - Optionally points to an OVERLAPPED structure to be
  2290. used with the request. If NULL then the transfer starts at the
  2291. current file position and WriteFileGather will not return until the
  2292. operation completes.
  2293. If the handle <hFile> was created without specifying
  2294. FILE_FLAG_OVERLAPPED the file pointer is moved to the specified
  2295. offset plus lpNumberOfBytesWritten before WriteFile returns.
  2296. WriteFile will wait for the request to complete before returning
  2297. (it will not set ERROR_IO_PENDING).
  2298. When FILE_FLAG_OVERLAPPED is specified, WriteFile may return
  2299. ERROR_IO_PENDING to allow the calling function to continue processing
  2300. while the operation completes. The event (or hFile if hEvent is NULL) will
  2301. be set to the signalled state upon completion of the request.
  2302. When the handle is created with FILE_FLAG_OVERLAPPED and lpOverlapped
  2303. is set to NULL, WriteFile will return ERROR_INVALID_PARAMTER because
  2304. the file offset is required.
  2305. Return Value:
  2306. TRUE - The operation was a success.
  2307. FALSE - The operation failed. Extended error status is
  2308. available using GetLastError.
  2309. --*/
  2310. {
  2311. NTSTATUS Status;
  2312. IO_STATUS_BLOCK IoStatusBlock;
  2313. LPDWORD lpNumberOfBytesWritten = NULL;
  2314. if ( ARGUMENT_PRESENT(lpReserved) ||
  2315. !ARGUMENT_PRESENT( lpOverlapped )) {
  2316. SetLastError(ERROR_INVALID_PARAMETER);
  2317. return FALSE;
  2318. }
  2319. if (CONSOLE_HANDLE(hFile)) {
  2320. BaseSetLastNTError(STATUS_INVALID_HANDLE);
  2321. return FALSE;
  2322. }
  2323. if ( ARGUMENT_PRESENT(lpNumberOfBytesWritten) ) {
  2324. *lpNumberOfBytesWritten = 0;
  2325. }
  2326. if ( ARGUMENT_PRESENT( lpOverlapped ) ) {
  2327. LARGE_INTEGER Li;
  2328. lpOverlapped->Internal = (DWORD)STATUS_PENDING;
  2329. Li.LowPart = lpOverlapped->Offset;
  2330. Li.HighPart = lpOverlapped->OffsetHigh;
  2331. Status = NtWriteFileGather(
  2332. hFile,
  2333. lpOverlapped->hEvent,
  2334. NULL,
  2335. (ULONG_PTR)lpOverlapped->hEvent & 1 ? NULL : lpOverlapped,
  2336. (PIO_STATUS_BLOCK)&lpOverlapped->Internal,
  2337. aSegementArray,
  2338. nNumberOfBytesToWrite,
  2339. &Li,
  2340. NULL
  2341. );
  2342. if ( !NT_ERROR(Status) && Status != STATUS_PENDING) {
  2343. if ( ARGUMENT_PRESENT(lpNumberOfBytesWritten) ) {
  2344. try {
  2345. *lpNumberOfBytesWritten = (DWORD)lpOverlapped->InternalHigh;
  2346. }
  2347. except(EXCEPTION_EXECUTE_HANDLER) {
  2348. *lpNumberOfBytesWritten = 0;
  2349. }
  2350. }
  2351. return TRUE;
  2352. }
  2353. else {
  2354. BaseSetLastNTError(Status);
  2355. return FALSE;
  2356. }
  2357. }
  2358. else {
  2359. Status = NtWriteFileGather(
  2360. hFile,
  2361. NULL,
  2362. NULL,
  2363. NULL,
  2364. &IoStatusBlock,
  2365. aSegementArray,
  2366. nNumberOfBytesToWrite,
  2367. NULL,
  2368. NULL
  2369. );
  2370. if ( Status == STATUS_PENDING) {
  2371. // Operation must complete before return & IoStatusBlock destroyed
  2372. Status = NtWaitForSingleObject( hFile, FALSE, NULL );
  2373. if ( NT_SUCCESS(Status)) {
  2374. Status = IoStatusBlock.Status;
  2375. }
  2376. }
  2377. if ( NT_SUCCESS(Status)) {
  2378. *lpNumberOfBytesWritten = (DWORD)IoStatusBlock.Information;
  2379. return TRUE;
  2380. }
  2381. else {
  2382. if ( NT_WARNING(Status) ) {
  2383. *lpNumberOfBytesWritten = (DWORD)IoStatusBlock.Information;
  2384. }
  2385. BaseSetLastNTError(Status);
  2386. return FALSE;
  2387. }
  2388. }
  2389. }
  2390. BOOL
  2391. APIENTRY
  2392. SetFileValidData(
  2393. IN HANDLE hFile,
  2394. IN LONGLONG ValidDataLength
  2395. )
  2396. /*++
  2397. Routine Description:
  2398. SetFileValidData is used to set the valid data length for the given file.
  2399. Arguments:
  2400. hFile - Supplies an open handle to a file whose type valid data
  2401. length is to be set
  2402. ValidDataLength - Supplies the desired valid data length
  2403. Return Value:
  2404. TRUE - The operation was a success.
  2405. FALSE - The operation failed. Extended error status is
  2406. available using GetLastError.
  2407. --*/
  2408. {
  2409. NTSTATUS Status;
  2410. IO_STATUS_BLOCK IoStatusBlock;
  2411. FILE_VALID_DATA_LENGTH_INFORMATION ValidDataInfo;
  2412. if (CONSOLE_HANDLE(hFile)) {
  2413. BaseSetLastNTError(STATUS_INVALID_HANDLE);
  2414. return FALSE;
  2415. }
  2416. ValidDataInfo.ValidDataLength.QuadPart = ValidDataLength;
  2417. Status = NtSetInformationFile(
  2418. hFile,
  2419. &IoStatusBlock,
  2420. &ValidDataInfo,
  2421. sizeof(FILE_VALID_DATA_LENGTH_INFORMATION),
  2422. FileValidDataLengthInformation
  2423. );
  2424. if (!NT_SUCCESS(Status)) {
  2425. BaseSetLastNTError(Status);
  2426. return FALSE;
  2427. }
  2428. return TRUE;
  2429. }
  2430. BOOL
  2431. APIENTRY
  2432. SetFileShortNameW(
  2433. IN HANDLE hFile,
  2434. IN LPCWSTR lpShortName
  2435. )
  2436. /*++
  2437. Routine Description:
  2438. SetFileShortNameW is used to set the short name for the given file.
  2439. Arguments:
  2440. hFile - Supplies an open handle to a file whose short name is to be changed
  2441. lpShortName - Supplies the desired short name
  2442. Return Value:
  2443. TRUE - The operation was a success.
  2444. FALSE - The operation failed. Extended error status is
  2445. available using GetLastError.
  2446. --*/
  2447. {
  2448. NTSTATUS Status;
  2449. IO_STATUS_BLOCK IoStatusBlock;
  2450. PFILE_NAME_INFORMATION FileNameInfo;
  2451. DWORD FileNameInfoSize;
  2452. DWORD FileInformationClass;
  2453. if (CONSOLE_HANDLE(hFile)) {
  2454. BaseSetLastNTError(STATUS_INVALID_HANDLE);
  2455. return FALSE;
  2456. }
  2457. if (!ARGUMENT_PRESENT(lpShortName)) {
  2458. SetLastError(ERROR_INVALID_PARAMETER);
  2459. return FALSE;
  2460. }
  2461. FileNameInfoSize = FIELD_OFFSET(FILE_NAME_INFORMATION, FileName) + ((wcslen(lpShortName)+1)*sizeof(WCHAR));
  2462. FileNameInfo = RtlAllocateHeap( RtlProcessHeap(), MAKE_TAG(TMP_TAG), FileNameInfoSize );
  2463. if (!FileNameInfo) {
  2464. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2465. return FALSE;
  2466. }
  2467. FileNameInfo->FileNameLength = wcslen(lpShortName) * sizeof(WCHAR);
  2468. wcscpy( FileNameInfo->FileName, lpShortName );
  2469. Status = NtSetInformationFile(
  2470. hFile,
  2471. &IoStatusBlock,
  2472. FileNameInfo,
  2473. FileNameInfoSize,
  2474. FileShortNameInformation
  2475. );
  2476. RtlFreeHeap( RtlProcessHeap(), 0, FileNameInfo );
  2477. if (!NT_SUCCESS(Status)) {
  2478. BaseSetLastNTError(Status);
  2479. return FALSE;
  2480. }
  2481. FileInformationClass = FileShortNameInformation;
  2482. if ((FileInformationClass == FileEndOfFileInformation) ||
  2483. (FileInformationClass == FileAllocationInformation) ||
  2484. (FileInformationClass == FilePositionInformation))
  2485. {
  2486. return FALSE;
  2487. }
  2488. return TRUE;
  2489. }
  2490. BOOL
  2491. APIENTRY
  2492. SetFileShortNameA(
  2493. IN HANDLE hFile,
  2494. IN LPCSTR lpShortName
  2495. )
  2496. /*++
  2497. Routine Description:
  2498. SetFileShortNameW is used to set the short name for the given file.
  2499. Arguments:
  2500. hFile - Supplies an open handle to a file whose short name is to be changed
  2501. lpShortName - Supplies the desired short name
  2502. Return Value:
  2503. TRUE - The operation was a success.
  2504. FALSE - The operation failed. Extended error status is
  2505. available using GetLastError.
  2506. --*/
  2507. {
  2508. PUNICODE_STRING Unicode;
  2509. Unicode = Basep8BitStringToStaticUnicodeString( lpShortName );
  2510. if (Unicode == NULL) {
  2511. return FALSE;
  2512. }
  2513. return ( SetFileShortNameW(
  2514. hFile,
  2515. (LPCWSTR)Unicode->Buffer
  2516. )
  2517. );
  2518. }
  2519. BOOLEAN
  2520. Wow64EnableWow64FsRedirection (
  2521. IN BOOLEAN Wow64FsEnableRedirection
  2522. )
  2523. /*++
  2524. Routine Description:
  2525. This function enables/disables Wow64 file system redirection.
  2526. Wow64 redirects all accesses to %windir%\system32 to %windir%\syswow64.
  2527. This API is useful for 32-bit applications which want to gain access to the
  2528. native system32 directory. By default, Wow64 file system redirection is enabled.
  2529. File redirection is only affected for the thread calling this API.
  2530. Note : You must enable file system redirection after disabling it. Once you have
  2531. a file handle, you must enable file system redirection back.
  2532. Example:
  2533. BOOL bRet = Wow64EnableWow64FsRedirection (FALSE);
  2534. if (bRet == TRUE) {
  2535. //
  2536. // Open the file handle
  2537. //
  2538. CreateFile (..."c:\\windows\\system32\\notepad.exe"...)
  2539. //
  2540. // Enable Wow64 file system redirection.
  2541. //
  2542. Wow64EnableWow64FsRedirection (TRUE);
  2543. }
  2544. //
  2545. // Use the file handle
  2546. //
  2547. Arguments:
  2548. Wow64FsEnableRedirection - Boolean to indicate whether to enable Wow64 file system
  2549. redirection. Specify FALSE if you want to disable Wow64 file system redirection,
  2550. otherwise TRUE to enable it.
  2551. Return Value:
  2552. TRUE - The operation was successul.
  2553. FALSE - The operation failed. Extended error status is available
  2554. using GetLastError.
  2555. --*/
  2556. {
  2557. NTSTATUS NtStatus;
  2558. NtStatus = RtlWow64EnableFsRedirection (Wow64FsEnableRedirection);
  2559. if (!NT_SUCCESS (NtStatus)) {
  2560. BaseSetLastNTError (NtStatus);
  2561. return FALSE;
  2562. }
  2563. return TRUE;
  2564. }