+++ /dev/null
-//======================================================================
-//
-// Formatx
-//
-// Copyright (c) 1998 Mark Russinovich
-// Systems Internals
-// http://www.sysinternals.com
-//
-// Format clone that demonstrates the use of the FMIFS file system
-// utility library.
-//
-// --------------------------------------------------------------------
-//
-// This software is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Library General Public License as
-// published by the Free Software Foundation; either version 2 of the
-// License, or (at your option) any later version.
-//
-// This software is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Library General Public License for more details.
-//
-// You should have received a copy of the GNU Library General Public
-// License along with this software; see the file COPYING.LIB. If
-// not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-// Cambridge, MA 02139, USA.
-//
-// --------------------------------------------------------------------
-//
-// 1999 February (Emanuele Aliberti)
-// Adapted for ReactOS and lcc-win32.
-//
-// 1999 April (Emanuele Aliberti)
-// Adapted for ReactOS and egcs.
-//
-// 2003 April (Casper S. Hornstrup)
-// Reintegration.
-//
-//======================================================================
-
-#include <stdio.h>
-#include <tchar.h>
-
-/* PSDK/NDK Headers */
-#define WIN32_NO_STATUS
-#include <windef.h>
-#include <winbase.h>
-
-#include <conutils.h>
-
-#define NTOS_MODE_USER
-#include <ndk/rtlfuncs.h>
-
-/* FMIFS Public Header */
-#include <fmifs/fmifs.h>
-
-#include "resource.h"
-
-#define FMIFS_IMPORT_DLL
-
-// Globals
-BOOL Error = FALSE;
-
-// Switches
-BOOL QuickFormat = FALSE;
-DWORD ClusterSize = 0;
-BOOL CompressDrive = FALSE;
-BOOL GotALabel = FALSE;
-PWCHAR Label = L"";
-PWCHAR Drive = NULL;
-PWCHAR FileSystem = L"FAT";
-
-WCHAR RootDirectory[MAX_PATH];
-WCHAR LabelString[12];
-
-#ifndef FMIFS_IMPORT_DLL
-//
-// Functions in FMIFS.DLL
-//
-PFORMATEX FormatEx;
-PENABLEVOLUMECOMPRESSION EnableVolumeCompression;
-PQUERYAVAILABLEFILESYSTEMFORMAT QueryAvailableFileSystemFormat;
-#endif
-
-
-//
-// Size array
-//
-typedef struct {
- WCHAR SizeString[16];
- DWORD ClusterSize;
-} SIZEDEFINITION, *PSIZEDEFINITION;
-
-SIZEDEFINITION LegalSizes[] = {
- { L"512", 512 },
- { L"1024", 1024 },
- { L"2048", 2048 },
- { L"4096", 4096 },
- { L"8192", 8192 },
- { L"16K", 16384 },
- { L"32K", 32768 },
- { L"64K", 65536 },
- { L"128K", 65536 * 2 },
- { L"256K", 65536 * 4 },
- { L"", 0 },
-};
-
-
-//----------------------------------------------------------------------
-//
-// PrintWin32Error
-//
-// Takes the win32 error code and prints the text version.
-//
-//----------------------------------------------------------------------
-static VOID PrintWin32Error(LPWSTR Message, DWORD ErrorCode)
-{
- ConPrintf(StdErr, L"%s: ", Message);
- ConMsgPuts(StdErr, FORMAT_MESSAGE_FROM_SYSTEM,
- NULL, ErrorCode, LANG_USER_DEFAULT);
- ConPuts(StdErr, L"\n");
-}
-
-
-//----------------------------------------------------------------------
-//
-// ParseCommandLine
-//
-// Get the switches.
-//
-//----------------------------------------------------------------------
-static int ParseCommandLine(int argc, WCHAR *argv[])
-{
- int i, j;
- BOOLEAN gotFormat = FALSE;
- BOOLEAN gotQuick = FALSE;
- BOOLEAN gotSize = FALSE;
- BOOLEAN gotLabel = FALSE;
- BOOLEAN gotCompressed = FALSE;
-
- for (i = 1; i < argc; i++)
- {
- switch (argv[i][0])
- {
- case L'-': case L'/':
-
- if (!_wcsnicmp(&argv[i][1], L"FS:", 3))
- {
- if (gotFormat) return -1;
- FileSystem = &argv[i][4];
- gotFormat = TRUE;
- }
- else if (!_wcsnicmp(&argv[i][1], L"A:", 2))
- {
- if (gotSize) return -1;
- j = 0;
- while (LegalSizes[j].ClusterSize &&
- wcsicmp(LegalSizes[j].SizeString, &argv[i][3]))
- {
- j++;
- }
-
- if (!LegalSizes[j].ClusterSize) return i;
- ClusterSize = LegalSizes[j].ClusterSize;
- gotSize = TRUE;
- }
- else if (!_wcsnicmp(&argv[i][1], L"V:", 2))
- {
- if (gotLabel) return -1;
- Label = &argv[i][3];
- gotLabel = TRUE;
- GotALabel = TRUE;
- }
- else if (!wcsicmp(&argv[i][1], L"Q"))
- {
- if (gotQuick) return -1;
- QuickFormat = TRUE;
- gotQuick = TRUE;
- }
- else if (!wcsicmp(&argv[i][1], L"C"))
- {
- if (gotCompressed) return -1;
- CompressDrive = TRUE;
- gotCompressed = TRUE;
- }
- else
- {
- return i;
- }
- break;
-
- default:
- {
- if (Drive) return i;
- if (argv[i][1] != L':') return i;
-
- Drive = argv[i];
- break;
- }
- }
- }
- return 0;
-}
-
-//----------------------------------------------------------------------
-//
-// FormatExCallback
-//
-// The file system library will call us back with commands that we
-// can interpret. If we wanted to halt the chkdsk we could return FALSE.
-//
-//----------------------------------------------------------------------
-BOOLEAN WINAPI
-FormatExCallback(
- CALLBACKCOMMAND Command,
- ULONG Modifier,
- PVOID Argument)
-{
- PDWORD percent;
- PTEXTOUTPUT output;
- PBOOLEAN status;
-
- //
- // We get other types of commands, but we don't have to pay attention to them
- //
- switch (Command)
- {
- case PROGRESS:
- percent = (PDWORD)Argument;
- ConResPrintf(StdOut, STRING_COMPLETE, *percent);
- break;
-
- case OUTPUT:
- output = (PTEXTOUTPUT)Argument;
- ConPrintf(StdOut, L"%S\n", output->Output);
- break;
-
- case DONE:
- status = (PBOOLEAN)Argument;
- if (*status == FALSE)
- {
- ConResPuts(StdOut, STRING_FORMAT_FAIL);
- Error = TRUE;
- }
- break;
-
- case DONEWITHSTRUCTURE:
- case UNKNOWN2:
- case UNKNOWN3:
- case UNKNOWN4:
- case UNKNOWN5:
- case INSUFFICIENTRIGHTS:
- case FSNOTSUPPORTED:
- case VOLUMEINUSE:
- case UNKNOWN9:
- case UNKNOWNA:
- case UNKNOWNC:
- case UNKNOWND:
- case STRUCTUREPROGRESS:
- case CLUSTERSIZETOOSMALL:
- ConResPuts(StdOut, STRING_NO_SUPPORT);
- return FALSE;
- }
- return TRUE;
-}
-
-#ifndef FMIFS_IMPORT_DLL
-//----------------------------------------------------------------------
-//
-// LoadFMIFSEntryPoints
-//
-// Loads FMIFS.DLL and locates the entry point(s) we are going to use
-//
-//----------------------------------------------------------------------
-static BOOLEAN LoadFMIFSEntryPoints(VOID)
-{
- HMODULE hFmifs = LoadLibraryW( L"fmifs.dll");
- if (hFmifs == NULL)
- return FALSE;
-
- FormatEx = (PFORMATEX)GetProcAddress(hFmifs, "FormatEx");
- if (!FormatEx)
- {
- FreeLibrary(hFmifs);
- return FALSE;
- }
-
- EnableVolumeCompression = (PENABLEVOLUMECOMPRESSION)GetProcAddress(hFmifs, "EnableVolumeCompression");
- if (!EnableVolumeCompression)
- {
- FreeLibrary(hFmifs);
- return FALSE;
- }
-
- QueryAvailableFileSystemFormat = (PQUERYAVAILABLEFILESYSTEMFORMAT)GetProcAddress(hFmifs, "QueryAvailableFileSystemFormat");
- if (!QueryAvailableFileSystemFormat)
- {
- FreeLibrary(hFmifs);
- return FALSE;
- }
-
- return TRUE;
-}
-#endif
-
-
-//----------------------------------------------------------------------
-//
-// Usage
-//
-// Tell the user how to use the program
-//
-//----------------------------------------------------------------------
-static VOID Usage(LPWSTR ProgramName)
-{
- WCHAR szMsg[RC_STRING_MAX_SIZE];
- WCHAR szFormats[MAX_PATH];
- WCHAR szFormatW[MAX_PATH];
- DWORD Index = 0;
- BYTE dummy;
- BOOLEAN latestVersion;
-
- K32LoadStringW(GetModuleHandle(NULL), STRING_HELP, szMsg, ARRAYSIZE(szMsg));
-
-#ifndef FMIFS_IMPORT_DLL
- if (!LoadFMIFSEntryPoints())
- {
- ConPrintf(StdOut, szMsg, ProgramName, L"");
- return;
- }
-#endif
-
- szFormats[0] = 0;
- while (QueryAvailableFileSystemFormat(Index++, szFormatW, &dummy, &dummy, &latestVersion))
- {
- if (!latestVersion)
- continue;
- if (szFormats[0])
- wcscat(szFormats, L", ");
-
- wcscat(szFormats, szFormatW);
- }
- ConPrintf(StdOut, szMsg, ProgramName, szFormats);
-}
-
-
-//----------------------------------------------------------------------
-//
-// WMain
-//
-// Engine. Just get command line switches and fire off a format. This
-// could also be done in a GUI like Explorer does when you select a
-// drive and run a check on it.
-//
-// We do this in UNICODE because the chkdsk command expects PWCHAR
-// arguments.
-//
-//----------------------------------------------------------------------
-int wmain(int argc, WCHAR *argv[])
-{
- int badArg;
- FMIFS_MEDIA_FLAG media = FMIFS_HARDDISK;
- DWORD driveType;
- WCHAR fileSystem[1024];
- WCHAR volumeName[1024];
- WCHAR input[1024];
- DWORD serialNumber;
- DWORD flags, maxComponent;
- ULARGE_INTEGER freeBytesAvailableToCaller, totalNumberOfBytes, totalNumberOfFreeBytes;
- WCHAR szMsg[RC_STRING_MAX_SIZE];
-
- /* Initialize the Console Standard Streams */
- ConInitStdStreams();
-
- ConPuts(StdOut,
- L"\n"
- L"Formatx v1.0 by Mark Russinovich\n"
- L"Systems Internals - http://www.sysinternals.com\n"
- L"ReactOS adaptation 1999 by Emanuele Aliberti\n\n");
-
-#ifndef FMIFS_IMPORT_DLL
- //
- // Get function pointers
- //
- if (!LoadFMIFSEntryPoints())
- {
- ConResPuts(StdErr, STRING_FMIFS_FAIL);
- return -1;
- }
-#endif
-
- //
- // Parse command line
- //
- badArg = ParseCommandLine(argc, argv);
- if (badArg)
- {
- ConResPrintf(StdErr, STRING_UNKNOW_ARG, argv[badArg]);
- Usage(argv[0]);
- return -1;
- }
-
- //
- // Get the drive's format
- //
- if (!Drive)
- {
- ConResPuts(StdErr, STRING_DRIVE_PARM);
- Usage(argv[0]);
- return -1;
- }
- else
- {
- wcscpy(RootDirectory, Drive);
- }
- RootDirectory[2] = L'\\';
- RootDirectory[3] = L'\0';
-
- //
- // See if the drive is removable or not
- //
- driveType = GetDriveTypeW(RootDirectory);
- switch (driveType)
- {
- case DRIVE_UNKNOWN :
- K32LoadStringW(GetModuleHandle(NULL), STRING_ERROR_DRIVE_TYPE, szMsg, ARRAYSIZE(szMsg));
- PrintWin32Error(szMsg, GetLastError());
- return -1;
-
- case DRIVE_REMOTE:
- case DRIVE_CDROM:
- ConResPuts(StdOut, STRING_NO_SUPPORT);
- return -1;
-
- case DRIVE_NO_ROOT_DIR:
- K32LoadStringW(GetModuleHandle(NULL), STRING_NO_VOLUME, szMsg, ARRAYSIZE(szMsg));
- PrintWin32Error(szMsg, GetLastError());
- return -1;
-
- case DRIVE_REMOVABLE:
- ConResPrintf(StdOut, STRING_INSERT_DISK, RootDirectory[0]);
- fgetws(input, ARRAYSIZE(input), stdin);
- media = FMIFS_FLOPPY;
- break;
-
- case DRIVE_FIXED:
- case DRIVE_RAMDISK:
- media = FMIFS_HARDDISK;
- break;
- }
-
- // Reject attempts to format the system drive
- {
- WCHAR path[MAX_PATH + 1];
- UINT rc;
- rc = GetWindowsDirectoryW(path, MAX_PATH);
- if (rc == 0 || rc > MAX_PATH)
- // todo: Report "Unable to query system directory"
- return -1;
- if (towlower(path[0]) == towlower(Drive[0]))
- {
- // todo: report "Cannot format system drive"
- ConResPuts(StdOut, STRING_NO_SUPPORT);
- return -1;
- }
- }
-
- //
- // Determine the drive's file system format
- //
- if (!GetVolumeInformationW(RootDirectory,
- volumeName, ARRAYSIZE(volumeName),
- &serialNumber, &maxComponent, &flags,
- fileSystem, ARRAYSIZE(fileSystem)))
- {
- K32LoadStringW(GetModuleHandle(NULL), STRING_NO_VOLUME, szMsg, ARRAYSIZE(szMsg));
- PrintWin32Error(szMsg, GetLastError());
- return -1;
- }
-
- if (!GetDiskFreeSpaceExW(RootDirectory,
- &freeBytesAvailableToCaller,
- &totalNumberOfBytes,
- &totalNumberOfFreeBytes))
- {
- K32LoadStringW(GetModuleHandle(NULL), STRING_NO_VOLUME_SIZE, szMsg, ARRAYSIZE(szMsg));
- PrintWin32Error(szMsg, GetLastError());
- return -1;
- }
- ConResPrintf(StdOut, STRING_FILESYSTEM, fileSystem);
-
- //
- // Make sure they want to do this
- //
- if (driveType == DRIVE_FIXED)
- {
- if (volumeName[0])
- {
- while (TRUE)
- {
- ConResPrintf(StdOut, STRING_LABEL_NAME_EDIT, RootDirectory[0]);
- fgetws(input, ARRAYSIZE(input), stdin);
- input[wcslen(input) - 1] = 0;
-
- if (!wcsicmp(input, volumeName))
- break;
-
- ConResPuts(StdOut, STRING_ERROR_LABEL);
- }
- }
-
- ConResPrintf(StdOut, STRING_YN_FORMAT, RootDirectory[0]);
-
- K32LoadStringW(GetModuleHandle(NULL), STRING_YES_NO_FAQ, szMsg, ARRAYSIZE(szMsg));
- while (TRUE)
- {
- fgetws(input, ARRAYSIZE(input), stdin);
- if (_wcsnicmp(&input[0], &szMsg[0], 1) == 0) break;
- if (_wcsnicmp(&input[0], &szMsg[1], 1) == 0)
- {
- ConPuts(StdOut, L"\n");
- return 0;
- }
- }
- }
-
- //
- // Tell the user we're doing a long format if appropriate
- //
- if (!QuickFormat)
- {
- K32LoadStringW(GetModuleHandle(NULL), STRING_VERIFYING, szMsg, ARRAYSIZE(szMsg));
- if (totalNumberOfBytes.QuadPart > 1024*1024*10)
- {
- ConPrintf(StdOut, L"%s %luM\n", szMsg, (DWORD)(totalNumberOfBytes.QuadPart/(1024*1024)));
- }
- else
- {
- ConPrintf(StdOut, L"%s %.1fM\n", szMsg,
- ((float)(LONGLONG)totalNumberOfBytes.QuadPart)/(float)(1024.0*1024.0));
- }
- }
- else
- {
- K32LoadStringW(GetModuleHandle(NULL), STRING_FAST_FMT, szMsg, ARRAYSIZE(szMsg));
- if (totalNumberOfBytes.QuadPart > 1024*1024*10)
- {
- ConPrintf(StdOut, L"%s %luM\n", szMsg, (DWORD)(totalNumberOfBytes.QuadPart/(1024*1024)));
- }
- else
- {
- ConPrintf(StdOut, L"%s %.2fM\n", szMsg,
- ((float)(LONGLONG)totalNumberOfBytes.QuadPart)/(float)(1024.0*1024.0));
- }
- ConResPuts(StdOut, STRING_CREATE_FSYS);
- }
-
- //
- // Format away!
- //
- FormatEx(RootDirectory, media, FileSystem, Label, QuickFormat,
- ClusterSize, FormatExCallback);
- if (Error) return -1;
- ConResPuts(StdOut, STRING_FMT_COMPLETE);
-
- //
- // Enable compression if desired
- //
- if (CompressDrive)
- {
- if (!EnableVolumeCompression(RootDirectory, TRUE))
- ConResPuts(StdOut, STRING_VOL_COMPRESS);
- }
-
- //
- // Get the label if we don't have it
- //
- if (!GotALabel)
- {
- ConResPuts(StdOut, STRING_ENTER_LABEL);
- fgetws(input, ARRAYSIZE(LabelString), stdin);
-
- input[wcslen(input) - 1] = 0;
- if (!SetVolumeLabelW(RootDirectory, input))
- {
- K32LoadStringW(GetModuleHandle(NULL), STRING_NO_LABEL, szMsg, ARRAYSIZE(szMsg));
- PrintWin32Error(szMsg, GetLastError());
- return -1;
- }
- }
-
- if (!GetVolumeInformationW(RootDirectory,
- volumeName, ARRAYSIZE(volumeName),
- &serialNumber, &maxComponent, &flags,
- fileSystem, ARRAYSIZE(fileSystem)))
- {
- K32LoadStringW(GetModuleHandle(NULL), STRING_NO_VOLUME, szMsg, ARRAYSIZE(szMsg));
- PrintWin32Error(szMsg, GetLastError());
- return -1;
- }
-
- //
- // Print out some stuff including the formatted size
- //
- if (!GetDiskFreeSpaceExW(RootDirectory,
- &freeBytesAvailableToCaller,
- &totalNumberOfBytes,
- &totalNumberOfFreeBytes))
- {
- K32LoadStringW(GetModuleHandle(NULL), STRING_NO_VOLUME_SIZE, szMsg, ARRAYSIZE(szMsg));
- PrintWin32Error(szMsg, GetLastError());
- return -1;
- }
-
- ConResPrintf(StdOut, STRING_FREE_SPACE, totalNumberOfBytes.QuadPart,
- totalNumberOfFreeBytes.QuadPart);
-
- //
- // Get the drive's serial number
- //
- if (!GetVolumeInformationW(RootDirectory,
- volumeName, ARRAYSIZE(volumeName),
- &serialNumber, &maxComponent, &flags,
- fileSystem, ARRAYSIZE(fileSystem)))
- {
- K32LoadStringW(GetModuleHandle(NULL), STRING_NO_VOLUME, szMsg, ARRAYSIZE(szMsg));
- PrintWin32Error(szMsg, GetLastError());
- return -1;
- }
- ConResPrintf(StdOut, STRING_SERIAL_NUMBER,
- (unsigned int)(serialNumber >> 16),
- (unsigned int)(serialNumber & 0xFFFF));
-
- return 0;
-}
-
-/* EOF */