Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenfs.c
Go to the documentation of this file.
00001 /* 00002 * FreeLoader 00003 * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com> 00004 * Copyright (C) 2008-2009 Hervé Poussineau <hpoussin@reactos.org> 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License along 00017 * with this program; if not, write to the Free Software Foundation, Inc., 00018 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00019 */ 00020 00021 #include <freeldr.h> 00022 00023 #define NDEBUG 00024 #include <debug.h> 00025 00026 DBG_DEFAULT_CHANNEL(FILESYSTEM); 00027 00029 // FUNCTIONS 00031 00032 VOID FileSystemError(PCSTR ErrorString) 00033 { 00034 ERR("%s\n", ErrorString); 00035 00036 UiMessageBox(ErrorString); 00037 } 00038 00039 PFILE FsOpenFile(PCSTR FileName) 00040 { 00041 CHAR FullPath[MAX_PATH]; 00042 ULONG FileId; 00043 LONG ret; 00044 00045 // 00046 // Print status message 00047 // 00048 TRACE("Opening file '%s'...\n", FileName); 00049 00050 // 00051 // Create full file name 00052 // 00053 MachDiskGetBootPath(FullPath, sizeof(FullPath)); 00054 strcat(FullPath, FileName); 00055 00056 // 00057 // Open the file 00058 // 00059 ret = ArcOpen(FullPath, OpenReadOnly, &FileId); 00060 00061 // 00062 // Check for success 00063 // 00064 if (ret == ESUCCESS) 00065 return (PFILE)FileId; 00066 else 00067 return (PFILE)0; 00068 } 00069 00070 VOID FsCloseFile(PFILE FileHandle) 00071 { 00072 ULONG FileId = (ULONG)FileHandle; 00073 00074 // 00075 // Close the handle 00076 // 00077 ArcClose(FileId); 00078 00079 // 00080 // Do not check for error; this function is 00081 // supposed to always succeed 00082 // 00083 } 00084 00085 /* 00086 * ReadFile() 00087 * returns number of bytes read or EOF 00088 */ 00089 BOOLEAN FsReadFile(PFILE FileHandle, ULONG BytesToRead, ULONG* BytesRead, PVOID Buffer) 00090 { 00091 ULONG FileId = (ULONG)FileHandle; 00092 LONG ret; 00093 00094 // 00095 // Read the file 00096 // 00097 ret = ArcRead(FileId, Buffer, BytesToRead, BytesRead); 00098 00099 // 00100 // Check for success 00101 // 00102 if (ret == ESUCCESS) 00103 return TRUE; 00104 else 00105 return FALSE; 00106 } 00107 00108 ULONG FsGetFileSize(PFILE FileHandle) 00109 { 00110 ULONG FileId = (ULONG)FileHandle; 00111 FILEINFORMATION Information; 00112 LONG ret; 00113 00114 // 00115 // Query file informations 00116 // 00117 ret = ArcGetFileInformation(FileId, &Information); 00118 00119 // 00120 // Check for error 00121 // 00122 if (ret != ESUCCESS || Information.EndingAddress.HighPart != 0) 00123 return 0; 00124 00125 // 00126 // Return file size 00127 // 00128 return Information.EndingAddress.LowPart; 00129 } 00130 00131 VOID FsSetFilePointer(PFILE FileHandle, ULONG NewFilePointer) 00132 { 00133 ULONG FileId = (ULONG)FileHandle; 00134 LARGE_INTEGER Position; 00135 00136 // 00137 // Set file position 00138 // 00139 Position.HighPart = 0; 00140 Position.LowPart = NewFilePointer; 00141 ArcSeek(FileId, &Position, SeekAbsolute); 00142 00143 // 00144 // Do not check for error; this function is 00145 // supposed to always succeed 00146 // 00147 } 00148 00149 /* 00150 * FsGetNumPathParts() 00151 * This function parses a path in the form of dir1\dir2\file1.ext 00152 * and returns the number of parts it has (i.e. 3 - dir1,dir2,file1.ext) 00153 */ 00154 ULONG FsGetNumPathParts(PCSTR Path) 00155 { 00156 size_t i; 00157 ULONG num; 00158 00159 for (i=0,num=0; i<strlen(Path); i++) 00160 { 00161 if ((Path[i] == '\\') || (Path[i] == '/')) 00162 { 00163 num++; 00164 } 00165 } 00166 num++; 00167 00168 TRACE("FsGetNumPathParts() Path = %s NumPathParts = %d\n", Path, num); 00169 00170 return num; 00171 } 00172 00173 /* 00174 * FsGetFirstNameFromPath() 00175 * This function parses a path in the form of dir1\dir2\file1.ext 00176 * and puts the first name of the path (e.g. "dir1") in buffer 00177 * compatible with the MSDOS directory structure 00178 */ 00179 VOID FsGetFirstNameFromPath(PCHAR Buffer, PCSTR Path) 00180 { 00181 size_t i; 00182 00183 // Copy all the characters up to the end of the 00184 // string or until we hit a '\' character 00185 // and put them in Buffer 00186 for (i=0; i<strlen(Path); i++) 00187 { 00188 if ((Path[i] == '\\') || (Path[i] == '/')) 00189 { 00190 break; 00191 } 00192 else 00193 { 00194 Buffer[i] = Path[i]; 00195 } 00196 } 00197 00198 Buffer[i] = 0; 00199 00200 TRACE("FsGetFirstNameFromPath() Path = %s FirstName = %s\n", Path, Buffer); 00201 } 00202 00203 typedef struct tagFILEDATA 00204 { 00205 ULONG DeviceId; 00206 ULONG ReferenceCount; 00207 const DEVVTBL* FuncTable; 00208 const DEVVTBL* FileFuncTable; 00209 VOID* Specific; 00210 } FILEDATA; 00211 00212 typedef struct tagDEVICE 00213 { 00214 LIST_ENTRY ListEntry; 00215 const DEVVTBL* FuncTable; 00216 CHAR* Prefix; 00217 ULONG DeviceId; 00218 ULONG ReferenceCount; 00219 } DEVICE; 00220 00221 static FILEDATA FileData[MAX_FDS]; 00222 static LIST_ENTRY DeviceListHead; 00223 00224 LONG ArcClose(ULONG FileId) 00225 { 00226 LONG ret; 00227 00228 if (FileId >= MAX_FDS || !FileData[FileId].FuncTable) 00229 return EBADF; 00230 00231 ret = FileData[FileId].FuncTable->Close(FileId); 00232 00233 if (ret == ESUCCESS) 00234 { 00235 FileData[FileId].FuncTable = NULL; 00236 FileData[FileId].Specific = NULL; 00237 FileData[FileId].DeviceId = -1; 00238 } 00239 return ret; 00240 } 00241 00242 LONG ArcGetFileInformation(ULONG FileId, FILEINFORMATION* Information) 00243 { 00244 if (FileId >= MAX_FDS || !FileData[FileId].FuncTable) 00245 return EBADF; 00246 return FileData[FileId].FuncTable->GetFileInformation(FileId, Information); 00247 } 00248 00249 LONG ArcOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId) 00250 { 00251 ULONG Count, i, ret; 00252 PLIST_ENTRY pEntry; 00253 DEVICE* pDevice; 00254 CHAR* DeviceName; 00255 CHAR* FileName; 00256 CHAR* p; 00257 CHAR* q; 00258 SIZE_T Length; 00259 OPENMODE DeviceOpenMode; 00260 ULONG DeviceId; 00261 00262 /* Print status message */ 00263 TRACE("Opening file '%s'...\n", Path); 00264 00265 *FileId = MAX_FDS; 00266 00267 /* Search last ')', which delimits device and path */ 00268 FileName = strrchr(Path, ')'); 00269 if (!FileName) 00270 return EINVAL; 00271 FileName++; 00272 00273 /* Count number of "()", which needs to be replaced by "(0)" */ 00274 Count = 0; 00275 for (p = Path; p != FileName; p++) 00276 if (*p == '(' && *(p + 1) == ')') 00277 Count++; 00278 00279 /* Duplicate device name, and replace "()" by "(0)" (if required) */ 00280 Length = FileName - Path + Count; 00281 if (Count != 0) 00282 { 00283 DeviceName = MmHeapAlloc(FileName - Path + Count); 00284 if (!DeviceName) 00285 return ENOMEM; 00286 for (p = Path, q = DeviceName; p != FileName; p++) 00287 { 00288 *q++ = *p; 00289 if (*p == '(' && *(p + 1) == ')') 00290 *q++ = '0'; 00291 } 00292 } 00293 else 00294 DeviceName = Path; 00295 00296 /* Search for the device */ 00297 pEntry = DeviceListHead.Flink; 00298 if (OpenMode == OpenReadOnly || OpenMode == OpenWriteOnly) 00299 DeviceOpenMode = OpenMode; 00300 else 00301 DeviceOpenMode = OpenReadWrite; 00302 while (pEntry != &DeviceListHead) 00303 { 00304 pDevice = CONTAINING_RECORD(pEntry, DEVICE, ListEntry); 00305 if (strncmp(pDevice->Prefix, DeviceName, Length) == 0) 00306 { 00307 /* OK, device found. It is already opened? */ 00308 if (pDevice->ReferenceCount == 0) 00309 { 00310 /* Search some room for the device */ 00311 for (DeviceId = 0; DeviceId < MAX_FDS; DeviceId++) 00312 if (!FileData[DeviceId].FuncTable) 00313 break; 00314 if (DeviceId == MAX_FDS) 00315 return EMFILE; 00316 /* Try to open the device */ 00317 FileData[DeviceId].FuncTable = pDevice->FuncTable; 00318 ret = pDevice->FuncTable->Open(pDevice->Prefix, DeviceOpenMode, &DeviceId); 00319 if (ret != ESUCCESS) 00320 { 00321 FileData[DeviceId].FuncTable = NULL; 00322 return ret; 00323 } 00324 else if (!*FileName) 00325 { 00326 /* Done, caller wanted to open the raw device */ 00327 *FileId = DeviceId; 00328 pDevice->ReferenceCount++; 00329 return ESUCCESS; 00330 } 00331 00332 /* Try to detect the file system */ 00333 #ifndef _M_ARM 00334 FileData[DeviceId].FileFuncTable = IsoMount(DeviceId); 00335 if (!FileData[DeviceId].FileFuncTable) 00336 #endif 00337 FileData[DeviceId].FileFuncTable = FatMount(DeviceId); 00338 #ifndef _M_ARM 00339 if (!FileData[DeviceId].FileFuncTable) 00340 FileData[DeviceId].FileFuncTable = NtfsMount(DeviceId); 00341 if (!FileData[DeviceId].FileFuncTable) 00342 FileData[DeviceId].FileFuncTable = Ext2Mount(DeviceId); 00343 #endif 00344 #if defined(_M_IX86) || defined(_M_AMD64) 00345 if (!FileData[DeviceId].FileFuncTable) 00346 FileData[DeviceId].FileFuncTable = PxeMount(DeviceId); 00347 #endif 00348 if (!FileData[DeviceId].FileFuncTable) 00349 { 00350 /* Error, unable to detect file system */ 00351 pDevice->FuncTable->Close(DeviceId); 00352 FileData[DeviceId].FuncTable = NULL; 00353 return ENODEV; 00354 } 00355 00356 pDevice->DeviceId = DeviceId; 00357 } 00358 else 00359 { 00360 DeviceId = pDevice->DeviceId; 00361 } 00362 pDevice->ReferenceCount++; 00363 break; 00364 } 00365 pEntry = pEntry->Flink; 00366 } 00367 if (pEntry == &DeviceListHead) 00368 return ENODEV; 00369 00370 /* At this point, device is found and opened. Its file id is stored 00371 * in DeviceId, and FileData[DeviceId].FileFuncTable contains what 00372 * needs to be called to open the file */ 00373 00374 /* Search some room for the device */ 00375 for (i = 0; i < MAX_FDS; i++) 00376 if (!FileData[i].FuncTable) 00377 break; 00378 if (i == MAX_FDS) 00379 return EMFILE; 00380 00381 /* Skip leading backslash, if any */ 00382 if (*FileName == '\\') 00383 FileName++; 00384 00385 /* Open the file */ 00386 FileData[i].FuncTable = FileData[DeviceId].FileFuncTable; 00387 FileData[i].DeviceId = DeviceId; 00388 *FileId = i; 00389 ret = FileData[i].FuncTable->Open(FileName, OpenMode, FileId); 00390 if (ret != ESUCCESS) 00391 { 00392 FileData[i].FuncTable = NULL; 00393 *FileId = MAX_FDS; 00394 } 00395 return ret; 00396 } 00397 00398 LONG ArcRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count) 00399 { 00400 if (FileId >= MAX_FDS || !FileData[FileId].FuncTable) 00401 return EBADF; 00402 return FileData[FileId].FuncTable->Read(FileId, Buffer, N, Count); 00403 } 00404 00405 LONG ArcSeek(ULONG FileId, LARGE_INTEGER* Position, SEEKMODE SeekMode) 00406 { 00407 if (FileId >= MAX_FDS || !FileData[FileId].FuncTable) 00408 return EBADF; 00409 return FileData[FileId].FuncTable->Seek(FileId, Position, SeekMode); 00410 } 00411 00412 VOID FsRegisterDevice(CHAR* Prefix, const DEVVTBL* FuncTable) 00413 { 00414 DEVICE* pNewEntry; 00415 SIZE_T Length; 00416 00417 TRACE("FsRegisterDevice() Prefix = %s\n", Prefix); 00418 00419 Length = strlen(Prefix) + 1; 00420 pNewEntry = MmHeapAlloc(sizeof(DEVICE) + Length); 00421 if (!pNewEntry) 00422 return; 00423 pNewEntry->FuncTable = FuncTable; 00424 pNewEntry->ReferenceCount = 0; 00425 pNewEntry->Prefix = (CHAR*)(pNewEntry + 1); 00426 memcpy(pNewEntry->Prefix, Prefix, Length); 00427 00428 InsertHeadList(&DeviceListHead, &pNewEntry->ListEntry); 00429 } 00430 00431 LPCWSTR FsGetServiceName(ULONG FileId) 00432 { 00433 if (FileId >= MAX_FDS || !FileData[FileId].FuncTable) 00434 return NULL; 00435 return FileData[FileId].FuncTable->ServiceName; 00436 } 00437 00438 VOID FsSetDeviceSpecific(ULONG FileId, VOID* Specific) 00439 { 00440 if (FileId >= MAX_FDS || !FileData[FileId].FuncTable) 00441 return; 00442 FileData[FileId].Specific = Specific; 00443 } 00444 00445 VOID* FsGetDeviceSpecific(ULONG FileId) 00446 { 00447 if (FileId >= MAX_FDS || !FileData[FileId].FuncTable) 00448 return NULL; 00449 return FileData[FileId].Specific; 00450 } 00451 00452 ULONG FsGetDeviceId(ULONG FileId) 00453 { 00454 if (FileId >= MAX_FDS) 00455 return (ULONG)-1; 00456 return FileData[FileId].DeviceId; 00457 } 00458 00459 VOID FsInit(VOID) 00460 { 00461 ULONG i; 00462 00463 RtlZeroMemory(FileData, sizeof(FileData)); 00464 for (i = 0; i < MAX_FDS; i++) 00465 FileData[i].DeviceId = (ULONG)-1; 00466 00467 InitializeListHead(&DeviceListHead); 00468 } Generated on Sun May 27 2012 04:19:13 for ReactOS by
1.7.6.1
|