1 //======================================================================
7 // Copyright (c) 1998 Mark Russinovich
9 // http://www.sysinternals.com/
11 // This software is free software; you can redistribute it and/or
12 // modify it under the terms of the GNU Library General Public License as
13 // published by the Free Software Foundation; either version 2 of the
14 // License, or (at your option) any later version.
16 // This software is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 // Library General Public License for more details.
21 // You should have received a copy of the GNU Library General Public
22 // License along with this software; see the file COPYING.LIB. If
23 // not, write to the Free Software Foundation, Inc., 675 Mass Ave,
24 // Cambridge, MA 02139, USA.
26 // ---------------------------------------------------------------------
27 // Format clone that demonstrates the use of the FMIFS file system
30 // 1999 February (Emanuele Aliberti)
31 // Adapted for ReactOS and lcc-win32.
33 // 1999 April (Emanuele Aliberti)
34 // Adapted for ReactOS and egcs.
36 //======================================================================
41 #include "../../reactos/include/fmifs.h"
46 #define WBUFSIZE(b) (sizeof(b) / sizeof (wchar_t))
55 BOOL QuickFormat
= FALSE
;
56 DWORD ClusterSize
= 0;
57 BOOL CompressDrive
= FALSE
;
58 BOOL GotALabel
= FALSE
;
61 PWCHAR Format
= L
"FAT";
63 WCHAR RootDirectory
[MAX_PATH
];
64 WCHAR LabelString
[12];
66 #ifndef FMIFS_IMPORT_DLL
68 // Functions in FMIFS.DLL
71 PENABLEVOLUMECOMPRESSION EnableVolumeCompression
;
72 #endif /* ndef FMIFS_IMPORT_DLL */
80 WCHAR SizeString
[16];
83 } SIZEDEFINITION
, *PSIZEDEFINITION
;
97 { L
"128K", 65536 * 2 },
98 { L
"256K", 65536 * 4 },
103 //----------------------------------------------------------------------
107 // Tell the user how to use the program
109 // 1990218 EA ProgramName missing in wprintf arg list
111 //----------------------------------------------------------------------
113 Usage( PWCHAR ProgramName
)
117 Usage: %s drive: [-FS:file-system] [-V:label] [-Q] [-A:size] [-C]\n\n\
118 [drive:] Specifies the drive to format.\n\
119 -FS:file-system Specifies the type of file system (e.g. FAT).\n\
120 -V:label Specifies volume label.\n\
121 -Q Performs a quick format.\n\
122 -A:size Overrides the default allocation unit size. Default settings\n\
123 are strongly recommended for general use\n\
124 NTFS supports 512, 1024, 2048, 4096, 8192, 16K, 32K, 64K.\n\
125 FAT supports 8192, 16K, 32K, 64K, 128K, 256K.\n\
126 NTFS compression is not supported for allocation unit sizes\n\
128 -C Files created on the new volume will be compressed by\n\
135 //----------------------------------------------------------------------
141 // 19990218 EA switch characters '-' and '/' are wide
143 //----------------------------------------------------------------------
152 BOOLEAN gotFormat
= FALSE
;
153 BOOLEAN gotQuick
= FALSE
;
154 BOOLEAN gotSize
= FALSE
;
155 BOOLEAN gotLabel
= FALSE
;
156 BOOLEAN gotCompressed
= FALSE
;
164 switch ( argv
[i
][0] )
170 if( !wcsnicmp( & argv
[i
][1], L
"FS:", 3 ))
172 if( gotFormat
) return -1;
173 Format
= & argv
[i
][4];
176 else if( !wcsnicmp( & argv
[i
][1], L
"A:", 2 ))
178 if ( gotSize
) return -1;
180 while ( LegalSizes
[j
].ClusterSize
&&
182 LegalSizes
[j
].SizeString
,
188 if( !LegalSizes
[j
].ClusterSize
) return i
;
189 ClusterSize
= LegalSizes
[j
].ClusterSize
;
192 else if( !wcsnicmp( & argv
[i
][1], L
"V:", 2 ))
194 if( gotLabel
) return -1;
195 Label
= & argv
[i
][3];
199 else if ( !wcsicmp( & argv
[i
][1], L
"Q" ))
201 if( gotQuick
) return -1;
205 else if ( !wcsicmp( & argv
[i
][1], L
"C" ))
207 if( gotCompressed
) return -1;
208 CompressDrive
= TRUE
;
209 gotCompressed
= TRUE
;
219 if ( Drive
) return i
;
220 if ( argv
[i
][1] != L
':' ) return i
;
230 //----------------------------------------------------------------------
234 // The file system library will call us back with commands that we
235 // can interpret. If we wanted to halt the chkdsk we could return FALSE.
237 //----------------------------------------------------------------------
241 CALLBACKCOMMAND Command
,
249 //static createStructures = FALSE;
252 // We get other types of commands, but we don't have to pay attention to them
257 percent
= (PDWORD
) Argument
;
258 wprintf(L
"%d percent completed.\r", *percent
);
262 output
= (PTEXTOUTPUT
) Argument
;
263 fprintf(stdout
, "%s", output
->Output
);
267 status
= (PBOOLEAN
) Argument
;
268 if ( *status
== FALSE
)
270 wprintf(L
"FormatEx was unable to complete successfully.\n\n");
281 #ifndef FMIFS_IMPORT_DLL
282 //----------------------------------------------------------------------
284 // LoadFMIFSEntryPoints
286 // Loads FMIFS.DLL and locates the entry point(s) we are going to use
288 // 19990216 EA ANSI strings in LoadFMIFSEntryPoints should be
291 //----------------------------------------------------------------------
293 LoadFMIFSEntryPoints(VOID
)
295 LoadLibraryW( L
"fmifs.dll" );
298 (void *) GetProcAddress(
299 GetModuleHandleW( L
"fmifs.dll"),
306 if ( !(EnableVolumeCompression
=
307 (void *) GetProcAddress(
308 GetModuleHandleW( L
"fmifs.dll"),
309 "EnableVolumeCompression"
317 #endif /* ndef FMIFS_IMPORT_DLL */
320 //----------------------------------------------------------------------
324 // Engine. Just get command line switches and fire off a format. This
325 // could also be done in a GUI like Explorer does when you select a
326 // drive and run a check on it.
328 // We do this in UNICODE because the chkdsk command expects PWCHAR
331 //----------------------------------------------------------------------
333 wmain( int argc
, WCHAR
*argv
[] )
340 WCHAR fileSystem
[1024];
341 WCHAR volumeName
[1024];
348 ULARGE_INTEGER freeBytesAvailableToCaller
,
350 totalNumberOfFreeBytes
;
354 \nFormatx v1.0 by Mark Russinovich\n\
355 Systems Internals - http://www.sysinternals.com\n\
356 ReactOs adaptation 1999 by Emanuele Aliberti\n\n"
359 #ifndef FMIFS_IMPORT_DLL
361 // Get function pointers
363 if( !LoadFMIFSEntryPoints())
365 wprintf(L
"Could not located FMIFS entry points.\n\n");
368 #endif /* ndef FMIFS_IMPORT_DLL */
370 // Parse command line
372 if( (badArg
= ParseCommandLine( argc
, argv
)))
375 L
"Unknown argument: %s\n",
382 // Get the drive's format
386 wprintf(L
"Required drive parameter is missing.\n\n");
392 wcscpy( RootDirectory
, Drive
);
394 RootDirectory
[2] = L
'\\';
395 RootDirectory
[3] = L
'\0';
397 // See if the drive is removable or not
399 driveType
= GetDriveTypeW( RootDirectory
);
400 if ( driveType
!= DRIVE_FIXED
)
403 L
"Insert a new floppy in drive %C:\nand press Enter when ready...",
411 media
= FMIFS_FLOPPY
;
414 // Determine the drive's file system format
416 if ( !GetVolumeInformationW(
419 WBUFSIZE(volumeName
),
424 WBUFSIZE(fileSystem
) )
427 L
"Could not query volume",
432 if( !GetDiskFreeSpaceExW(
434 & freeBytesAvailableToCaller
,
435 & totalNumberOfBytes
,
436 & totalNumberOfFreeBytes
)
440 L
"Could not query volume size",
446 L
"The type of the file system is %s.\n",
450 // Make sure they want to do this
452 if ( driveType
== DRIVE_FIXED
)
459 L
"Enter current volume label for drive %C: ",
467 input
[ wcslen( input
) - 1 ] = 0;
469 if ( !wcsicmp( input
, volumeName
))
473 wprintf(L
"An incorrect volume label was entered for this drive.\n");
478 wprintf(L
"\nWARNING, ALL DATA ON NON_REMOVABLE DISK\n");
479 wprintf(L
"DRIVE %C: WILL BE LOST!\n", RootDirectory
[0] );
480 wprintf(L
"Proceed with Format (Y/N)? " );
486 if ( (input
[0] == L
'Y') || (input
[0] == L
'y') ) break;
488 if ( (input
[0] == L
'N') || (input
[0] == L
'n') )
494 media
= FMIFS_HARDDISK
;
497 // Tell the user we're doing a long format if appropriate
501 if ( totalNumberOfBytes
.QuadPart
> 1024*1024*10 )
506 (DWORD
) (totalNumberOfBytes
.QuadPart
/(1024*1024))
512 L
"Verifying %.1fM\n",
513 ((float)(LONGLONG
)totalNumberOfBytes
.QuadPart
)/(float)(1024.0*1024.0)
519 if ( totalNumberOfBytes
.QuadPart
> 1024*1024*10 )
522 L
"QuickFormatting %dM\n",
523 (DWORD
) (totalNumberOfBytes
.QuadPart
/ (1024 * 1024))
529 L
"QuickFormatting %.2fM\n",
530 ((float)(LONGLONG
)totalNumberOfBytes
.QuadPart
) / (float)(1024.0*1024.0)
533 wprintf(L
"Creating file system structures.\n");
547 if ( Error
) return -1;
548 wprintf(L
"Format complete.\n");
550 // Enable compression if desired
554 if( !EnableVolumeCompression( RootDirectory
, TRUE
))
556 wprintf(L
"Volume does not support compression.\n");
560 // Get the label if we don't have it
564 wprintf(L
"Volume Label (11 characters, Enter for none)? " );
567 WBUFSIZE(LabelString
),
571 input
[ wcslen(input
) - 1 ] = 0;
572 if( !SetVolumeLabelW( RootDirectory
, input
))
575 L
"Could not label volume",
581 if ( !GetVolumeInformationW(
584 WBUFSIZE(volumeName
),
589 WBUFSIZE(fileSystem
) )
592 L
"Could not query volume",
598 // Print out some stuff including the formatted size
600 if ( !GetDiskFreeSpaceExW(
602 & freeBytesAvailableToCaller
,
603 & totalNumberOfBytes
,
604 & totalNumberOfFreeBytes
)
607 L
"Could not query volume size",
613 L
"\n%I64d bytes total disk space.\n",
614 totalNumberOfBytes
.QuadPart
617 L
"%I64d bytes available on disk.\n",
618 totalNumberOfFreeBytes
.QuadPart
621 // Get the drive's serial number
623 if ( !GetVolumeInformationW(
626 WBUFSIZE(volumeName
),
631 WBUFSIZE(fileSystem
) )
634 L
"Could not query volume",
640 L
"\nVolume Serial Number is %04X-%04X\n",
642 serialNumber
& 0xFFFF