ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

autochk.c
Go to the documentation of this file.
00001 /* PROJECT:         ReactOS Kernel
00002  * LICENSE:         GPL - See COPYING in the top level directory
00003  * FILE:            base/system/autochk/autochk.c
00004  * PURPOSE:         Filesystem checker
00005  * PROGRAMMERS:     Aleksey Bragin
00006  *                  Eric Kohl
00007  *                  Hervé Poussineau
00008  */
00009 
00010 /* INCLUDES *****************************************************************/
00011 
00012 #include <stdio.h>
00013 #define WIN32_NO_STATUS
00014 #include <windows.h>
00015 #define NTOS_MODE_USER
00016 #include <ndk/exfuncs.h>
00017 #include <ndk/iofuncs.h>
00018 #include <ndk/obfuncs.h>
00019 #include <ndk/psfuncs.h>
00020 #include <ndk/rtlfuncs.h>
00021 #include <ndk/umfuncs.h>
00022 #include <fmifs/fmifs.h>
00023 
00024 #define NDEBUG
00025 #include <debug.h>
00026 
00027 /* DEFINES ******************************************************************/
00028 
00029 #define FS_ATTRIBUTE_BUFFER_SIZE (MAX_PATH * sizeof(WCHAR) + sizeof(FILE_FS_ATTRIBUTE_INFORMATION))
00030 
00031 
00032 /* FUNCTIONS ****************************************************************/
00033 //
00034 // FMIFS function
00035 //
00036 
00037 static VOID
00038 PrintString(char* fmt,...)
00039 {
00040     char buffer[512];
00041     va_list ap;
00042     UNICODE_STRING UnicodeString;
00043     ANSI_STRING AnsiString;
00044 
00045     va_start(ap, fmt);
00046     vsprintf(buffer, fmt, ap);
00047     va_end(ap);
00048 
00049     RtlInitAnsiString(&AnsiString, buffer);
00050     RtlAnsiStringToUnicodeString(&UnicodeString,
00051                                  &AnsiString,
00052                                  TRUE);
00053     NtDisplayString(&UnicodeString);
00054     RtlFreeUnicodeString(&UnicodeString);
00055 }
00056 
00057 // this func is taken from kernel32/file/volume.c
00058 static HANDLE
00059 OpenDirectory(
00060     IN LPCWSTR DirName,
00061     IN BOOLEAN Write)
00062 {
00063     UNICODE_STRING NtPathU;
00064     OBJECT_ATTRIBUTES ObjectAttributes;
00065     NTSTATUS Status;
00066     IO_STATUS_BLOCK IoStatusBlock;
00067     HANDLE hFile;
00068 
00069     if (!RtlDosPathNameToNtPathName_U(DirName,
00070                                       &NtPathU,
00071                                       NULL,
00072                                       NULL))
00073     {
00074         DPRINT1("Invalid path!\n");
00075         return INVALID_HANDLE_VALUE;
00076     }
00077 
00078     InitializeObjectAttributes(
00079         &ObjectAttributes,
00080         &NtPathU,
00081         OBJ_CASE_INSENSITIVE,
00082         NULL,
00083         NULL);
00084 
00085     Status = NtCreateFile(
00086         &hFile,
00087         Write ? FILE_GENERIC_WRITE : FILE_GENERIC_READ,
00088         &ObjectAttributes,
00089         &IoStatusBlock,
00090         NULL,
00091         0,
00092         FILE_SHARE_READ|FILE_SHARE_WRITE,
00093         FILE_OPEN,
00094         0,
00095         NULL,
00096         0);
00097 
00098     RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathU.Buffer);
00099 
00100     if (!NT_SUCCESS(Status))
00101     {
00102         return INVALID_HANDLE_VALUE;
00103     }
00104 
00105     return hFile;
00106 }
00107 
00108 static NTSTATUS
00109 GetFileSystem(
00110     IN LPCWSTR Drive,
00111     IN OUT LPWSTR FileSystemName,
00112     IN SIZE_T FileSystemNameSize)
00113 {
00114     HANDLE FileHandle;
00115     NTSTATUS Status;
00116     IO_STATUS_BLOCK IoStatusBlock;
00117     PFILE_FS_ATTRIBUTE_INFORMATION FileFsAttribute;
00118     UCHAR Buffer[FS_ATTRIBUTE_BUFFER_SIZE];
00119 
00120     FileFsAttribute = (PFILE_FS_ATTRIBUTE_INFORMATION)Buffer;
00121 
00122     FileHandle = OpenDirectory(Drive, FALSE);
00123     if (FileHandle == INVALID_HANDLE_VALUE)
00124         return STATUS_INVALID_PARAMETER;
00125 
00126     Status = NtQueryVolumeInformationFile(FileHandle,
00127                                           &IoStatusBlock,
00128                                           FileFsAttribute,
00129                                           FS_ATTRIBUTE_BUFFER_SIZE,
00130                                           FileFsAttributeInformation);
00131     NtClose(FileHandle);
00132 
00133     if (NT_SUCCESS(Status))
00134     {
00135         if (FileSystemNameSize * sizeof(WCHAR) >= FileFsAttribute->FileSystemNameLength + sizeof(WCHAR))
00136         {
00137             CopyMemory(FileSystemName,
00138                        FileFsAttribute->FileSystemName,
00139                        FileFsAttribute->FileSystemNameLength);
00140             FileSystemName[FileFsAttribute->FileSystemNameLength / sizeof(WCHAR)] = 0;
00141         }
00142         else
00143             return STATUS_BUFFER_TOO_SMALL;
00144     }
00145     else
00146         return Status;
00147 
00148     return STATUS_SUCCESS;
00149 }
00150 
00151 // This is based on SysInternal's ChkDsk app
00152 static BOOLEAN NTAPI
00153 ChkdskCallback(
00154     IN CALLBACKCOMMAND Command,
00155     IN ULONG Modifier,
00156     IN PVOID Argument)
00157 {
00158     PDWORD      Percent;
00159     PBOOLEAN    Status;
00160     PTEXTOUTPUT Output;
00161 
00162     //
00163     // We get other types of commands,
00164     // but we don't have to pay attention to them
00165     //
00166     switch(Command)
00167     {
00168     case UNKNOWN2:
00169         DPRINT("UNKNOWN2\r");
00170         break;
00171 
00172     case UNKNOWN3:
00173         DPRINT("UNKNOWN3\r");
00174         break;
00175 
00176     case UNKNOWN4:
00177         DPRINT("UNKNOWN4\r");
00178         break;
00179 
00180     case UNKNOWN5:
00181         DPRINT("UNKNOWN5\r");
00182         break;
00183 
00184     case UNKNOWN9:
00185         DPRINT("UNKNOWN9\r");
00186         break;
00187 
00188     case UNKNOWNA:
00189         DPRINT("UNKNOWNA\r");
00190         break;
00191 
00192     case UNKNOWNC:
00193         DPRINT("UNKNOWNC\r");
00194         break;
00195 
00196     case UNKNOWND:
00197         DPRINT("UNKNOWND\r");
00198         break;
00199 
00200     case INSUFFICIENTRIGHTS:
00201         DPRINT("INSUFFICIENTRIGHTS\r");
00202         break;
00203 
00204     case FSNOTSUPPORTED:
00205         DPRINT("FSNOTSUPPORTED\r");
00206         break;
00207 
00208     case VOLUMEINUSE:
00209         DPRINT("VOLUMEINUSE\r");
00210         break;
00211 
00212     case STRUCTUREPROGRESS:
00213         DPRINT("STRUCTUREPROGRESS\r");
00214         break;
00215 
00216     case DONEWITHSTRUCTURE:
00217         DPRINT("DONEWITHSTRUCTURE\r");
00218         break;
00219 
00220     case CLUSTERSIZETOOSMALL:
00221         DPRINT("CLUSTERSIZETOOSMALL\r");
00222         break;
00223 
00224     case PROGRESS:
00225         Percent = (PDWORD) Argument;
00226         PrintString("%d percent completed.\r", *Percent);
00227         break;
00228 
00229     case OUTPUT:
00230         Output = (PTEXTOUTPUT) Argument;
00231         PrintString("%s", Output->Output);
00232         break;
00233 
00234     case DONE:
00235         Status = (PBOOLEAN)Argument;
00236         if (*Status == TRUE)
00237         {
00238             PrintString("Autochk was unable to complete successfully.\n\n");
00239             //Error = TRUE;
00240         }
00241         break;
00242     }
00243     return TRUE;
00244 }
00245 
00246 /* Load the provider associated with this file system */
00247 static PVOID
00248 LoadProvider(
00249     IN PWCHAR FileSystem)
00250 {
00251     UNICODE_STRING ProviderDll;
00252     PVOID BaseAddress;
00253     NTSTATUS Status;
00254 
00255     /* FIXME: add more providers here */
00256 
00257     if (wcscmp(FileSystem, L"NTFS") == 0)
00258     {
00259       RtlInitUnicodeString(&ProviderDll, L"untfs.dll");
00260     }
00261     else if (wcscmp(FileSystem, L"FAT") == 0
00262              || wcscmp(FileSystem, L"FAT32") == 0)
00263     {
00264       RtlInitUnicodeString(&ProviderDll, L"ufat.dll");
00265     }
00266     else
00267     {
00268       return NULL;
00269     }
00270 
00271     Status = LdrLoadDll(NULL, NULL, &ProviderDll, &BaseAddress);
00272     if (!NT_SUCCESS(Status))
00273         return NULL;
00274     return BaseAddress;
00275 }
00276 
00277 static NTSTATUS
00278 CheckVolume(
00279     IN PWCHAR DrivePath)
00280 {
00281     WCHAR FileSystem[128];
00282     ANSI_STRING ChkdskFunctionName = RTL_CONSTANT_STRING("ChkdskEx");
00283     PVOID Provider;
00284     CHKDSKEX ChkdskFunc;
00285     WCHAR NtDrivePath[64];
00286     UNICODE_STRING DrivePathU;
00287     NTSTATUS Status;
00288 
00289     /* Get the file system */
00290     Status = GetFileSystem(DrivePath,
00291                            FileSystem,
00292                            sizeof(FileSystem) / sizeof(FileSystem[0]));
00293     if (!NT_SUCCESS(Status))
00294     {
00295         DPRINT1("GetFileSystem() failed with status 0x%08lx\n", Status);
00296         PrintString("  Unable to get file system of %S\n", DrivePath);
00297         return Status;
00298     }
00299 
00300     /* Load the provider which will do the chkdsk */
00301     Provider = LoadProvider(FileSystem);
00302     if (Provider == NULL)
00303     {
00304         DPRINT1("LoadProvider() failed\n");
00305         PrintString("  Unable to verify a %S volume\n", FileSystem);
00306         return STATUS_DLL_NOT_FOUND;
00307     }
00308 
00309     /* Get the Chkdsk function address */
00310     Status = LdrGetProcedureAddress(Provider,
00311                                     &ChkdskFunctionName,
00312                                     0,
00313                                     (PVOID*)&ChkdskFunc);
00314     if (!NT_SUCCESS(Status))
00315     {
00316         DPRINT1("LdrGetProcedureAddress() failed with status 0x%08lx\n", Status);
00317         PrintString("  Unable to verify a %S volume\n", FileSystem);
00318         LdrUnloadDll(Provider);
00319         return Status;
00320     }
00321 
00322     /* Call provider */
00323     //PrintString("  Verifying volume %S\n", DrivePath);
00324     swprintf(NtDrivePath, L"\\??\\");
00325     wcscat(NtDrivePath, DrivePath);
00326     NtDrivePath[wcslen(NtDrivePath)-1] = 0;
00327     RtlInitUnicodeString(&DrivePathU, NtDrivePath);
00328 
00329     DPRINT("AUTOCHK: Checking %wZ\n", &DrivePathU);
00330     Status = ChkdskFunc(&DrivePathU,
00331                         TRUE, // FixErrors
00332                         TRUE, // Verbose
00333                         TRUE, // CheckOnlyIfDirty
00334                         FALSE,// ScanDrive
00335                         ChkdskCallback);
00336 
00337     LdrUnloadDll(Provider);
00338     return Status;
00339 }
00340 
00341 /* Native image's entry point */
00342 int
00343 _cdecl
00344 _main(int argc,
00345       char *argv[],
00346       char *envp[],
00347       int DebugFlag)
00348 {
00349     PROCESS_DEVICEMAP_INFORMATION DeviceMap;
00350     ULONG i;
00351     NTSTATUS Status;
00352     WCHAR DrivePath[128];
00353 
00354     // Win2003 passes the only param - "*". Probably means to check all drives
00355     /*
00356     DPRINT("Got %d params\n", argc);
00357     for (i=0; i<argc; i++)
00358         DPRINT("Param %d: %s\n", i, argv[i]);
00359     */
00360 
00361     /* FIXME: We should probably use here the mount manager to be
00362      * able to check volumes which don't have a drive letter.
00363      */
00364 
00365     Status = NtQueryInformationProcess(NtCurrentProcess(),
00366                                        ProcessDeviceMap,
00367                                        &DeviceMap.Query,
00368                                        sizeof(DeviceMap.Query),
00369                                        NULL);
00370     if (!NT_SUCCESS(Status))
00371     {
00372         DPRINT1("NtQueryInformationProcess() failed with status 0x%08lx\n",
00373             Status);
00374         return 1;
00375     }
00376 
00377     for (i = 0; i < 26; i++)
00378     {
00379         if ((DeviceMap.Query.DriveMap & (1 << i))
00380          && (DeviceMap.Query.DriveType[i] == DOSDEVICE_DRIVE_FIXED))
00381         {
00382             swprintf(DrivePath, L"%c:\\", L'A'+i);
00383             CheckVolume(DrivePath);
00384         }
00385     }
00386     //PrintString("  Done\n\n");
00387     return 0;
00388 }
00389 
00390 /* EOF */

Generated on Mon May 28 2012 04:18:27 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.