Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1897 lines
47 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. tfat.c
  5. Abstract:
  6. Test program for the Fat File system
  7. Author:
  8. Gary Kimura [GaryKi] 24-May-1989
  9. Revision History:
  10. --*/
  11. #include <stdio.h>
  12. #include <string.h>
  13. //#include <ctype.h>
  14. #define toupper(C) ((C) >= 'a' && (C) <= 'z' ? (C) - ('a' - 'A') : (C))
  15. #define isdigit(C) ((C) >= '0' && (C) <= '9')
  16. #include <nt.h>
  17. #include <ntrtl.h>
  18. #ifndef SIMULATOR
  19. ULONG IoInitIncludeDevices;
  20. #endif // SIMULATOR
  21. #define simprintf(X,Y) {if (!Silent) {DbgPrint(X,Y);} }
  22. BOOLEAN Silent;
  23. //
  24. // The buffer size must be a multiple of 512
  25. //
  26. #define BUFFERSIZE 1024
  27. UCHAR Buffer[BUFFERSIZE];
  28. HANDLE CurrentProcessHandle;
  29. CHAR Prefix[32];
  30. ULONG WriteThrough = 0;
  31. VOID
  32. PrintTime (
  33. IN PLARGE_INTEGER Time
  34. );
  35. VOID
  36. WaitForSingleObjectError(
  37. IN NTSTATUS Status
  38. );
  39. VOID
  40. CreateFileError(
  41. IN NTSTATUS Status,
  42. PCHAR File
  43. );
  44. VOID
  45. OpenFileError(
  46. IN NTSTATUS Status,
  47. PCHAR File
  48. );
  49. VOID
  50. ReadFileError(
  51. IN NTSTATUS Status
  52. );
  53. VOID
  54. WriteFileError(
  55. IN NTSTATUS Status
  56. );
  57. VOID
  58. CheckIoStatus(
  59. IN PIO_STATUS_BLOCK IoStatus,
  60. IN ULONG Length,
  61. IN BOOLEAN Read
  62. );
  63. VOID
  64. SetInformationFileError(
  65. IN NTSTATUS Status
  66. );
  67. VOID
  68. QueryInformationFileError(
  69. IN NTSTATUS Status
  70. );
  71. VOID
  72. SetVolumeInformationFileError(
  73. IN NTSTATUS Status
  74. );
  75. VOID
  76. QueryVolumeInformationFileError(
  77. IN NTSTATUS Status
  78. );
  79. VOID
  80. CloseError(
  81. IN NTSTATUS Status
  82. );
  83. VOID
  84. IoStatusError(
  85. IN NTSTATUS Status
  86. );
  87. VOID
  88. main(
  89. int argc,
  90. char *argv[],
  91. char *envp[]
  92. )
  93. {
  94. NTSTATUS Status;
  95. ULONG i;
  96. ULONG Count;
  97. VOID FatMain();
  98. CHAR Device[8];
  99. CurrentProcessHandle = NtCurrentProcess();
  100. Status = STATUS_SUCCESS;
  101. // DbgPrint( "Entering User Mode Test Program\n" );
  102. // DbgPrint( "argc: %ld\n", argc );
  103. // if (argv != NULL) {
  104. // for (i=0; i<argc; i++) {
  105. // DbgPrint( "argv[ %ld ]: %s\n", i, argv[ i ] );
  106. // }
  107. // }
  108. // if (envp != NULL) {
  109. // i = 0;
  110. // while (*envp) {
  111. // DbgPrint( "envp[ %02ld ]: %s\n", i++, *envp++ );
  112. // }
  113. // }
  114. if (argc > 1) {
  115. Count = 0;
  116. for (i = 0; isdigit(argv[1][i]); i += 1) {
  117. Count = Count * 10 + argv[1][i] - '0';
  118. }
  119. } else {
  120. Count = 1;
  121. }
  122. if (argc > 2) {
  123. strcpy( Device, argv[2]);
  124. } else {
  125. strcpy( Device, "\\A:\\");
  126. }
  127. if (argc > 3) {
  128. WriteThrough = FILE_WRITE_THROUGH;
  129. }
  130. if (toupper(Device[1]) != Device[1]) {
  131. Device[1] = (CHAR)toupper(Device[1]);
  132. Silent = TRUE;
  133. } else {
  134. Silent = FALSE;
  135. }
  136. FatMain(Count, Device);
  137. // DbgPrint( "Exiting User Mode Test Program with Status = %X\n", Status );
  138. NtTerminateProcess( CurrentProcessHandle, Status );
  139. }
  140. VOID
  141. FatMain(
  142. IN ULONG LoopCount,
  143. IN CHAR Device[]
  144. )
  145. {
  146. VOID Upcase();
  147. VOID Append(),Chmode(),Copy(),Create(),DebugLevel(),Delete();
  148. VOID Directory(),Mkdir(),Query(),QVolume(),Rename();
  149. VOID SVolume(),Type(),Quit();
  150. CHAR Str[64];
  151. CHAR Str2[64];
  152. CHAR LoopStr[64];
  153. ULONG i;
  154. LARGE_INTEGER Time;
  155. DbgPrint("FatMain %d\n", LoopCount);
  156. NtQuerySystemTime(&Time);
  157. strcpy( Prefix, Device); // "\\A:\\";
  158. Prefix[12] = 0;
  159. RtlIntegerToChar((ULONG)NtCurrentTeb()->ClientId.UniqueProcess, 16, -8, &Prefix[4]);
  160. Mkdir( Prefix );
  161. Directory( Device );
  162. Directory( Prefix );
  163. for (i = 0; i < LoopCount; i += 1) {
  164. NtQuerySystemTime(&Time);
  165. strcpy(LoopStr, "Start loop xxxxxxxx ");
  166. RtlIntegerToChar(i, 16, -8, &LoopStr[11]);
  167. strcat( LoopStr, Prefix );
  168. DbgPrint(LoopStr);
  169. DbgPrint("\n");
  170. //
  171. // Create new log
  172. //
  173. strcpy( Str2, "\\" ); RtlIntegerToChar(i, 16, -8, &Str2[1]); Str2[9] = 0;
  174. strcpy( Str, Prefix ); Create( strcat( Str, Str2 ), i);
  175. //
  176. // Delete last log file if i > 0
  177. //
  178. if (i > 0) {
  179. strcpy( Str2, "\\" ); RtlIntegerToChar(i-1, 16, -8, &Str2[1]); Str2[9] = 0;
  180. strcpy( Str, Prefix ); Delete( strcat( Str, Str2 ) );
  181. }
  182. //
  183. // Create some new files
  184. //
  185. strcpy( Str, Prefix ); Create( strcat( Str, "\\0.tmp" ), 0 );
  186. strcpy( Str, Prefix ); Create( strcat( Str, "\\1.tmp" ), 1 );
  187. strcpy( Str, Prefix ); Create( strcat( Str, "\\511.tmp" ), 511 );
  188. strcpy( Str, Prefix ); Create( strcat( Str, "\\512.tmp" ), 512 );
  189. strcpy( Str, Prefix ); Create( strcat( Str, "\\513.tmp" ), 513 );
  190. strcpy( Str, Prefix ); Create( strcat( Str, "\\1023.tmp" ), 1023 );
  191. strcpy( Str, Prefix ); Create( strcat( Str, "\\1024.tmp" ), 1024 );
  192. strcpy( Str, Prefix ); Create( strcat( Str, "\\1025.tmp" ), 1025 );
  193. strcpy( Str, Prefix ); Create( strcat( Str, "\\4095.tmp" ), 4095 );
  194. strcpy( Str, Prefix ); Create( strcat( Str, "\\4096.tmp" ), 4096 );
  195. strcpy( Str, Prefix ); Create( strcat( Str, "\\4097.tmp" ), 4097 );
  196. strcpy( Str, Prefix ); Create( strcat( Str, "\\8191.tmp" ), 8191 );
  197. strcpy( Str, Prefix ); Create( strcat( Str, "\\8192.tmp" ), 8192 );
  198. strcpy( Str, Prefix ); Create( strcat( Str, "\\8193.tmp" ), 8193 );
  199. Directory( Device );
  200. Directory( Prefix );
  201. strcpy( Str, Prefix ); strcpy( Str2, Prefix ); Copy( strcat( Str, "\\0.tmp" ), strcat( Str2, "\\0.tmq" ) );
  202. strcpy( Str, Prefix ); strcpy( Str2, Prefix ); Copy( strcat( Str, "\\1.tmp" ), strcat( Str2, "\\1.tmq" ) );
  203. strcpy( Str, Prefix ); strcpy( Str2, Prefix ); Copy( strcat( Str, "\\511.tmp" ), strcat( Str2, "\\511.tmq" ) );
  204. strcpy( Str, Prefix ); strcpy( Str2, Prefix ); Copy( strcat( Str, "\\512.tmp" ), strcat( Str2, "\\512.tmq" ) );
  205. strcpy( Str, Prefix ); strcpy( Str2, Prefix ); Copy( strcat( Str, "\\513.tmp" ), strcat( Str2, "\\513.tmq" ) );
  206. strcpy( Str, Prefix ); strcpy( Str2, Prefix ); Copy( strcat( Str, "\\1023.tmp" ), strcat( Str2, "\\1023.tmq" ) );
  207. strcpy( Str, Prefix ); strcpy( Str2, Prefix ); Copy( strcat( Str, "\\1024.tmp" ), strcat( Str2, "\\1024.tmq" ) );
  208. strcpy( Str, Prefix ); strcpy( Str2, Prefix ); Copy( strcat( Str, "\\1025.tmp" ), strcat( Str2, "\\1025.tmq" ) );
  209. strcpy( Str, Prefix ); strcpy( Str2, Prefix ); Copy( strcat( Str, "\\4095.tmp" ), strcat( Str2, "\\4095.tmq" ) );
  210. strcpy( Str, Prefix ); strcpy( Str2, Prefix ); Copy( strcat( Str, "\\4096.tmp" ), strcat( Str2, "\\4096.tmq" ) );
  211. strcpy( Str, Prefix ); strcpy( Str2, Prefix ); Copy( strcat( Str, "\\4097.tmp" ), strcat( Str2, "\\4097.tmq" ) );
  212. strcpy( Str, Prefix ); strcpy( Str2, Prefix ); Copy( strcat( Str, "\\8191.tmp" ), strcat( Str2, "\\8191.tmq" ) );
  213. strcpy( Str, Prefix ); strcpy( Str2, Prefix ); Copy( strcat( Str, "\\8192.tmp" ), strcat( Str2, "\\8192.tmq" ) );
  214. strcpy( Str, Prefix ); strcpy( Str2, Prefix ); Copy( strcat( Str, "\\8193.tmp" ), strcat( Str2, "\\8193.tmq" ) );
  215. Directory( Device );
  216. Directory( Prefix );
  217. strcpy( Str, Prefix ); strcpy( Str2, Prefix ); Append( strcat( Str, "\\0.tmp" ), strcat( Str2, "\\0.tmq" ) );
  218. strcpy( Str, Prefix ); strcpy( Str2, Prefix ); Append( strcat( Str, "\\1.tmp" ), strcat( Str2, "\\1.tmq" ) );
  219. strcpy( Str, Prefix ); strcpy( Str2, Prefix ); Append( strcat( Str, "\\511.tmp" ), strcat( Str2, "\\511.tmq" ) );
  220. strcpy( Str, Prefix ); strcpy( Str2, Prefix ); Append( strcat( Str, "\\512.tmp" ), strcat( Str2, "\\512.tmq" ) );
  221. strcpy( Str, Prefix ); strcpy( Str2, Prefix ); Append( strcat( Str, "\\513.tmp" ), strcat( Str2, "\\513.tmq" ) );
  222. strcpy( Str, Prefix ); strcpy( Str2, Prefix ); Append( strcat( Str, "\\1023.tmp" ), strcat( Str2, "\\1023.tmq" ) );
  223. strcpy( Str, Prefix ); strcpy( Str2, Prefix ); Append( strcat( Str, "\\1024.tmp" ), strcat( Str2, "\\1024.tmq" ) );
  224. strcpy( Str, Prefix ); strcpy( Str2, Prefix ); Append( strcat( Str, "\\1025.tmp" ), strcat( Str2, "\\1025.tmq" ) );
  225. strcpy( Str, Prefix ); strcpy( Str2, Prefix ); Append( strcat( Str, "\\4095.tmp" ), strcat( Str2, "\\4095.tmq" ) );
  226. strcpy( Str, Prefix ); strcpy( Str2, Prefix ); Append( strcat( Str, "\\4096.tmp" ), strcat( Str2, "\\4096.tmq" ) );
  227. strcpy( Str, Prefix ); strcpy( Str2, Prefix ); Append( strcat( Str, "\\4097.tmp" ), strcat( Str2, "\\4097.tmq" ) );
  228. strcpy( Str, Prefix ); strcpy( Str2, Prefix ); Append( strcat( Str, "\\8191.tmp" ), strcat( Str2, "\\8191.tmq" ) );
  229. strcpy( Str, Prefix ); strcpy( Str2, Prefix ); Append( strcat( Str, "\\8192.tmp" ), strcat( Str2, "\\8192.tmq" ) );
  230. strcpy( Str, Prefix ); strcpy( Str2, Prefix ); Append( strcat( Str, "\\8193.tmp" ), strcat( Str2, "\\8193.tmq" ) );
  231. Directory( Device );
  232. Directory( Prefix );
  233. strcpy( Str, Prefix ); Delete( strcat( Str, "\\0.tmp" ) );
  234. strcpy( Str, Prefix ); Delete( strcat( Str, "\\1.tmp" ) );
  235. strcpy( Str, Prefix ); Delete( strcat( Str, "\\511.tmp" ) );
  236. strcpy( Str, Prefix ); Delete( strcat( Str, "\\512.tmp" ) );
  237. strcpy( Str, Prefix ); Delete( strcat( Str, "\\513.tmp" ) );
  238. strcpy( Str, Prefix ); Delete( strcat( Str, "\\1023.tmp" ) );
  239. strcpy( Str, Prefix ); Delete( strcat( Str, "\\1024.tmp" ) );
  240. strcpy( Str, Prefix ); Delete( strcat( Str, "\\1025.tmp" ) );
  241. strcpy( Str, Prefix ); Delete( strcat( Str, "\\4095.tmp" ) );
  242. strcpy( Str, Prefix ); Delete( strcat( Str, "\\4096.tmp" ) );
  243. strcpy( Str, Prefix ); Delete( strcat( Str, "\\4097.tmp" ) );
  244. strcpy( Str, Prefix ); Delete( strcat( Str, "\\8191.tmp" ) );
  245. strcpy( Str, Prefix ); Delete( strcat( Str, "\\8192.tmp" ) );
  246. strcpy( Str, Prefix ); Delete( strcat( Str, "\\8193.tmp" ) );
  247. Directory( Device );
  248. Directory( Prefix );
  249. }
  250. DbgPrint( "Done\n" );
  251. NtQuerySystemTime(&Time);
  252. Quit();
  253. return; // TRUE;
  254. }
  255. VOID
  256. Upcase (
  257. IN OUT PUCHAR String
  258. )
  259. {
  260. while (*String != '\0') {
  261. *String = (UCHAR)toupper(*String);
  262. String += 1;
  263. }
  264. }
  265. VOID Append(
  266. IN PCHAR FromName,
  267. IN PCHAR ToName
  268. )
  269. {
  270. NTSTATUS Status;
  271. HANDLE FromFileHandle;
  272. HANDLE ToFileHandle;
  273. OBJECT_ATTRIBUTES ObjectAttributes;
  274. STRING NameString;
  275. IO_STATUS_BLOCK IoStatus;
  276. LARGE_INTEGER ByteOffset;
  277. LARGE_INTEGER EofOffset;
  278. ULONG LogLsn;
  279. simprintf("Append ", 0);
  280. simprintf(FromName, 0);
  281. simprintf(" ", 0);
  282. simprintf(ToName, 0);
  283. simprintf("\n", 0);
  284. //
  285. // Open the From file for read access
  286. //
  287. RtlInitString( &NameString, FromName );
  288. InitializeObjectAttributes( &ObjectAttributes, &NameString, 0, NULL, NULL );
  289. if (!NT_SUCCESS(Status = NtOpenFile( &FromFileHandle,
  290. FILE_READ_DATA | SYNCHRONIZE,
  291. &ObjectAttributes,
  292. &IoStatus,
  293. 0L,
  294. WriteThrough ))) {
  295. OpenFileError( Status , FromName );
  296. return;
  297. }
  298. //
  299. // Open the To file for write access
  300. //
  301. RtlInitString( &NameString, ToName );
  302. InitializeObjectAttributes( &ObjectAttributes, &NameString, 0, NULL, NULL );
  303. if (!NT_SUCCESS(Status = NtOpenFile( &ToFileHandle,
  304. FILE_WRITE_DATA | SYNCHRONIZE,
  305. &ObjectAttributes,
  306. &IoStatus,
  307. 0L,
  308. WriteThrough ))) {
  309. OpenFileError( Status , ToName );
  310. return;
  311. }
  312. //
  313. // Now append the files
  314. //
  315. ByteOffset = LiFromLong( 0 );
  316. EofOffset = LiFromLong( FILE_WRITE_TO_END_OF_FILE );
  317. for (LogLsn = 0; TRUE; LogLsn += BUFFERSIZE/512) {
  318. ULONG ReadLength;
  319. //
  320. // Read the next logical sectors in
  321. //
  322. ByteOffset.LowPart = LogLsn * 512;
  323. if (!NT_SUCCESS(Status = NtReadFile( FromFileHandle,
  324. (HANDLE)NULL,
  325. (PIO_APC_ROUTINE)NULL,
  326. (PVOID)NULL,
  327. &IoStatus,
  328. Buffer,
  329. BUFFERSIZE,
  330. &ByteOffset,
  331. (PULONG) NULL ))) {
  332. if (Status == STATUS_END_OF_FILE) {
  333. break;
  334. }
  335. ReadFileError( Status );
  336. break;
  337. }
  338. if (!NT_SUCCESS( Status = NtWaitForSingleObject( FromFileHandle, TRUE, NULL))) {
  339. // NtPartyByNumber(50);
  340. WaitForSingleObjectError( Status );
  341. return;
  342. }
  343. //
  344. // Check how the read turned out
  345. //
  346. if (IoStatus.Status == STATUS_END_OF_FILE) {
  347. break;
  348. }
  349. CheckIoStatus( &IoStatus, BUFFERSIZE, TRUE );
  350. if (!NT_SUCCESS(IoStatus.Status)) {
  351. break;
  352. }
  353. //
  354. // Append the sectors to the To file
  355. //
  356. ReadLength = IoStatus.Information;
  357. if (!NT_SUCCESS(Status = NtWriteFile( ToFileHandle,
  358. (HANDLE)NULL,
  359. (PIO_APC_ROUTINE)NULL,
  360. (PVOID)NULL,
  361. &IoStatus,
  362. Buffer,
  363. IoStatus.Information,
  364. &EofOffset,
  365. (PULONG) NULL ))) {
  366. WriteFileError( Status );
  367. return;
  368. }
  369. if (!NT_SUCCESS(Status = NtWaitForSingleObject( ToFileHandle, TRUE, NULL))) {
  370. // NtPartyByNumber(50);
  371. WaitForSingleObjectError( Status );
  372. return;
  373. }
  374. //
  375. // Check how the write turned out
  376. //
  377. CheckIoStatus( &IoStatus, ReadLength, FALSE );
  378. if (!NT_SUCCESS(IoStatus.Status)) {
  379. IoStatusError( IoStatus.Status );
  380. break;
  381. }
  382. //
  383. // If we didn't read or write a full buffer then the copy is done
  384. //
  385. if (IoStatus.Information < BUFFERSIZE) {
  386. break;
  387. }
  388. }
  389. if (!NT_SUCCESS(IoStatus.Status) && (IoStatus.Status != STATUS_END_OF_FILE)) {
  390. IoStatusError( IoStatus.Status );
  391. }
  392. //
  393. // Close both files
  394. //
  395. if (!NT_SUCCESS(Status = NtClose( FromFileHandle ))) {
  396. CloseError( Status );
  397. }
  398. if (!NT_SUCCESS(Status = NtClose( ToFileHandle ))) {
  399. CloseError( Status );
  400. }
  401. //
  402. // And return to our caller
  403. //
  404. return;
  405. }
  406. VOID Chmode(
  407. IN PCHAR Attrib,
  408. IN PCHAR String
  409. )
  410. {
  411. NTSTATUS Status;
  412. HANDLE FileHandle;
  413. OBJECT_ATTRIBUTES ObjectAttributes;
  414. STRING NameString;
  415. IO_STATUS_BLOCK IoStatus;
  416. ULONG FileAttribute;
  417. //
  418. // Get the attribute
  419. //
  420. Upcase( (PUCHAR)Attrib );
  421. //
  422. // Get the filename
  423. //
  424. simprintf("Chmode", 0);
  425. simprintf(String, 0);
  426. simprintf(" ", 0);
  427. simprintf(Attrib, 0);
  428. simprintf("\n", 0);
  429. //
  430. // Decode the attributes
  431. //
  432. FileAttribute = 0;
  433. if (strpbrk(Attrib,"N") != NULL) {FileAttribute |= FILE_ATTRIBUTE_NORMAL;}
  434. if (strpbrk(Attrib,"R") != NULL) {FileAttribute |= FILE_ATTRIBUTE_READONLY;}
  435. if (strpbrk(Attrib,"H") != NULL) {FileAttribute |= FILE_ATTRIBUTE_HIDDEN;}
  436. if (strpbrk(Attrib,"S") != NULL) {FileAttribute |= FILE_ATTRIBUTE_SYSTEM;}
  437. if (strpbrk(Attrib,"A") != NULL) {FileAttribute |= FILE_ATTRIBUTE_ARCHIVE;}
  438. //
  439. // Open the file for write attributes access
  440. //
  441. RtlInitString( &NameString, String );
  442. InitializeObjectAttributes( &ObjectAttributes, &NameString, 0, NULL, NULL );
  443. if (!NT_SUCCESS(Status = NtOpenFile( &FileHandle,
  444. FILE_WRITE_ATTRIBUTES | SYNCHRONIZE,
  445. &ObjectAttributes,
  446. &IoStatus,
  447. 0L,
  448. WriteThrough ))) {
  449. OpenFileError( Status , String );
  450. return;
  451. }
  452. //
  453. // Change the file attributes
  454. //
  455. ((PFILE_BASIC_INFORMATION)&Buffer[0])->CreationTime.HighPart = 0;
  456. ((PFILE_BASIC_INFORMATION)&Buffer[0])->CreationTime.LowPart = 0;
  457. ((PFILE_BASIC_INFORMATION)&Buffer[0])->LastAccessTime.HighPart = 0;
  458. ((PFILE_BASIC_INFORMATION)&Buffer[0])->LastAccessTime.LowPart = 0;
  459. ((PFILE_BASIC_INFORMATION)&Buffer[0])->LastWriteTime.HighPart = 0;
  460. ((PFILE_BASIC_INFORMATION)&Buffer[0])->LastWriteTime.LowPart = 0;
  461. ((PFILE_BASIC_INFORMATION)&Buffer[0])->FileAttributes = FileAttribute;
  462. if (!NT_SUCCESS(Status = NtSetInformationFile( FileHandle,
  463. &IoStatus,
  464. Buffer,
  465. sizeof(FILE_BASIC_INFORMATION),
  466. FileBasicInformation))) {
  467. SetInformationFileError( Status );
  468. }
  469. //
  470. // Now close the file
  471. //
  472. if (!NT_SUCCESS(Status = NtClose( FileHandle ))) {
  473. CloseError( Status );
  474. }
  475. //
  476. // And return to our caller
  477. //
  478. return;
  479. }
  480. VOID Copy(
  481. IN PCHAR FromName,
  482. IN PCHAR ToName
  483. )
  484. {
  485. NTSTATUS Status;
  486. HANDLE FromFileHandle;
  487. HANDLE ToFileHandle;
  488. OBJECT_ATTRIBUTES ObjectAttributes;
  489. STRING NameString;
  490. IO_STATUS_BLOCK IoStatus;
  491. LARGE_INTEGER FromFileAllocation;
  492. LARGE_INTEGER ByteOffset;
  493. ULONG LogLsn;
  494. //
  495. // Get both file names
  496. //
  497. simprintf("Copy ", 0);
  498. simprintf(FromName, 0);
  499. simprintf(" ", 0);
  500. simprintf(ToName, 0);
  501. simprintf("\n", 0);
  502. //
  503. // Open the From file for read access
  504. //
  505. RtlInitString( &NameString, FromName );
  506. InitializeObjectAttributes( &ObjectAttributes, &NameString, 0, NULL, NULL );
  507. if (!NT_SUCCESS(Status = NtOpenFile( &FromFileHandle,
  508. FILE_READ_DATA | FILE_READ_ATTRIBUTES | SYNCHRONIZE,
  509. &ObjectAttributes,
  510. &IoStatus,
  511. 0L,
  512. WriteThrough ))) {
  513. OpenFileError( Status , FromName );
  514. return;
  515. }
  516. //
  517. // Get the size of the from file
  518. //
  519. if (!NT_SUCCESS(Status = NtQueryInformationFile( FromFileHandle,
  520. &IoStatus,
  521. Buffer,
  522. BUFFERSIZE,
  523. FileStandardInformation))) {
  524. QueryInformationFileError( Status );
  525. return;
  526. }
  527. FromFileAllocation = ((PFILE_STANDARD_INFORMATION)Buffer)->AllocationSize;
  528. //
  529. // Create the To file
  530. //
  531. RtlInitString( &NameString, ToName );
  532. InitializeObjectAttributes( &ObjectAttributes, &NameString, 0, NULL, NULL );
  533. if (!NT_SUCCESS(Status = NtCreateFile( &ToFileHandle,
  534. FILE_WRITE_DATA | SYNCHRONIZE,
  535. &ObjectAttributes,
  536. &IoStatus,
  537. &FromFileAllocation,
  538. FILE_ATTRIBUTE_NORMAL,
  539. 0L,
  540. FILE_SUPERSEDE,
  541. WriteThrough,
  542. (PVOID)NULL,
  543. 0L ))) {
  544. CreateFileError( Status , ToName );
  545. return;
  546. }
  547. //
  548. // Now copy the files
  549. //
  550. ByteOffset = LiFromLong( 0 );
  551. for (LogLsn = 0; TRUE; LogLsn += BUFFERSIZE/512) {
  552. ULONG ReadLength;
  553. //
  554. // Read the next logical sectors in
  555. //
  556. ByteOffset.LowPart = LogLsn * 512;
  557. if (!NT_SUCCESS(Status = NtReadFile( FromFileHandle,
  558. (HANDLE)NULL,
  559. (PIO_APC_ROUTINE)NULL,
  560. (PVOID)NULL,
  561. &IoStatus,
  562. Buffer,
  563. BUFFERSIZE,
  564. &ByteOffset,
  565. (PULONG) NULL ))) {
  566. if (Status == STATUS_END_OF_FILE) {
  567. break;
  568. }
  569. ReadFileError( Status );
  570. break;
  571. }
  572. if (!NT_SUCCESS(Status = NtWaitForSingleObject( FromFileHandle, TRUE, NULL))) {
  573. // NtPartyByNumber(50);
  574. WaitForSingleObjectError( Status );
  575. return;
  576. }
  577. //
  578. // Check how the read turned out
  579. //
  580. if (IoStatus.Status == STATUS_END_OF_FILE) {
  581. break;
  582. }
  583. CheckIoStatus( &IoStatus, BUFFERSIZE, TRUE );
  584. if (!NT_SUCCESS(IoStatus.Status)) {
  585. break;
  586. }
  587. //
  588. // Write the sectors out
  589. //
  590. ReadLength = IoStatus.Information;
  591. if (!NT_SUCCESS(Status = NtWriteFile( ToFileHandle,
  592. (HANDLE)NULL,
  593. (PIO_APC_ROUTINE)NULL,
  594. (PVOID)NULL,
  595. &IoStatus,
  596. Buffer,
  597. IoStatus.Information,
  598. &ByteOffset,
  599. (PULONG) NULL ))) {
  600. WriteFileError( Status );
  601. return;
  602. }
  603. if (!NT_SUCCESS(Status = NtWaitForSingleObject( ToFileHandle, TRUE, NULL))) {
  604. // NtPartyByNumber(50);
  605. WaitForSingleObjectError( Status );
  606. return;
  607. }
  608. //
  609. // Check how the write turned out
  610. //
  611. CheckIoStatus( &IoStatus, ReadLength, FALSE );
  612. if (!NT_SUCCESS(IoStatus.Status)) {
  613. IoStatusError( IoStatus.Status );
  614. break;
  615. }
  616. //
  617. // If we didn't read or write a full buffer then the copy is done
  618. //
  619. if (IoStatus.Information < BUFFERSIZE) {
  620. break;
  621. }
  622. }
  623. if (!NT_SUCCESS(IoStatus.Status) && (IoStatus.Status != STATUS_END_OF_FILE)) {
  624. IoStatusError( IoStatus.Status );
  625. }
  626. //
  627. // Close both files
  628. //
  629. if (!NT_SUCCESS(Status = NtClose( FromFileHandle ))) {
  630. CloseError( Status );
  631. }
  632. if (!NT_SUCCESS(Status = NtClose( ToFileHandle ))) {
  633. CloseError( Status );
  634. }
  635. //
  636. // And return to our caller
  637. //
  638. return;
  639. }
  640. VOID Create(
  641. IN PCHAR String,
  642. IN ULONG Size
  643. )
  644. {
  645. NTSTATUS Status;
  646. HANDLE FileHandle;
  647. OBJECT_ATTRIBUTES ObjectAttributes;
  648. STRING NameString;
  649. IO_STATUS_BLOCK IoStatus;
  650. LARGE_INTEGER AllocationSize;
  651. LARGE_INTEGER ByteOffset;
  652. ULONG BufferLength;
  653. ULONG i;
  654. static CHAR FoxString[] = "The quick brown fox jumped over the lazy dog.\r\n";
  655. ULONG FoxLength;
  656. //
  657. // Get the filename
  658. //
  659. simprintf("Create ", 0);
  660. simprintf(String, 0);
  661. simprintf("\n", 0);
  662. //
  663. // Create the new file
  664. //
  665. AllocationSize = LiFromUlong( Size );
  666. RtlInitString( &NameString, String );
  667. InitializeObjectAttributes( &ObjectAttributes, &NameString, 0, NULL, NULL );
  668. if (!NT_SUCCESS(Status = NtCreateFile( &FileHandle,
  669. FILE_WRITE_DATA | SYNCHRONIZE,
  670. &ObjectAttributes,
  671. &IoStatus,
  672. &AllocationSize,
  673. FILE_ATTRIBUTE_NORMAL,
  674. 0L,
  675. FILE_SUPERSEDE,
  676. WriteThrough,
  677. (PVOID)NULL,
  678. 0L ))) {
  679. CreateFileError( Status , String );
  680. return;
  681. }
  682. //
  683. // create a test buffer to output
  684. //
  685. FoxLength = strlen(FoxString);
  686. for (i = FoxLength; i < BUFFERSIZE; i += FoxLength) {
  687. strcpy((PCHAR)&Buffer[i-FoxLength], FoxString);
  688. }
  689. BufferLength = i - FoxLength;
  690. //
  691. // The main loop writes out the test buffer a BufferLength amount
  692. // at a time
  693. //
  694. ByteOffset = LiFromLong( 0 );
  695. for (i = BufferLength; i < Size; i += BufferLength) {
  696. //
  697. // Write the next buffer
  698. //
  699. ByteOffset.LowPart = i-BufferLength;
  700. if (!NT_SUCCESS(Status = NtWriteFile( FileHandle,
  701. (HANDLE)NULL,
  702. (PIO_APC_ROUTINE)NULL,
  703. (PVOID)NULL,
  704. &IoStatus,
  705. Buffer,
  706. BufferLength,
  707. &ByteOffset,
  708. (PULONG) NULL ))) {
  709. WriteFileError( Status );
  710. return;
  711. }
  712. if (!NT_SUCCESS(Status = NtWaitForSingleObject( FileHandle, TRUE, NULL))) {
  713. // NtPartyByNumber(50);
  714. WaitForSingleObjectError( Status );
  715. return;
  716. }
  717. //
  718. // check how the write turned out
  719. //
  720. CheckIoStatus( &IoStatus, BufferLength, FALSE );
  721. if (!NT_SUCCESS(IoStatus.Status)) {
  722. IoStatusError( IoStatus.Status );
  723. break;
  724. }
  725. }
  726. //
  727. // Check for a residual to output
  728. //
  729. if (i - BufferLength < Size) {
  730. //
  731. // Write out the residual buffer
  732. //
  733. ByteOffset.LowPart = i-BufferLength;
  734. if (!NT_SUCCESS(Status = NtWriteFile( FileHandle,
  735. (HANDLE)NULL,
  736. (PIO_APC_ROUTINE)NULL,
  737. (PVOID)NULL,
  738. &IoStatus,
  739. Buffer,
  740. Size - (i - BufferLength),
  741. &ByteOffset,
  742. (PULONG) NULL ))) {
  743. WriteFileError( Status );
  744. return;
  745. }
  746. if (!NT_SUCCESS(Status = NtWaitForSingleObject( FileHandle, TRUE, NULL))) {
  747. // NtPartyByNumber(50);
  748. WaitForSingleObjectError( Status );
  749. return;
  750. }
  751. //
  752. // check how the write turned out
  753. //
  754. CheckIoStatus( &IoStatus, Size - (i - BufferLength), FALSE );
  755. if (!NT_SUCCESS(IoStatus.Status)) {
  756. IoStatusError( IoStatus.Status );
  757. }
  758. }
  759. //
  760. // Now close the file
  761. //
  762. if (!NT_SUCCESS(Status = NtClose( FileHandle ))) {
  763. CloseError( Status );
  764. }
  765. //
  766. // And return to our caller
  767. //
  768. return;
  769. }
  770. VOID DebugLevel()
  771. {
  772. #ifdef FATDBG
  773. //simprintf("Debug Trace Level %x\n", FatDebugTraceLevel);
  774. #else
  775. //simprintf("System not compiled for debug tracing\n", 0);
  776. #endif // FATDBG
  777. return;
  778. }
  779. VOID Delete(
  780. IN PCHAR String
  781. )
  782. {
  783. NTSTATUS Status;
  784. HANDLE FileHandle;
  785. OBJECT_ATTRIBUTES ObjectAttributes;
  786. STRING NameString;
  787. IO_STATUS_BLOCK IoStatus;
  788. //
  789. // Get the filename
  790. //
  791. simprintf("Delete ", 0);
  792. simprintf(String, 0);
  793. simprintf("\n", 0);
  794. //
  795. // Open the file for delete access
  796. //
  797. RtlInitString( &NameString, String );
  798. InitializeObjectAttributes( &ObjectAttributes, &NameString, 0, NULL, NULL );
  799. if (!NT_SUCCESS(Status = NtCreateFile( &FileHandle,
  800. DELETE | SYNCHRONIZE,
  801. &ObjectAttributes,
  802. &IoStatus,
  803. (PLARGE_INTEGER)NULL,
  804. 0L,
  805. 0L,
  806. FILE_OPEN,
  807. WriteThrough,
  808. (PVOID)NULL,
  809. 0L ))) {
  810. CreateFileError( Status , String);
  811. return;
  812. }
  813. //
  814. // Mark the file for delete
  815. //
  816. ((PFILE_DISPOSITION_INFORMATION)&Buffer[0])->DeleteFile = TRUE;
  817. if (!NT_SUCCESS(Status = NtSetInformationFile( FileHandle,
  818. &IoStatus,
  819. Buffer,
  820. sizeof(FILE_DISPOSITION_INFORMATION),
  821. FileDispositionInformation))) {
  822. SetInformationFileError( Status );
  823. return;
  824. }
  825. //
  826. // Now close the file
  827. //
  828. if (!NT_SUCCESS(Status = NtClose( FileHandle ))) {
  829. CloseError( Status );
  830. }
  831. //
  832. // And return to our caller
  833. //
  834. return;
  835. }
  836. VOID Directory(
  837. IN PCHAR String
  838. )
  839. {
  840. NTSTATUS Status;
  841. HANDLE FileHandle;
  842. OBJECT_ATTRIBUTES ObjectAttributes;
  843. STRING NameString;
  844. IO_STATUS_BLOCK IoStatus;
  845. NTSTATUS NtStatus;
  846. PFILE_ADIRECTORY_INFORMATION FileInfo;
  847. ULONG i;
  848. //
  849. // Get the filename
  850. //
  851. simprintf("Directory ", 0);
  852. simprintf(String, 0);
  853. simprintf("\n", 0);
  854. //
  855. // Open the file for list directory access
  856. //
  857. RtlInitString( &NameString, String );
  858. InitializeObjectAttributes( &ObjectAttributes, &NameString, 0, NULL, NULL );
  859. if (!NT_SUCCESS(Status = NtOpenFile( &FileHandle,
  860. FILE_LIST_DIRECTORY | SYNCHRONIZE,
  861. &ObjectAttributes,
  862. &IoStatus,
  863. FILE_SHARE_READ,
  864. WriteThrough | FILE_DIRECTORY_FILE ))) {
  865. OpenFileError( Status , String );
  866. return;
  867. }
  868. //
  869. // zero out the buffer so next time we'll recognize the end of data
  870. //
  871. for (i = 0; i < BUFFERSIZE; i += 1) { Buffer[i] = 0; }
  872. //
  873. // Do the directory loop
  874. //
  875. for (NtStatus = NtQueryDirectoryFile( FileHandle,
  876. (HANDLE)NULL,
  877. (PIO_APC_ROUTINE)NULL,
  878. (PVOID)NULL,
  879. &IoStatus,
  880. Buffer,
  881. BUFFERSIZE,
  882. FileADirectoryInformation,
  883. FALSE,
  884. (PSTRING)NULL,
  885. TRUE);
  886. NT_SUCCESS(NtStatus);
  887. NtStatus = NtQueryDirectoryFile( FileHandle,
  888. (HANDLE)NULL,
  889. (PIO_APC_ROUTINE)NULL,
  890. (PVOID)NULL,
  891. &IoStatus,
  892. Buffer,
  893. BUFFERSIZE,
  894. FileADirectoryInformation,
  895. FALSE,
  896. (PSTRING)NULL,
  897. FALSE) ) {
  898. if (!NT_SUCCESS(Status = NtWaitForSingleObject(FileHandle, TRUE, NULL))) {
  899. // NtPartyByNumber(50);
  900. WaitForSingleObjectError( Status );
  901. return;
  902. }
  903. //
  904. // Check the Irp for success
  905. //
  906. if (!NT_SUCCESS(IoStatus.Status)) {
  907. break;
  908. }
  909. //
  910. // For every record in the buffer type out the directory information
  911. //
  912. //
  913. // Point to the first record in the buffer, we are guaranteed to have
  914. // one otherwise IoStatus would have been No More Files
  915. //
  916. FileInfo = (PFILE_ADIRECTORY_INFORMATION)&Buffer[0];
  917. while (TRUE) {
  918. //
  919. // Print out information about the file
  920. //
  921. simprintf("%8lx ", FileInfo->FileAttributes);
  922. simprintf("%8lx/", FileInfo->EndOfFile.LowPart);
  923. simprintf("%8lx ", FileInfo->AllocationSize.LowPart);
  924. {
  925. CHAR Saved;
  926. Saved = FileInfo->FileName[FileInfo->FileNameLength];
  927. FileInfo->FileName[FileInfo->FileNameLength] = 0;
  928. simprintf(FileInfo->FileName, 0);
  929. FileInfo->FileName[FileInfo->FileNameLength] = Saved;
  930. }
  931. simprintf("\n", 0);
  932. //
  933. // Check if there is another record, if there isn't then we
  934. // simply get out of this loop
  935. //
  936. if (FileInfo->NextEntryOffset == 0) {
  937. break;
  938. }
  939. //
  940. // There is another record so advance FileInfo to the next
  941. // record
  942. //
  943. FileInfo = (PFILE_ADIRECTORY_INFORMATION)(((PUCHAR)FileInfo) + FileInfo->NextEntryOffset);
  944. }
  945. //
  946. // zero out the buffer so next time we'll recognize the end of data
  947. //
  948. for (i = 0; i < BUFFERSIZE; i += 1) { Buffer[i] = 0; }
  949. }
  950. //
  951. // Now close the file
  952. //
  953. if (!NT_SUCCESS(Status = NtClose( FileHandle ))) {
  954. CloseError( Status );
  955. }
  956. //
  957. // And return to our caller
  958. //
  959. return;
  960. }
  961. VOID Mkdir(
  962. IN PCHAR String
  963. )
  964. {
  965. NTSTATUS Status;
  966. HANDLE FileHandle;
  967. OBJECT_ATTRIBUTES ObjectAttributes;
  968. STRING NameString;
  969. IO_STATUS_BLOCK IoStatus;
  970. LARGE_INTEGER AllocationSize;
  971. //
  972. // Get the filename
  973. //
  974. simprintf("Mkdir ", 0);
  975. simprintf(String, 0);
  976. simprintf("\n", 0);
  977. //
  978. // Create the new directory
  979. //
  980. AllocationSize = LiFromLong( 4 );
  981. RtlInitString( &NameString, String );
  982. InitializeObjectAttributes( &ObjectAttributes, &NameString, 0, NULL, NULL );
  983. if (!NT_SUCCESS(Status = NtCreateFile( &FileHandle,
  984. SYNCHRONIZE,
  985. &ObjectAttributes,
  986. &IoStatus,
  987. &AllocationSize,
  988. 0L,
  989. 0L,
  990. FILE_CREATE,
  991. WriteThrough | FILE_DIRECTORY_FILE,
  992. (PVOID)NULL,
  993. 0L ))) {
  994. CreateFileError( Status , String );
  995. return;
  996. }
  997. //
  998. // Now close the directory
  999. //
  1000. if (!NT_SUCCESS(Status = NtClose( FileHandle ))) {
  1001. CloseError( Status );
  1002. }
  1003. //
  1004. // And return to our caller
  1005. //
  1006. return;
  1007. }
  1008. VOID Query(
  1009. IN PCHAR String
  1010. )
  1011. {
  1012. NTSTATUS Status;
  1013. HANDLE FileHandle;
  1014. OBJECT_ATTRIBUTES ObjectAttributes;
  1015. STRING NameString;
  1016. IO_STATUS_BLOCK IoStatus;
  1017. ULONG i;
  1018. PFILE_AALL_INFORMATION AllInfo;
  1019. PFILE_BASIC_INFORMATION BasicInfo;
  1020. PFILE_STANDARD_INFORMATION StandardInfo;
  1021. PFILE_INTERNAL_INFORMATION InternalInfo;
  1022. PFILE_EA_INFORMATION EaInfo;
  1023. PFILE_ACCESS_INFORMATION AccessInfo;
  1024. PFILE_ANAME_INFORMATION NameInfo;
  1025. //
  1026. // zero out the buffer so next time we'll recognize the end of data
  1027. //
  1028. for (i = 0; i < BUFFERSIZE; i += 1) { Buffer[i] = 0; }
  1029. //
  1030. // Set up some local pointers
  1031. //
  1032. AllInfo = (PFILE_AALL_INFORMATION)Buffer;
  1033. BasicInfo = &AllInfo->BasicInformation;
  1034. StandardInfo = &AllInfo->StandardInformation;
  1035. InternalInfo = &AllInfo->InternalInformation;
  1036. EaInfo = &AllInfo->EaInformation;
  1037. AccessInfo = &AllInfo->AccessInformation;
  1038. NameInfo = &AllInfo->NameInformation;
  1039. //
  1040. // Get the filename
  1041. //
  1042. simprintf("Query ", 0);
  1043. simprintf(String, 0);
  1044. simprintf("\n", 0);
  1045. //
  1046. // Open the file for read attributes, read ea, and read control access
  1047. //
  1048. RtlInitString( &NameString, String );
  1049. InitializeObjectAttributes( &ObjectAttributes, &NameString, 0, NULL, NULL );
  1050. if (!NT_SUCCESS(Status = NtOpenFile( &FileHandle,
  1051. FILE_READ_ATTRIBUTES | FILE_READ_EA | READ_CONTROL | SYNCHRONIZE,
  1052. &ObjectAttributes,
  1053. &IoStatus,
  1054. 0L,
  1055. WriteThrough ))) {
  1056. OpenFileError( Status , String );
  1057. return;
  1058. }
  1059. //
  1060. // Query the file
  1061. //
  1062. if (!NT_SUCCESS(Status = NtQueryInformationFile( FileHandle,
  1063. &IoStatus,
  1064. Buffer,
  1065. BUFFERSIZE,
  1066. FileAAllInformation))) {
  1067. QueryInformationFileError( Status );
  1068. return;
  1069. }
  1070. //
  1071. // Output file name information
  1072. //
  1073. simprintf("\"", 0);
  1074. simprintf(NameInfo->FileName, 0);
  1075. simprintf("\"\n", 0);
  1076. //
  1077. // Output the times
  1078. //
  1079. simprintf(" Create = ", 0); PrintTime( &BasicInfo->CreationTime ); simprintf("\n", 0);
  1080. simprintf(" Access = ", 0); PrintTime( &BasicInfo->LastAccessTime ); simprintf("\n", 0);
  1081. simprintf(" Write = ", 0); PrintTime( &BasicInfo->LastWriteTime ); simprintf("\n", 0);
  1082. //
  1083. // Output File size, and allocation size
  1084. //
  1085. simprintf(" Size = %8lx\n", StandardInfo->EndOfFile.LowPart);
  1086. simprintf(" Alloc = %8lx\n", StandardInfo->AllocationSize.LowPart);
  1087. //
  1088. // Output File attributes, Device type, link count, and flags
  1089. //
  1090. simprintf(" Attrib = %8lx\n", BasicInfo->FileAttributes);
  1091. // simprintf(" DevType = %8lx\n", StandardInfo->DeviceType);
  1092. simprintf(" Links = %8lx\n", StandardInfo->NumberOfLinks);
  1093. simprintf(" Dir = %8lx\n", StandardInfo->Directory);
  1094. simprintf(" Delete = %8lx\n", StandardInfo->DeletePending);
  1095. //
  1096. // Output the index number and ea size
  1097. //
  1098. simprintf(" Index = %8lx\n", InternalInfo->IndexNumber.LowPart);
  1099. simprintf(" EaSize = %8lx\n", EaInfo->EaSize);
  1100. //
  1101. // Output the file access flags
  1102. //
  1103. simprintf(" Flags = %8lx\n", AccessInfo->AccessFlags);
  1104. //
  1105. // Now close the file
  1106. //
  1107. if (!NT_SUCCESS(Status = NtClose( FileHandle ))) {
  1108. CloseError( Status );
  1109. }
  1110. //
  1111. // And return to our caller
  1112. //
  1113. return;
  1114. }
  1115. VOID QVolume(
  1116. IN PCHAR String
  1117. )
  1118. {
  1119. NTSTATUS Status;
  1120. HANDLE FileHandle;
  1121. OBJECT_ATTRIBUTES ObjectAttributes;
  1122. STRING NameString;
  1123. IO_STATUS_BLOCK IoStatus;
  1124. ULONG i;
  1125. PFILE_FS_AVOLUME_INFORMATION VolumeInfo;
  1126. //
  1127. // zero out the buffer so next time we'll recognize the end of data
  1128. //
  1129. for (i = 0; i < BUFFERSIZE; i += 1) { Buffer[i] = 0; }
  1130. //
  1131. // Set up some local pointers
  1132. //
  1133. VolumeInfo = (PFILE_FS_AVOLUME_INFORMATION)Buffer;
  1134. //
  1135. // Get the volume name
  1136. //
  1137. simprintf("QVolume ", 0);
  1138. simprintf(String, 0);
  1139. simprintf("\n", 0);
  1140. //
  1141. // Open the Volume for no access
  1142. //
  1143. RtlInitString( &NameString, String );
  1144. InitializeObjectAttributes( &ObjectAttributes, &NameString, 0, NULL, NULL );
  1145. if (!NT_SUCCESS(Status = NtOpenFile( &FileHandle,
  1146. FILE_READ_ATTRIBUTES | SYNCHRONIZE,
  1147. &ObjectAttributes,
  1148. &IoStatus,
  1149. 0L,
  1150. WriteThrough ))) {
  1151. OpenFileError( Status , String );
  1152. return;
  1153. }
  1154. //
  1155. // zero out the buffer so next time we'll recognize the end of data
  1156. //
  1157. for (i = 0; i < BUFFERSIZE; i += 1) { Buffer[i] = 0; }
  1158. //
  1159. // Query the volume info
  1160. //
  1161. if (!NT_SUCCESS(Status = NtQueryVolumeInformationFile( FileHandle,
  1162. &IoStatus,
  1163. Buffer,
  1164. BUFFERSIZE,
  1165. FileAFsVolumeInformation))) {
  1166. QueryVolumeInformationFileError( Status );
  1167. return;
  1168. }
  1169. //
  1170. // Output Volume name information
  1171. //
  1172. simprintf("\"", 0);
  1173. simprintf(VolumeInfo->VolumeLabel, 0);
  1174. simprintf("\"\n", 0);
  1175. //
  1176. // Output the volume serial number
  1177. //
  1178. simprintf(" SerialNum = %8lx\n", VolumeInfo->VolumeSerialNumber);
  1179. //
  1180. // Now close the Volume
  1181. //
  1182. if (!NT_SUCCESS(Status = NtClose( FileHandle ))) {
  1183. CloseError( Status );
  1184. }
  1185. //
  1186. // And return to our caller
  1187. //
  1188. return;
  1189. }
  1190. VOID Rename()
  1191. {
  1192. //simprintf("Rename not implemented\n", 0);
  1193. }
  1194. VOID SVolume(
  1195. IN PCHAR String,
  1196. IN PCHAR Label
  1197. )
  1198. {
  1199. NTSTATUS Status;
  1200. HANDLE FileHandle;
  1201. OBJECT_ATTRIBUTES ObjectAttributes;
  1202. STRING NameString;
  1203. IO_STATUS_BLOCK IoStatus;
  1204. ULONG i;
  1205. PFILE_FS_ALABEL_INFORMATION LabelInfo;
  1206. //
  1207. // zero out the buffer so next time we'll recognize the end of data
  1208. //
  1209. for (i = 0; i < BUFFERSIZE; i += 1) { Buffer[i] = 0; }
  1210. //
  1211. // Set up some local pointers
  1212. //
  1213. LabelInfo = (PFILE_FS_ALABEL_INFORMATION)Buffer;
  1214. //
  1215. // Get the volume name, and new label name
  1216. //
  1217. strcpy( LabelInfo->VolumeLabel, Label );
  1218. LabelInfo->VolumeLabelLength = strlen(LabelInfo->VolumeLabel);
  1219. if ((LabelInfo->VolumeLabelLength == 1) &&
  1220. (LabelInfo->VolumeLabel[0] == '.')) {
  1221. LabelInfo->VolumeLabelLength = 0;
  1222. }
  1223. simprintf("SVolume ", 0);
  1224. simprintf(String, 0);
  1225. simprintf(" ", 0);
  1226. simprintf(LabelInfo->VolumeLabel, 0);
  1227. simprintf("\n", 0);
  1228. //
  1229. // Open the Volume for no access
  1230. //
  1231. RtlInitString( &NameString, String );
  1232. InitializeObjectAttributes( &ObjectAttributes, &NameString, 0, NULL, NULL );
  1233. if (!NT_SUCCESS(Status = NtOpenFile( &FileHandle,
  1234. FILE_WRITE_ATTRIBUTES | SYNCHRONIZE,
  1235. &ObjectAttributes,
  1236. &IoStatus,
  1237. 0L,
  1238. WriteThrough ))) {
  1239. OpenFileError( Status, String );
  1240. return;
  1241. }
  1242. //
  1243. // Set the volume info
  1244. //
  1245. if (!NT_SUCCESS(Status = NtSetVolumeInformationFile( FileHandle,
  1246. &IoStatus,
  1247. LabelInfo,
  1248. BUFFERSIZE,
  1249. FileAFsLabelInformation))) {
  1250. SetVolumeInformationFileError( Status );
  1251. return;
  1252. }
  1253. //
  1254. // Now close the Volume
  1255. //
  1256. if (!NT_SUCCESS(Status = NtClose( FileHandle ))) {
  1257. CloseError( Status );
  1258. }
  1259. //
  1260. // And return to our caller
  1261. //
  1262. return;
  1263. }
  1264. VOID Type(
  1265. IN PCHAR String
  1266. )
  1267. {
  1268. NTSTATUS Status;
  1269. HANDLE FileHandle;
  1270. OBJECT_ATTRIBUTES ObjectAttributes;
  1271. STRING NameString;
  1272. IO_STATUS_BLOCK IoStatus;
  1273. LARGE_INTEGER ByteOffset;
  1274. ULONG LogLsn;
  1275. ULONG i;
  1276. //
  1277. // Get the filename
  1278. //
  1279. simprintf("Type ", 0);
  1280. simprintf(String, 0);
  1281. simprintf("\n", 0);
  1282. //
  1283. // Open the file for read
  1284. //
  1285. RtlInitString( &NameString, String );
  1286. InitializeObjectAttributes( &ObjectAttributes, &NameString, 0, NULL, NULL );
  1287. if (!NT_SUCCESS(Status = NtOpenFile( &FileHandle,
  1288. FILE_READ_DATA | SYNCHRONIZE,
  1289. &ObjectAttributes,
  1290. &IoStatus,
  1291. 0L,
  1292. WriteThrough ))) {
  1293. OpenFileError( Status, String );
  1294. return;
  1295. }
  1296. //
  1297. // While there is data to be read we'll read a buffer and write it out
  1298. //
  1299. ByteOffset = LiFromLong( 0 );
  1300. for (LogLsn = 0; TRUE; LogLsn += BUFFERSIZE/512) {
  1301. //
  1302. // Read the next logical sector
  1303. //
  1304. ByteOffset.LowPart = LogLsn * 512;
  1305. if (!NT_SUCCESS(Status = NtReadFile( FileHandle,
  1306. (HANDLE)NULL,
  1307. (PIO_APC_ROUTINE)NULL,
  1308. (PVOID)NULL,
  1309. &IoStatus,
  1310. Buffer,
  1311. BUFFERSIZE,
  1312. &ByteOffset,
  1313. (PULONG) NULL ))) {
  1314. if (Status == STATUS_END_OF_FILE) {
  1315. break;
  1316. }
  1317. ReadFileError( Status );
  1318. break;
  1319. }
  1320. if (!NT_SUCCESS(Status = NtWaitForSingleObject( FileHandle, TRUE, NULL))) {
  1321. // NtPartyByNumber(50);
  1322. WaitForSingleObjectError( Status );
  1323. return;
  1324. }
  1325. //
  1326. // check how the read turned out
  1327. //
  1328. if (IoStatus.Status == STATUS_END_OF_FILE) {
  1329. break;
  1330. }
  1331. CheckIoStatus( &IoStatus, BUFFERSIZE, TRUE );
  1332. if (!NT_SUCCESS(IoStatus.Status)) {
  1333. IoStatusError( IoStatus.Status );
  1334. break;
  1335. }
  1336. //
  1337. // Write out the buffer
  1338. //
  1339. for (i = 0; i < IoStatus.Information; i += 1) {
  1340. simprintf("%c", Buffer[i]);
  1341. }
  1342. //
  1343. // If we didn't read in a complete buffer then we're all done reading
  1344. // and can get out of here
  1345. //
  1346. if (IoStatus.Information < BUFFERSIZE) {
  1347. break;
  1348. }
  1349. }
  1350. //
  1351. // Now close the file
  1352. //
  1353. if (!NT_SUCCESS(Status = NtClose( FileHandle ))) {
  1354. CloseError( Status );
  1355. }
  1356. //
  1357. // And return to our caller
  1358. //
  1359. return;
  1360. }
  1361. VOID
  1362. Quit()
  1363. {
  1364. simprintf("FatTest Exiting.\n", 0);
  1365. return;
  1366. }
  1367. VOID
  1368. PrintTime (
  1369. IN PLARGE_INTEGER Time
  1370. )
  1371. {
  1372. TIME_FIELDS TimeFields;
  1373. static PCHAR Months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
  1374. "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
  1375. static PCHAR Days[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
  1376. RtlTimeToTimeFields( Time, &TimeFields );
  1377. simprintf(" %4d-", TimeFields.Year);
  1378. simprintf(Months[TimeFields.Month-1], 0);
  1379. simprintf("-%2d", TimeFields.Day);
  1380. simprintf(" %2d", TimeFields.Hour);
  1381. simprintf(":%2d", TimeFields.Minute);
  1382. simprintf(":%2d", TimeFields.Second);
  1383. simprintf(".%3d (", TimeFields.Milliseconds);
  1384. simprintf(Days[TimeFields.Weekday], 0);
  1385. simprintf(")", 0);
  1386. return;
  1387. }
  1388. VOID
  1389. WaitForSingleObjectError(
  1390. IN NTSTATUS Status
  1391. )
  1392. {
  1393. DbgPrint(Prefix);
  1394. DbgPrint(" WaitForSingleObject Error %X\n", Status);
  1395. }
  1396. VOID
  1397. CreateFileError(
  1398. IN NTSTATUS Status,
  1399. PCHAR File
  1400. )
  1401. {
  1402. DbgPrint(Prefix);
  1403. DbgPrint(" CreateFile of %s Error %X\n", File, Status);
  1404. }
  1405. VOID
  1406. OpenFileError(
  1407. IN NTSTATUS Status,
  1408. PCHAR File
  1409. )
  1410. {
  1411. DbgPrint(Prefix);
  1412. DbgPrint(" OpenFile of %s Error %X\n", File, Status);
  1413. }
  1414. VOID
  1415. ReadFileError(
  1416. IN NTSTATUS Status
  1417. )
  1418. {
  1419. DbgPrint(Prefix);
  1420. DbgPrint(" ReadFile Error %X\n", Status);
  1421. }
  1422. VOID
  1423. WriteFileError(
  1424. IN NTSTATUS Status
  1425. )
  1426. {
  1427. DbgPrint(Prefix);
  1428. DbgPrint(" WriteFile Error %X\n", Status);
  1429. }
  1430. VOID
  1431. CheckIoStatus(
  1432. IN PIO_STATUS_BLOCK IoStatus,
  1433. IN ULONG Length,
  1434. IN BOOLEAN Read
  1435. )
  1436. {
  1437. if (!NT_SUCCESS(IoStatus->Status)) {
  1438. DbgPrint(" IoStatus->Status Error %08lx\n", IoStatus->Status);
  1439. }
  1440. if ((!Read && (IoStatus->Information != Length))
  1441. ||
  1442. (Read && (IoStatus->Information > Length))) {
  1443. DbgPrint(" IoStatus->Information Error %08lx\n", IoStatus->Information);
  1444. }
  1445. }
  1446. VOID
  1447. SetInformationFileError(
  1448. IN NTSTATUS Status
  1449. )
  1450. {
  1451. DbgPrint(Prefix);
  1452. DbgPrint(" SetInfoFile Error %X\n", Status);
  1453. }
  1454. VOID
  1455. QueryInformationFileError(
  1456. IN NTSTATUS Status
  1457. )
  1458. {
  1459. DbgPrint(Prefix);
  1460. DbgPrint(" QueryInfoFile Error %X\n", Status);
  1461. }
  1462. VOID
  1463. SetVolumeInformationFileError(
  1464. IN NTSTATUS Status
  1465. )
  1466. {
  1467. DbgPrint(Prefix);
  1468. DbgPrint(" SetVolumeInfoFile Error %X\n", Status);
  1469. }
  1470. VOID
  1471. QueryVolumeInformationFileError(
  1472. IN NTSTATUS Status
  1473. )
  1474. {
  1475. DbgPrint(Prefix);
  1476. DbgPrint(" QueryVolumeInfoFile Error %X\n", Status);
  1477. }
  1478. VOID
  1479. CloseError(
  1480. IN NTSTATUS Status
  1481. )
  1482. {
  1483. DbgPrint(Prefix);
  1484. DbgPrint(" Close Error %X\n", Status);
  1485. }
  1486. VOID
  1487. IoStatusError(
  1488. IN NTSTATUS Status
  1489. )
  1490. {
  1491. DbgPrint(Prefix);
  1492. DbgPrint(" IoStatus Error %X\n", Status);
  1493. }