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

fs.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 doxygen 1.7.6.1

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