Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenautochk.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
1.7.6.1
|