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