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

dfp.cxx
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:   See COPYING in the top level directory
00003  * PROJECT:     ReactOS cabinet manager
00004  * FILE:        tools/cabman/dfp.cpp
00005  * PURPOSE:     Directive file parser
00006  * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
00007  *              Colin Finck <mail@colinfinck.de>
00008  * NOTES:       The directive file format is similar to the
00009  *              directive file format used by Microsoft's MAKECAB
00010  * REVISIONS:
00011  *   CSH 21/03-2001 Created
00012  *   CSH 15/08-2003 Made it portable
00013  *   CF  04/05-2007 Made it compatible with 64-bit operating systems
00014  */
00015 #include <stdlib.h>
00016 #include <stdio.h>
00017 #include "cabinet.h"
00018 #include "dfp.h"
00019 
00020 
00021 #if defined(_WIN32)
00022 #define GetSizeOfFile(handle) _GetSizeOfFile(handle)
00023 static LONG _GetSizeOfFile(FILEHANDLE handle)
00024 {
00025     ULONG size = GetFileSize(handle, NULL);
00026     if (size == INVALID_FILE_SIZE)
00027         return -1;
00028 
00029     return size;
00030 }
00031 #define ReadFileData(handle, buffer, size, bytesread) _ReadFileData(handle, buffer, size, bytesread)
00032 static BOOL _ReadFileData(FILEHANDLE handle, void* buffer, ULONG size, PULONG bytesread)
00033 {
00034     return ReadFile(handle, buffer, size, (LPDWORD)bytesread, NULL);
00035 }
00036 #else
00037 #define GetSizeOfFile(handle) _GetSizeOfFile(handle)
00038 static LONG _GetSizeOfFile(FILEHANDLE handle)
00039 {
00040     LONG size;
00041     fseek(handle, 0, SEEK_END);
00042     size = ftell(handle);
00043     fseek(handle, 0, SEEK_SET);
00044     return size;
00045 }
00046 #define ReadFileData(handle, buffer, size, bytesread) _ReadFileData(handle, buffer, size, bytesread)
00047 static bool _ReadFileData(FILEHANDLE handle, void* buffer, ULONG size, PULONG bytesread)
00048 {
00049     *bytesread = fread(buffer, 1, size, handle);
00050     return *bytesread == size;
00051 }
00052 #endif
00053 
00054 /* CDFParser */
00055 
00056 CDFParser::CDFParser()
00057 /*
00058  * FUNCTION: Default constructor
00059  */
00060 {
00061     InfFileOnly     = false;
00062     DontGenerateInf = false;
00063 
00064     FileBuffer     = NULL;
00065     FileLoaded     = false;
00066     CurrentOffset  = 0;
00067     CurrentLine    = 0;
00068     CabinetCreated = false;
00069     DiskCreated    = false;
00070     FolderCreated  = false;
00071     CabinetName    = NULL;
00072     DiskLabel      = NULL;
00073     MaxDiskSize    = NULL;
00074 
00075     MaxDiskSizeAllSet      = false;
00076     CabinetNameTemplateSet = false;
00077     DiskLabelTemplateSet   = false;
00078     InfFileNameSet         = false;
00079 
00080     InfModeEnabled = false;
00081     InfFileHandle = NULL;
00082 
00083     strcpy(FileRelativePath, "");
00084 }
00085 
00086 CDFParser::~CDFParser()
00087 /*
00088  * FUNCTION: Default destructor
00089  */
00090 {
00091     PCABINET_NAME CNPrev;
00092     PCABINET_NAME CNNext;
00093     PDISK_NUMBER DNPrev;
00094     PDISK_NUMBER DNNext;
00095 
00096     if (FileBuffer)
00097         FreeMemory(FileBuffer);
00098     CNNext = CabinetName;
00099     while (CNNext != NULL)
00100     {
00101         CNPrev = CNNext->Next;
00102         FreeMemory(CNNext);
00103         CNNext = CNPrev;
00104     }
00105     CNNext = DiskLabel;
00106     while (CNNext != NULL)
00107     {
00108         CNPrev = CNNext->Next;
00109         FreeMemory(CNNext);
00110         CNNext = CNPrev;
00111     }
00112     DNNext = MaxDiskSize;
00113     while (DNNext != NULL)
00114     {
00115         DNPrev = DNNext->Next;
00116         FreeMemory(DNNext);
00117         DNNext = DNPrev;
00118     }
00119 
00120     if (InfFileHandle != NULL)
00121         CloseFile(InfFileHandle);
00122 }
00123 
00124 void CDFParser::WriteInfLine(char* InfLine)
00125 {
00126     char buf[PATH_MAX];
00127     char eolbuf[2];
00128     char* destpath;
00129 #if defined(_WIN32)
00130     ULONG BytesWritten;
00131 #endif
00132 
00133     if (DontGenerateInf)
00134         return;
00135 
00136     if (InfFileHandle == NULL)
00137     {
00138         if (!InfFileNameSet)
00139             /* FIXME: Use cabinet name with extension .inf */
00140             return;
00141 
00142         destpath = GetDestinationPath();
00143         if (strlen(destpath) > 0)
00144         {
00145             strcpy(buf, destpath);
00146             strcat(buf, InfFileName);
00147         }
00148         else
00149             strcpy(buf, InfFileName);
00150 
00151         /* Create .inf file, overwrite if it already exists */
00152 #if defined(_WIN32)
00153         InfFileHandle = CreateFile(buf,     // Create this file
00154             GENERIC_WRITE,                  // Open for writing
00155             0,                              // No sharing
00156             NULL,                           // No security
00157             CREATE_ALWAYS,                  // Create or overwrite
00158             FILE_ATTRIBUTE_NORMAL,          // Normal file
00159             NULL);                          // No attribute template
00160         if (InfFileHandle == INVALID_HANDLE_VALUE)
00161         {
00162             DPRINT(MID_TRACE, ("Error creating '%u'.\n", (UINT)GetLastError()));
00163             return;
00164         }
00165 #else /* !_WIN32 */
00166         InfFileHandle = fopen(buf, "wb");
00167         if (InfFileHandle == NULL)
00168         {
00169             DPRINT(MID_TRACE, ("Error creating '%i'.\n", errno));
00170             return;
00171         }
00172 #endif
00173     }
00174 
00175 #if defined(_WIN32)
00176     if (!WriteFile(InfFileHandle, InfLine, (DWORD)strlen(InfLine), (LPDWORD)&BytesWritten, NULL))
00177     {
00178         DPRINT(MID_TRACE, ("ERROR WRITING '%u'.\n", (UINT)GetLastError()));
00179         return;
00180     }
00181 #else
00182     if (fwrite(InfLine, strlen(InfLine), 1, InfFileHandle) < 1)
00183         return;
00184 #endif
00185 
00186     eolbuf[0] = 0x0d;
00187     eolbuf[1] = 0x0a;
00188 
00189 #if defined(_WIN32)
00190     if (!WriteFile(InfFileHandle, eolbuf, sizeof(eolbuf), (LPDWORD)&BytesWritten, NULL))
00191     {
00192         DPRINT(MID_TRACE, ("ERROR WRITING '%u'.\n", (UINT)GetLastError()));
00193         return;
00194     }
00195 #else
00196     if (fwrite(eolbuf, 1, sizeof(eolbuf), InfFileHandle) < 1)
00197         return;
00198 #endif
00199 }
00200 
00201 
00202 ULONG CDFParser::Load(char* FileName)
00203 /*
00204  * FUNCTION: Loads a directive file into memory
00205  * ARGUMENTS:
00206  *     FileName = Pointer to name of directive file
00207  * RETURNS:
00208  *     Status of operation
00209  */
00210 {
00211     ULONG BytesRead;
00212     LONG FileSize;
00213 
00214     if (FileLoaded)
00215         return CAB_STATUS_SUCCESS;
00216 
00217     /* Create cabinet file, overwrite if it already exists */
00218 #if defined(_WIN32)
00219     FileHandle = CreateFile(FileName, // Create this file
00220         GENERIC_READ,                 // Open for reading
00221         0,                            // No sharing
00222         NULL,                         // No security
00223         OPEN_EXISTING,                // Open the file
00224         FILE_ATTRIBUTE_NORMAL,        // Normal file
00225         NULL);                        // No attribute template
00226     if (FileHandle == INVALID_HANDLE_VALUE)
00227         return CAB_STATUS_CANNOT_OPEN;
00228 #else /* !_WIN32 */
00229     FileHandle = fopen(FileName, "rb");
00230     if (FileHandle == NULL)
00231         return CAB_STATUS_CANNOT_OPEN;
00232 #endif
00233 
00234     FileSize = GetSizeOfFile(FileHandle);
00235     if (FileSize == -1)
00236     {
00237         CloseFile(FileHandle);
00238         return CAB_STATUS_CANNOT_OPEN;
00239     }
00240 
00241     FileBufferSize = (ULONG)FileSize;
00242 
00243     FileBuffer = (char*)AllocateMemory(FileBufferSize);
00244     if (!FileBuffer)
00245     {
00246         CloseFile(FileHandle);
00247         return CAB_STATUS_NOMEMORY;
00248     }
00249 
00250     if (!ReadFileData(FileHandle, FileBuffer, FileBufferSize, &BytesRead))
00251     {
00252         CloseFile(FileHandle);
00253         FreeMemory(FileBuffer);
00254         FileBuffer = NULL;
00255         return CAB_STATUS_CANNOT_READ;
00256     }
00257 
00258     CloseFile(FileHandle);
00259 
00260     FileLoaded = true;
00261 
00262     DPRINT(MAX_TRACE, ("File (%u bytes)\n", (UINT)FileBufferSize));
00263 
00264     return CAB_STATUS_SUCCESS;
00265 }
00266 
00267 
00268 ULONG CDFParser::Parse()
00269 /*
00270  * FUNCTION: Parses a loaded directive file
00271  * RETURNS:
00272  *     Status of operation
00273  */
00274 {
00275     bool Command;
00276     ULONG Status;
00277 
00278     if (!FileLoaded)
00279         return CAB_STATUS_NOFILE;
00280 
00281     while (ReadLine())
00282     {
00283         Command = false;
00284 
00285         if (InfModeEnabled)
00286         {
00287             bool WriteLine = true;
00288             while (CurrentToken != TokenEnd)
00289             {
00290                 switch (CurrentToken)
00291                 {
00292                     case TokenIdentifier:
00293                         if (Command)
00294                         {
00295                             /* Command */
00296                             Status = PerformCommand();
00297                             if (Status == CAB_STATUS_FAILURE)
00298                                 WriteLine = true;
00299                             else
00300                                 if (!InfModeEnabled)
00301                                     WriteLine = false;
00302 
00303                             CurrentToken = TokenEnd;
00304                             continue;
00305                         }
00306                         else
00307                         {
00308                             WriteLine = true;
00309                             CurrentToken = TokenEnd;
00310                             continue;
00311                         }
00312                         break;
00313 
00314                     case TokenSpace:
00315                         break;
00316 
00317                     case TokenPeriod:
00318                         Command = true;
00319                         break;
00320 
00321                     default:
00322                         WriteLine = true;
00323                         CurrentToken = TokenEnd;
00324                         continue;
00325                 }
00326                 NextToken();
00327             }
00328             if (WriteLine)
00329                 WriteInfLine(Line);
00330         }
00331         else
00332         {
00333             while (CurrentToken != TokenEnd)
00334             {
00335                 switch (CurrentToken)
00336                 {
00337                     case TokenInteger:
00338                         sprintf(CurrentString, "%u", (UINT)CurrentInteger);
00339                     case TokenIdentifier:
00340                     case TokenString:
00341                         if (Command)
00342                         {
00343                             /* Command */
00344                             Status = PerformCommand();
00345 
00346                             if (Status == CAB_STATUS_FAILURE)
00347                             {
00348                                 printf("Directive file contains errors at line %u.\n", (UINT)CurrentLine);
00349                                 DPRINT(MID_TRACE, ("Error while executing command.\n"));
00350                             }
00351 
00352                             if (Status != CAB_STATUS_SUCCESS)
00353                                 return Status;
00354                         }
00355                         else
00356                         {
00357                             /* File copy */
00358                             Status = PerformFileCopy();
00359 
00360                             if (Status != CAB_STATUS_SUCCESS)
00361                             {
00362                                 printf("Directive file contains errors at line %u.\n", (UINT)CurrentLine);
00363                                 DPRINT(MID_TRACE, ("Error while copying file.\n"));
00364                             }
00365 
00366                             if (Status != CAB_STATUS_SUCCESS)
00367                                 return Status;
00368                         }
00369                         break;
00370 
00371                     case TokenSpace:
00372                         break;
00373 
00374                     case TokenSemi:
00375                         CurrentToken = TokenEnd;
00376                         continue;
00377 
00378                     case TokenPeriod:
00379                         Command = true;
00380                         break;
00381 
00382                     default:
00383                         printf("Directive file contains errors at line %u.\n", (UINT)CurrentLine);
00384                         DPRINT(MID_TRACE, ("Token is (%u).\n", (UINT)CurrentToken));
00385                         return CAB_STATUS_SUCCESS;
00386                     }
00387                     NextToken();
00388             }
00389         }
00390     }
00391 
00392     if (!InfFileOnly)
00393     {
00394         printf("\nWriting cabinet. This may take a while...\n\n");
00395 
00396         if (DiskCreated)
00397         {
00398             Status = WriteDisk(false);
00399             if (Status == CAB_STATUS_SUCCESS)
00400                 Status = CloseDisk();
00401             if (Status != CAB_STATUS_SUCCESS)
00402             {
00403                 DPRINT(MIN_TRACE, ("Cannot write disk (%u).\n", (UINT)Status));
00404                 return Status;
00405             }
00406         }
00407 
00408         if (CabinetCreated)
00409         {
00410             Status = CloseCabinet();
00411             if (Status != CAB_STATUS_SUCCESS)
00412             {
00413                 DPRINT(MIN_TRACE, ("Cannot close cabinet (%u).\n", (UINT)Status));
00414                 return Status;
00415             }
00416         }
00417 
00418         printf("\nDone.\n");
00419     }
00420 
00421     return CAB_STATUS_SUCCESS;
00422 }
00423 
00424 
00425 void CDFParser::SetFileRelativePath(char* Path)
00426 /*
00427  * FUNCTION: Sets path where files in the .dff is assumed relative to
00428  * ARGUMENTS:
00429  *    Path = Pointer to string with path
00430  */
00431 {
00432     strcpy(FileRelativePath, Path);
00433     ConvertPath(FileRelativePath, false);
00434     if (strlen(FileRelativePath) > 0)
00435         NormalizePath(FileRelativePath, PATH_MAX);
00436 }
00437 
00438 
00439 bool CDFParser::OnDiskLabel(ULONG Number, char* Label)
00440 /*
00441  * FUNCTION: Called when a disk needs a label
00442  * ARGUMENTS:
00443  *     Number = Cabinet number that needs a label
00444  *     Label  = Pointer to buffer to place label of disk
00445  * RETURNS:
00446  *     true if a disk label was returned, false if not
00447  */
00448 {
00449     char Buffer[20];
00450     ULONG i;
00451     int j;
00452     char ch;
00453 
00454     Number += 1;
00455 
00456     DPRINT(MID_TRACE, ("Giving disk (%u) a label...\n", (UINT)Number));
00457 
00458     if (GetDiskName(&DiskLabel, Number, Label))
00459         return true;
00460 
00461     if (DiskLabelTemplateSet)
00462     {
00463         j = 0;
00464         strcpy(Label, "");
00465         for (i = 0; i < strlen(DiskLabelTemplate); i++)
00466         {
00467             ch = DiskLabelTemplate[i];
00468             if (ch == '*')
00469             {
00470                 sprintf(Buffer, "%u", (UINT)Number);
00471                 strcat(Label, Buffer);
00472                 j += (LONG)strlen(Buffer);
00473             }
00474             else
00475             {
00476                 Label[j] = ch;
00477                 j++;
00478             }
00479             Label[j] = '\0';
00480         }
00481 
00482         DPRINT(MID_TRACE, ("Giving disk (%s) as a label...\n", Label));
00483 
00484         return true;
00485     }
00486     else
00487         return false;
00488 }
00489 
00490 
00491 bool CDFParser::OnCabinetName(ULONG Number, char* Name)
00492 /*
00493  * FUNCTION: Called when a cabinet needs a name
00494  * ARGUMENTS:
00495  *     Number = Disk number that needs a name
00496  *     Name   = Pointer to buffer to place name of cabinet
00497  * RETURNS:
00498  *     true if a cabinet name was returned, false if not
00499  */
00500 {
00501     char Buffer[PATH_MAX];
00502     ULONG i;
00503     int j;
00504     char ch;
00505 
00506     Number += 1;
00507 
00508     DPRINT(MID_TRACE, ("Giving cabinet (%u) a name...\n", (UINT)Number));
00509 
00510     if (GetDiskName(&CabinetName, Number, Buffer))
00511     {
00512         strcpy(Name, GetDestinationPath());
00513         strcat(Name, Buffer);
00514         return true;
00515     }
00516 
00517     if (CabinetNameTemplateSet)
00518     {
00519         strcpy(Name, GetDestinationPath());
00520         j = (LONG)strlen(Name);
00521         for (i = 0; i < strlen(CabinetNameTemplate); i++)
00522         {
00523             ch = CabinetNameTemplate[i];
00524             if (ch == '*')
00525             {
00526                 sprintf(Buffer, "%u", (UINT)Number);
00527                 strcat(Name, Buffer);
00528                 j += (LONG)strlen(Buffer);
00529             }
00530             else
00531             {
00532                 Name[j] = ch;
00533                 j++;
00534             }
00535             Name[j] = '\0';
00536         }
00537 
00538         DPRINT(MID_TRACE, ("Giving cabinet (%s) as a name...\n", Name));
00539         return true;
00540     }
00541     else
00542         return false;
00543 }
00544 
00545 
00546 bool CDFParser::SetDiskName(PCABINET_NAME *List, ULONG Number, char* String)
00547 /*
00548  * FUNCTION: Sets an entry in a list
00549  * ARGUMENTS:
00550  *     List   = Address of pointer to list
00551  *     Number = Disk number
00552  *     String = Pointer to string
00553  * RETURNS:
00554  *     false if there was not enough free memory available
00555  */
00556 {
00557     PCABINET_NAME CN;
00558 
00559     CN = *List;
00560     while (CN != NULL)
00561     {
00562         if (CN->DiskNumber == Number)
00563         {
00564             strcpy(CN->Name, String);
00565             return true;
00566         }
00567         CN = CN->Next;
00568     }
00569 
00570     CN = (PCABINET_NAME)AllocateMemory(sizeof(CABINET_NAME));
00571     if (!CN)
00572         return false;
00573 
00574     CN->DiskNumber = Number;
00575     strcpy(CN->Name, String);
00576 
00577     CN->Next = *List;
00578     *List = CN;
00579 
00580     return true;
00581 }
00582 
00583 
00584 bool CDFParser::GetDiskName(PCABINET_NAME *List, ULONG Number, char* String)
00585 /*
00586  * FUNCTION: Returns an entry in a list
00587  * ARGUMENTS:
00588  *     List   = Address of pointer to list
00589  *     Number = Disk number
00590  *     String = Address of buffer to copy string to
00591  * RETURNS:
00592  *     false if there was not enough free memory available
00593  */
00594 {
00595     PCABINET_NAME CN;
00596 
00597     CN = *List;
00598     while (CN != NULL)
00599     {
00600         if (CN->DiskNumber == Number)
00601         {
00602             strcpy(String, CN->Name);
00603             return true;
00604         }
00605         CN = CN->Next;
00606     }
00607 
00608     return false;
00609 }
00610 
00611 
00612 bool CDFParser::SetDiskNumber(PDISK_NUMBER *List, ULONG Number, ULONG Value)
00613 /*
00614  * FUNCTION: Sets an entry in a list
00615  * ARGUMENTS:
00616  *     List   = Address of pointer to list
00617  *     Number = Disk number
00618  *     Value  = Value to set
00619  * RETURNS:
00620  *     false if there was not enough free memory available
00621  */
00622 {
00623     PDISK_NUMBER DN;
00624 
00625     DN = *List;
00626     while (DN != NULL)
00627     {
00628         if (DN->DiskNumber == Number)
00629         {
00630             DN->Number = Value;
00631             return true;
00632         }
00633         DN = DN->Next;
00634     }
00635 
00636     DN = (PDISK_NUMBER)AllocateMemory(sizeof(DISK_NUMBER));
00637     if (!DN)
00638         return false;
00639 
00640     DN->DiskNumber = Number;
00641     DN->Number = Value;
00642 
00643     DN->Next = *List;
00644     *List = DN;
00645 
00646     return true;
00647 }
00648 
00649 
00650 bool CDFParser::GetDiskNumber(PDISK_NUMBER *List, ULONG Number, PULONG Value)
00651 /*
00652  * FUNCTION: Returns an entry in a list
00653  * ARGUMENTS:
00654  *     List   = Address of pointer to list
00655  *     Number = Disk number
00656  *     Value  = Address of buffer to place value
00657  * RETURNS:
00658  *     true if the entry was found
00659  */
00660 {
00661     PDISK_NUMBER DN;
00662 
00663     DN = *List;
00664     while (DN != NULL)
00665     {
00666         if (DN->DiskNumber == Number)
00667         {
00668             *Value = DN->Number;
00669             return true;
00670         }
00671         DN = DN->Next;
00672     }
00673 
00674     return false;
00675 }
00676 
00677 
00678 bool CDFParser::DoDiskLabel(ULONG Number, char* Label)
00679 /*
00680  * FUNCTION: Sets the label of a disk
00681  * ARGUMENTS:
00682  *     Number = Disk number
00683  *     Label  = Pointer to label of disk
00684  * RETURNS:
00685  *     false if there was not enough free memory available
00686  */
00687 {
00688     DPRINT(MID_TRACE, ("Setting label of disk (%u) to '%s'\n", (UINT)Number, Label));
00689 
00690     return SetDiskName(&DiskLabel, Number, Label);
00691 }
00692 
00693 
00694 void CDFParser::DoDiskLabelTemplate(char* Template)
00695 /*
00696  * FUNCTION: Sets a disk label template to use
00697  * ARGUMENTS:
00698  *     Template = Pointer to disk label template
00699  */
00700 {
00701     DPRINT(MID_TRACE, ("Setting disk label template to '%s'\n", Template));
00702 
00703     strcpy(DiskLabelTemplate, Template);
00704     DiskLabelTemplateSet = true;
00705 }
00706 
00707 
00708 bool CDFParser::DoCabinetName(ULONG Number, char* Name)
00709 /*
00710  * FUNCTION: Sets the name of a cabinet
00711  * ARGUMENTS:
00712  *     Number = Disk number
00713  *     Name   = Pointer to name of cabinet
00714  * RETURNS:
00715  *     false if there was not enough free memory available
00716  */
00717 {
00718     DPRINT(MID_TRACE, ("Setting name of cabinet (%u) to '%s'\n", (UINT)Number, Name));
00719 
00720     return SetDiskName(&CabinetName, Number, Name);
00721 }
00722 
00723 
00724 void CDFParser::DoCabinetNameTemplate(char* Template)
00725 /*
00726  * FUNCTION: Sets a cabinet name template to use
00727  * ARGUMENTS:
00728  *     Template = Pointer to cabinet name template
00729  */
00730 {
00731     DPRINT(MID_TRACE, ("Setting cabinet name template to '%s'\n", Template));
00732 
00733     strcpy(CabinetNameTemplate, Template);
00734     CabinetNameTemplateSet = true;
00735 }
00736 
00737 
00738 ULONG CDFParser::DoMaxDiskSize(bool NumberValid, ULONG Number)
00739 /*
00740  * FUNCTION: Sets the maximum disk size
00741  * ARGUMENTS:
00742  *     NumberValid = true if disk number is valid
00743  *     Number      = Disk number
00744  * RETURNS:
00745  *     Status of operation
00746  * NOTES:
00747  *     Standard sizes are 2.88M, 1.44M, 1.25M, 1.2M, 720K, 360K, and CDROM
00748  */
00749 {
00750     ULONG A, B, Value;
00751 
00752     if (IsNextToken(TokenInteger, true))
00753     {
00754         A = CurrentInteger;
00755 
00756         if (IsNextToken(TokenPeriod, false))
00757         {
00758             if (!IsNextToken(TokenInteger, false))
00759                 return CAB_STATUS_FAILURE;
00760 
00761             B = CurrentInteger;
00762 
00763         }
00764         else
00765             B = 0;
00766 
00767         if (CurrentToken == TokenIdentifier)
00768         {
00769             switch (CurrentString[0])
00770             {
00771                 case 'K':
00772                     if (B != 0)
00773                         return CAB_STATUS_FAILURE;
00774 
00775                     if (A == 720)
00776                         /* 720K disk */
00777                         Value = 730112;
00778                     else if (A == 360)
00779                         /* 360K disk */
00780                         Value = 362496;
00781                     else
00782                         return CAB_STATUS_FAILURE;
00783                     break;
00784 
00785                 case 'M':
00786                     if (A == 1)
00787                     {
00788                         if (B == 44)
00789                             /* 1.44M disk */
00790                             Value = 1457664;
00791                         else if (B == 25)
00792                             /* 1.25M disk */
00793                             Value = 1300000; // FIXME: Value?
00794                         else if (B == 2)
00795                             /* 1.2M disk */
00796                             Value = 1213952;
00797                         else
00798                             return CAB_STATUS_FAILURE;
00799                     }
00800                     else if (A == 2)
00801                     {
00802                         if (B == 88)
00803                             /* 2.88M disk */
00804                             Value = 2915328;
00805                         else
00806                             return CAB_STATUS_FAILURE;
00807                     }
00808                     else
00809                         return CAB_STATUS_FAILURE;
00810                     break;
00811 
00812                 default:
00813                     DPRINT(MID_TRACE, ("Bad suffix (%c)\n", CurrentString[0]));
00814                     return CAB_STATUS_FAILURE;
00815             }
00816         }
00817         else
00818             Value = A;
00819     }
00820     else
00821     {
00822         if ((CurrentToken != TokenString) &&
00823             (strcasecmp(CurrentString, "CDROM") != 0))
00824             return CAB_STATUS_FAILURE;
00825         /* CDROM */
00826         Value = 640*1024*1024;  // FIXME: Correct size for CDROM?
00827     }
00828 
00829     if (NumberValid)
00830         return (SetDiskNumber(&MaxDiskSize, Number, Value)?
00831             CAB_STATUS_SUCCESS : CAB_STATUS_FAILURE);
00832 
00833     MaxDiskSizeAll    = Value;
00834     MaxDiskSizeAllSet = true;
00835 
00836     SetMaxDiskSize(Value);
00837 
00838     return CAB_STATUS_SUCCESS;
00839 }
00840 
00841 
00842 void CDFParser::DoInfFileName(char* FileName)
00843 /*
00844  * FUNCTION: Sets filename of the generated .inf file
00845  * ARGUMENTS:
00846  *     FileName = Pointer to .inf filename
00847  */
00848 {
00849     DPRINT(MID_TRACE, ("Setting .inf filename to '%s'\n", FileName));
00850 
00851     strcpy(InfFileName, FileName);
00852     InfFileNameSet = true;
00853 }
00854 
00855 ULONG CDFParser::SetupNewDisk()
00856 /*
00857  * FUNCTION: Sets up parameters for a new disk
00858  * RETURNS:
00859  *     Status of operation
00860  */
00861 {
00862     ULONG Value;
00863 
00864     if (!GetDiskNumber(&MaxDiskSize, GetCurrentDiskNumber(), &Value))
00865     {
00866         if (MaxDiskSizeAllSet)
00867             Value = MaxDiskSizeAll;
00868         else
00869             Value = 0;
00870     }
00871     SetMaxDiskSize(Value);
00872 
00873     return CAB_STATUS_SUCCESS;
00874 }
00875 
00876 
00877 ULONG CDFParser::PerformSetCommand()
00878 /*
00879  * FUNCTION: Performs a set variable command
00880  * RETURNS:
00881  *     Status of operation
00882  */
00883 {
00884     SETTYPE SetType;
00885     bool NumberValid = false;
00886     ULONG Number = 0;
00887 
00888     if (!IsNextToken(TokenIdentifier, true))
00889         return CAB_STATUS_FAILURE;
00890 
00891     if (strcasecmp(CurrentString, "DiskLabel") == 0)
00892         SetType = stDiskLabel;
00893     else if (strcasecmp(CurrentString, "DiskLabelTemplate") == 0)
00894         SetType = stDiskLabelTemplate;
00895     else if (strcasecmp(CurrentString, "CabinetName") == 0)
00896         SetType = stCabinetName;
00897     else if (strcasecmp(CurrentString, "CabinetNameTemplate") == 0)
00898         SetType = stCabinetNameTemplate;
00899     else if (strcasecmp(CurrentString, "MaxDiskSize") == 0)
00900         SetType = stMaxDiskSize;
00901     else if (strcasecmp(CurrentString, "InfFileName") == 0)
00902         SetType = stInfFileName;
00903     else
00904         return CAB_STATUS_FAILURE;
00905 
00906     if ((SetType == stDiskLabel) || (SetType == stCabinetName))
00907     {
00908         if (!IsNextToken(TokenInteger, false))
00909             return CAB_STATUS_FAILURE;
00910         Number = CurrentInteger;
00911 
00912         if (!IsNextToken(TokenEqual, true))
00913             return CAB_STATUS_FAILURE;
00914     }
00915     else if (SetType == stMaxDiskSize)
00916     {
00917         if (IsNextToken(TokenInteger, false))
00918         {
00919             NumberValid = true;
00920             Number = CurrentInteger;
00921         }
00922         else
00923         {
00924             NumberValid = false;
00925             while (CurrentToken == TokenSpace)
00926                 NextToken();
00927             if (CurrentToken != TokenEqual)
00928                 return CAB_STATUS_FAILURE;
00929         }
00930     }
00931     else if (!IsNextToken(TokenEqual, true))
00932             return CAB_STATUS_FAILURE;
00933 
00934     if (SetType != stMaxDiskSize)
00935     {
00936         if (!IsNextToken(TokenString, true))
00937             return CAB_STATUS_FAILURE;
00938     }
00939 
00940     switch (SetType)
00941     {
00942         case stDiskLabel:
00943             if (!DoDiskLabel(Number, CurrentString))
00944                 DPRINT(MIN_TRACE, ("Not enough available free memory.\n"));
00945             return CAB_STATUS_SUCCESS;
00946 
00947         case stCabinetName:
00948             if (!DoCabinetName(Number, CurrentString))
00949                 DPRINT(MIN_TRACE, ("Not enough available free memory.\n"));
00950             return CAB_STATUS_SUCCESS;
00951 
00952         case stDiskLabelTemplate:
00953             DoDiskLabelTemplate(CurrentString);
00954             return CAB_STATUS_SUCCESS;
00955 
00956         case stCabinetNameTemplate:
00957             DoCabinetNameTemplate(CurrentString);
00958             return CAB_STATUS_SUCCESS;
00959 
00960         case stMaxDiskSize:
00961             return DoMaxDiskSize(NumberValid, Number);
00962 
00963         case stInfFileName:
00964             DoInfFileName(CurrentString);
00965             return CAB_STATUS_SUCCESS;
00966 
00967         default:
00968             return CAB_STATUS_FAILURE;
00969     }
00970 }
00971 
00972 
00973 ULONG CDFParser::PerformNewCommand()
00974 /*
00975  * FUNCTION: Performs a new disk|cabinet|folder command
00976  * RETURNS:
00977  *     Status of operation
00978  */
00979 {
00980     NEWTYPE NewType;
00981     ULONG Status;
00982 
00983     if (!IsNextToken(TokenIdentifier, true))
00984         return CAB_STATUS_FAILURE;
00985 
00986     if (strcasecmp(CurrentString, "Disk") == 0)
00987         NewType = ntDisk;
00988     else if (strcasecmp(CurrentString, "Cabinet") == 0)
00989         NewType = ntCabinet;
00990     else if (strcasecmp(CurrentString, "Folder") == 0)
00991         NewType = ntFolder;
00992     else
00993         return CAB_STATUS_FAILURE;
00994 
00995     switch (NewType)
00996     {
00997         case ntDisk:
00998             if (DiskCreated)
00999             {
01000                 Status = WriteDisk(true);
01001                 if (Status == CAB_STATUS_SUCCESS)
01002                     Status = CloseDisk();
01003                 if (Status != CAB_STATUS_SUCCESS)
01004                 {
01005                     DPRINT(MIN_TRACE, ("Cannot write disk (%u).\n", (UINT)Status));
01006                     return CAB_STATUS_SUCCESS;
01007                 }
01008                 DiskCreated = false;
01009             }
01010 
01011             Status = NewDisk();
01012             if (Status != CAB_STATUS_SUCCESS)
01013             {
01014                 DPRINT(MIN_TRACE, ("Cannot create disk (%u).\n", (UINT)Status));
01015                 return CAB_STATUS_SUCCESS;
01016             }
01017             DiskCreated = true;
01018             SetupNewDisk();
01019             return CAB_STATUS_SUCCESS;
01020 
01021         case ntCabinet:
01022             if (DiskCreated)
01023             {
01024                 Status = WriteDisk(true);
01025                 if (Status == CAB_STATUS_SUCCESS)
01026                     Status = CloseDisk();
01027                 if (Status != CAB_STATUS_SUCCESS)
01028                 {
01029                     DPRINT(MIN_TRACE, ("Cannot write disk (%u).\n", (UINT)Status));
01030                     return CAB_STATUS_SUCCESS;
01031                 }
01032                 DiskCreated = false;
01033             }
01034 
01035             Status = NewCabinet();
01036             if (Status != CAB_STATUS_SUCCESS)
01037             {
01038                 DPRINT(MIN_TRACE, ("Cannot create cabinet (%u).\n", (UINT)Status));
01039                 return CAB_STATUS_SUCCESS;
01040             }
01041             DiskCreated = true;
01042             SetupNewDisk();
01043             return CAB_STATUS_SUCCESS;
01044 
01045         case ntFolder:
01046             Status = NewFolder();
01047             ASSERT(Status == CAB_STATUS_SUCCESS);
01048             return CAB_STATUS_SUCCESS;
01049 
01050         default:
01051             return CAB_STATUS_FAILURE;
01052     }
01053 }
01054 
01055 
01056 ULONG CDFParser::PerformInfBeginCommand()
01057 /*
01058  * FUNCTION: Begins inf mode
01059  * RETURNS:
01060  *     Status of operation
01061  */
01062 {
01063     InfModeEnabled = true;
01064     return CAB_STATUS_SUCCESS;
01065 }
01066 
01067 
01068 ULONG CDFParser::PerformInfEndCommand()
01069 /*
01070  * FUNCTION: Begins inf mode
01071  * RETURNS:
01072  *     Status of operation
01073  */
01074 {
01075     InfModeEnabled = false;
01076     return CAB_STATUS_SUCCESS;
01077 }
01078 
01079 
01080 ULONG CDFParser::PerformCommand()
01081 /*
01082  * FUNCTION: Performs a command
01083  * RETURNS:
01084  *     Status of operation
01085  */
01086 {
01087     if (strcasecmp(CurrentString, "Set") == 0)
01088         return PerformSetCommand();
01089     if (strcasecmp(CurrentString, "New") == 0)
01090         return PerformNewCommand();
01091     if (strcasecmp(CurrentString, "InfBegin") == 0)
01092         return PerformInfBeginCommand();
01093     if (strcasecmp(CurrentString, "InfEnd") == 0)
01094         return PerformInfEndCommand();
01095 
01096     return CAB_STATUS_FAILURE;
01097 }
01098 
01099 
01100 ULONG CDFParser::PerformFileCopy()
01101 /*
01102  * FUNCTION: Performs a file copy
01103  * RETURNS:
01104  *     Status of operation
01105  */
01106 {
01107     ULONG Status;
01108     ULONG i, j;
01109     char ch;
01110     char SrcName[PATH_MAX];
01111     char DstName[PATH_MAX];
01112     char InfLine[PATH_MAX];
01113     char Options[128];
01114     char BaseFilename[PATH_MAX];
01115 
01116     *SrcName = '\0';
01117     *DstName = '\0';
01118     *Options = '\0';
01119 
01120     // source file
01121     i = CurrentChar;
01122     while ((i < LineLength) &&
01123         ((ch = Line[i]) != ' ') &&
01124          (ch != 0x09) &&
01125          (ch != ';'))
01126     {
01127         CurrentString[i] = ch;
01128         i++;
01129     }
01130     CurrentString[i] = '\0';
01131     CurrentToken = TokenString;
01132     CurrentChar  = i + 1;
01133     strcpy(BaseFilename, CurrentString);
01134     strcat(SrcName, BaseFilename);
01135 
01136     // destination
01137     SkipSpaces();
01138 
01139     if (CurrentToken != TokenEnd)
01140     {
01141         j = (ULONG)strlen(CurrentString); i = 0;
01142         while ((CurrentChar + i < LineLength) &&
01143             ((ch = Line[CurrentChar + i]) != ' ') &&
01144              (ch != 0x09) &&
01145              (ch != ';'))
01146         {
01147             CurrentString[j + i] = ch;
01148             i++;
01149         }
01150         CurrentString[j + i] = '\0';
01151         CurrentToken = TokenString;
01152         CurrentChar += i + 1;
01153         strcpy(DstName, CurrentString);
01154     }
01155 
01156     // options (it may be empty)
01157     SkipSpaces ();
01158 
01159     if (CurrentToken != TokenEnd)
01160     {
01161         j = (ULONG)strlen(CurrentString); i = 0;
01162         while ((CurrentChar + i < LineLength) &&
01163             ((ch = Line[CurrentChar + i]) != ' ') &&
01164              (ch != 0x09) &&
01165              (ch != ';'))
01166         {
01167             CurrentString[j + i] = ch;
01168             i++;
01169         }
01170         CurrentString[j + i] = '\0';
01171         CurrentToken = TokenString;
01172         CurrentChar += i + 1;
01173         strcpy(Options, CurrentString);
01174     }
01175 
01176     if (!CabinetCreated)
01177     {
01178         DPRINT(MID_TRACE, ("Creating cabinet.\n"));
01179 
01180         Status = NewCabinet();
01181         if (Status != CAB_STATUS_SUCCESS)
01182         {
01183             DPRINT(MIN_TRACE, ("Cannot create cabinet (%u).\n", (UINT)Status));
01184             printf("Cannot create cabinet.\n");
01185             return CAB_STATUS_FAILURE;
01186         }
01187         CabinetCreated = true;
01188 
01189         DPRINT(MID_TRACE, ("Creating disk.\n"));
01190 
01191         Status = NewDisk();
01192         if (Status != CAB_STATUS_SUCCESS)
01193         {
01194             DPRINT(MIN_TRACE, ("Cannot create disk (%u).\n", (UINT)Status));
01195             printf("Cannot create disk.\n");
01196             return CAB_STATUS_FAILURE;
01197         }
01198         DiskCreated = true;
01199         SetupNewDisk();
01200     }
01201 
01202     DPRINT(MID_TRACE, ("Adding file: '%s'   destination: '%s'.\n", SrcName, DstName));
01203 
01204     Status = AddFile(SrcName);
01205     if (Status == CAB_STATUS_CANNOT_OPEN)
01206     {
01207         strcpy(SrcName, FileRelativePath);
01208         strcat(SrcName, BaseFilename);
01209         Status = AddFile(SrcName);
01210     }
01211     switch (Status)
01212     {
01213         case CAB_STATUS_SUCCESS:
01214             sprintf(InfLine, "%s=%s", GetFileName(SrcName), DstName);
01215             WriteInfLine(InfLine);
01216             break;
01217 
01218         case CAB_STATUS_CANNOT_OPEN:
01219             if (strstr(Options,"optional"))
01220             {
01221                 Status = CAB_STATUS_SUCCESS;
01222                 printf("Optional file does not exist: %s.\n", SrcName);
01223             }
01224             else
01225                 printf("File does not exist: %s.\n", SrcName);
01226 
01227             break;
01228 
01229         case CAB_STATUS_NOMEMORY:
01230             printf("Insufficient memory to add file: %s.\n", SrcName);
01231             break;
01232 
01233         default:
01234             printf("Cannot add file: %s (%u).\n", SrcName, (UINT)Status);
01235             break;
01236     }
01237     return Status;
01238 }
01239 
01240 
01241 void CDFParser::SkipSpaces()
01242 /*
01243  * FUNCTION: Skips any spaces in the current line
01244  */
01245 {
01246     NextToken();
01247     while (CurrentToken == TokenSpace)
01248         NextToken();
01249 }
01250 
01251 
01252 bool CDFParser::IsNextToken(DFP_TOKEN Token, bool NoSpaces)
01253 /*
01254  * FUNCTION: Checks if next token equals Token
01255  * ARGUMENTS:
01256  *     Token  = Token to compare with
01257  *     SkipSp = true if spaces should be skipped
01258  * RETURNS:
01259  *     false if next token is diffrent from Token
01260  */
01261 {
01262     if (NoSpaces)
01263         SkipSpaces();
01264     else
01265         NextToken();
01266     return (CurrentToken == Token);
01267 }
01268 
01269 
01270 bool CDFParser::ReadLine()
01271 /*
01272  * FUNCTION: Reads the next line into the line buffer
01273  * RETURNS:
01274  *     true if there is a new line, false if not
01275  */
01276 {
01277     ULONG i, j;
01278     char ch;
01279 
01280     if (CurrentOffset >= FileBufferSize)
01281         return false;
01282 
01283     i = 0;
01284     while (((j = CurrentOffset + i) < FileBufferSize) && (i < sizeof(Line) - 1) &&
01285         ((ch = FileBuffer[j]) != 0x0D && (ch = FileBuffer[j]) != 0x0A))
01286     {
01287         Line[i] = ch;
01288         i++;
01289     }
01290 
01291     Line[i]    = '\0';
01292     LineLength = i;
01293 
01294     if ((FileBuffer[CurrentOffset + i] == 0x0D) && (FileBuffer[CurrentOffset + i + 1] == 0x0A))
01295         CurrentOffset++;
01296 
01297     CurrentOffset += i + 1;
01298 
01299     CurrentChar = 0;
01300 
01301     CurrentLine++;
01302 
01303     NextToken();
01304 
01305     return true;
01306 }
01307 
01308 
01309 void CDFParser::NextToken()
01310 /*
01311  * FUNCTION: Reads the next token from the current line
01312  */
01313 {
01314     ULONG i;
01315     char ch = ' ';
01316 
01317     if (CurrentChar >= LineLength)
01318     {
01319         CurrentToken = TokenEnd;
01320         return;
01321     }
01322 
01323     switch (Line[CurrentChar])
01324     {
01325         case ' ':
01326         case 0x09:
01327             CurrentToken = TokenSpace;
01328             break;
01329 
01330         case ';':
01331             CurrentToken = TokenSemi;
01332             break;
01333 
01334         case '=':
01335             CurrentToken = TokenEqual;
01336             break;
01337 
01338         case '.':
01339             CurrentToken = TokenPeriod;
01340             break;
01341 
01342         case '\\':
01343             CurrentToken = TokenBackslash;
01344             break;
01345 
01346         case '"':
01347             i = 0;
01348             while ((CurrentChar + i + 1 < LineLength) &&
01349                 ((ch = Line[CurrentChar + i + 1]) != '"'))
01350             {
01351                 CurrentString[i] = ch;
01352                 i++;
01353             }
01354             CurrentString[i] = '\0';
01355             CurrentToken = TokenString;
01356             CurrentChar += i + 2;
01357             return;
01358 
01359         default:
01360             i = 0;
01361             while ((CurrentChar + i < LineLength) &&
01362                 ((ch = Line[CurrentChar + i]) >= '0') && (ch <= '9'))
01363             {
01364                 CurrentString[i] = ch;
01365                 i++;
01366             }
01367             if (i > 0)
01368             {
01369                 CurrentString[i] = '\0';
01370                 CurrentInteger = atoi(CurrentString);
01371                 CurrentToken = TokenInteger;
01372                 CurrentChar += i;
01373                 return;
01374             }
01375             i = 0;
01376             while (((CurrentChar + i < LineLength) &&
01377                 (((ch = Line[CurrentChar + i]) >= 'a') && (ch <= 'z'))) ||
01378                 ((ch >= 'A') && (ch <= 'Z')) || (ch == '_'))
01379             {
01380                 CurrentString[i] = ch;
01381                 i++;
01382             }
01383             if (i > 0)
01384             {
01385                 CurrentString[i] = '\0';
01386                 CurrentToken = TokenIdentifier;
01387                 CurrentChar += i;
01388                 return;
01389             }
01390             CurrentToken = TokenEnd;
01391     }
01392     CurrentChar++;
01393 }
01394 
01395 /* EOF */

Generated on Fri May 25 2012 04:36:08 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.