1 //======================================================================
3 // $Id: format.c,v 1.1 1999/05/16 07:27:35 ea Exp $
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 //======================================================================
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");
279 #ifndef FMIFS_IMPORT_DLL
280 //----------------------------------------------------------------------
282 // LoadFMIFSEntryPoints
284 // Loads FMIFS.DLL and locates the entry point(s) we are going to use
286 // 19990216 EA ANSI strings in LoadFMIFSEntryPoints should be
289 //----------------------------------------------------------------------
291 LoadFMIFSEntryPoints(VOID
)
293 LoadLibraryW( L
"fmifs.dll" );
296 (void *) GetProcAddress(
297 GetModuleHandleW( L
"fmifs.dll"),
304 if ( !(EnableVolumeCompression
=
305 (void *) GetProcAddress(
306 GetModuleHandleW( L
"fmifs.dll"),
307 "EnableVolumeCompression"
315 #endif /* ndef FMIFS_IMPORT_DLL */
318 //----------------------------------------------------------------------
322 // Engine. Just get command line switches and fire off a format. This
323 // could also be done in a GUI like Explorer does when you select a
324 // drive and run a check on it.
326 // We do this in UNICODE because the chkdsk command expects PWCHAR
329 //----------------------------------------------------------------------
331 wmain( int argc
, WCHAR
*argv
[] )
338 WCHAR fileSystem
[1024];
339 WCHAR volumeName
[1024];
346 ULARGE_INTEGER freeBytesAvailableToCaller
,
348 totalNumberOfFreeBytes
;
352 \nFormatx v1.0 by Mark Russinovich\n\
353 Systems Internals - http://www.sysinternals.com\n\
354 ReactOs adaptation 1999 by Emanuele Aliberti\n\n"
357 #ifndef FMIFS_IMPORT_DLL
359 // Get function pointers
361 if( !LoadFMIFSEntryPoints())
363 wprintf(L
"Could not located FMIFS entry points.\n\n");
366 #endif /* ndef FMIFS_IMPORT_DLL */
368 // Parse command line
370 if( (badArg
= ParseCommandLine( argc
, argv
)))
373 L
"Unknown argument: %s\n",
380 // Get the drive's format
384 wprintf(L
"Required drive parameter is missing.\n\n");
390 wcscpy( RootDirectory
, Drive
);
392 RootDirectory
[2] = L
'\\';
393 RootDirectory
[3] = L
'\0';
395 // See if the drive is removable or not
397 driveType
= GetDriveTypeW( RootDirectory
);
398 if ( driveType
!= DRIVE_FIXED
)
401 L
"Insert a new floppy in drive %C:\nand press Enter when ready...",
409 media
= FMIFS_FLOPPY
;
412 // Determine the drive's file system format
414 if ( !GetVolumeInformationW(
417 WBUFSIZE(volumeName
),
422 WBUFSIZE(fileSystem
) )
425 L
"Could not query volume",
430 if( !GetDiskFreeSpaceExW(
432 & freeBytesAvailableToCaller
,
433 & totalNumberOfBytes
,
434 & totalNumberOfFreeBytes
)
438 L
"Could not query volume size",
444 L
"The type of the file system is %s.\n",
448 // Make sure they want to do this
450 if ( driveType
== DRIVE_FIXED
)
457 L
"Enter current volume label for drive %C: ",
465 input
[ wcslen( input
) - 1 ] = 0;
467 if ( !wcsicmp( input
, volumeName
))
471 wprintf(L
"An incorrect volume label was entered for this drive.\n");
476 wprintf(L
"\nWARNING, ALL DATA ON NON_REMOVABLE DISK\n");
477 wprintf(L
"DRIVE %C: WILL BE LOST!\n", RootDirectory
[0] );
478 wprintf(L
"Proceed with Format (Y/N)? " );
484 if ( (input
[0] == L
'Y') || (input
[0] == L
'y') ) break;
486 if ( (input
[0] == L
'N') || (input
[0] == L
'n') )
492 media
= FMIFS_HARDDISK
;
495 // Tell the user we're doing a long format if appropriate
499 if ( totalNumberOfBytes
.QuadPart
> 1024*1024*10 )
504 (DWORD
) (totalNumberOfBytes
.QuadPart
/(1024*1024))
510 L
"Verifying %.1fM\n",
511 ((float)(LONGLONG
)totalNumberOfBytes
.QuadPart
)/(float)(1024.0*1024.0)
517 if ( totalNumberOfBytes
.QuadPart
> 1024*1024*10 )
520 L
"QuickFormatting %dM\n",
521 (DWORD
) (totalNumberOfBytes
.QuadPart
/ (1024 * 1024))
527 L
"QuickFormatting %.2fM\n",
528 ((float)(LONGLONG
)totalNumberOfBytes
.QuadPart
) / (float)(1024.0*1024.0)
531 wprintf(L
"Creating file system structures.\n");
545 if ( Error
) return -1;
546 wprintf(L
"Format complete.\n");
548 // Enable compression if desired
552 if( !EnableVolumeCompression( RootDirectory
, TRUE
))
554 wprintf(L
"Volume does not support compression.\n");
558 // Get the label if we don't have it
562 wprintf(L
"Volume Label (11 characters, Enter for none)? " );
565 WBUFSIZE(LabelString
),
569 input
[ wcslen(input
) - 1 ] = 0;
570 if( !SetVolumeLabelW( RootDirectory
, input
))
573 L
"Could not label volume",
579 if ( !GetVolumeInformationW(
582 WBUFSIZE(volumeName
),
587 WBUFSIZE(fileSystem
) )
590 L
"Could not query volume",
596 // Print out some stuff including the formatted size
598 if ( !GetDiskFreeSpaceExW(
600 & freeBytesAvailableToCaller
,
601 & totalNumberOfBytes
,
602 & totalNumberOfFreeBytes
)
605 L
"Could not query volume size",
611 L
"\n%I64d bytes total disk space.\n",
612 totalNumberOfBytes
.QuadPart
615 L
"%I64d bytes available on disk.\n",
616 totalNumberOfFreeBytes
.QuadPart
619 // Get the drive's serial number
621 if ( !GetVolumeInformationW(
624 WBUFSIZE(volumeName
),
629 WBUFSIZE(fileSystem
) )
632 L
"Could not query volume",
638 L
"\nVolume Serial Number is %04X-%04X\n",
640 serialNumber
& 0xFFFF