2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS cabinet manager
4 * FILE: tools/cabman/dfp.cxx
5 * PURPOSE: Directive file parser
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Colin Finck <mail@colinfinck.de>
8 * NOTES: The directive file format is similar to the
9 * directive file format used by Microsoft's MAKECAB
11 * CSH 21/03-2001 Created
12 * CSH 15/08-2003 Made it portable
13 * CF 04/05-2007 Made it compatible with 64-bit operating systems
22 #define GetSizeOfFile(handle) _GetSizeOfFile(handle)
23 static LONG
_GetSizeOfFile(FILEHANDLE handle
)
25 ULONG size
= GetFileSize(handle
, NULL
);
26 if (size
== INVALID_FILE_SIZE
)
31 #define ReadFileData(handle, buffer, size, bytesread) _ReadFileData(handle, buffer, size, bytesread)
32 static BOOL
_ReadFileData(FILEHANDLE handle
, void* buffer
, ULONG size
, PULONG bytesread
)
34 return ReadFile(handle
, buffer
, size
, (LPDWORD
)bytesread
, NULL
);
37 #define GetSizeOfFile(handle) _GetSizeOfFile(handle)
38 static LONG
_GetSizeOfFile(FILEHANDLE handle
)
41 fseek(handle
, 0, SEEK_END
);
43 fseek(handle
, 0, SEEK_SET
);
46 #define ReadFileData(handle, buffer, size, bytesread) _ReadFileData(handle, buffer, size, bytesread)
47 static bool _ReadFileData(FILEHANDLE handle
, void* buffer
, ULONG size
, PULONG bytesread
)
49 *bytesread
= fread(buffer
, 1, size
, handle
);
50 return *bytesread
== size
;
56 CDFParser::CDFParser()
58 * FUNCTION: Default constructor
62 DontGenerateInf
= false;
68 CabinetCreated
= false;
70 FolderCreated
= false;
75 MaxDiskSizeAllSet
= false;
76 CabinetNameTemplateSet
= false;
77 DiskLabelTemplateSet
= false;
78 InfFileNameSet
= false;
80 InfModeEnabled
= false;
83 strcpy(FileRelativePath
, "");
86 CDFParser::~CDFParser()
88 * FUNCTION: Default destructor
97 FreeMemory(FileBuffer
);
99 while (CNNext
!= NULL
)
101 CNPrev
= CNNext
->Next
;
106 while (CNNext
!= NULL
)
108 CNPrev
= CNNext
->Next
;
112 DNNext
= MaxDiskSize
;
113 while (DNNext
!= NULL
)
115 DNPrev
= DNNext
->Next
;
120 if (InfFileHandle
!= NULL
)
121 CloseFile(InfFileHandle
);
124 void CDFParser::WriteInfLine(char* InfLine
)
136 if (InfFileHandle
== NULL
)
139 /* FIXME: Use cabinet name with extension .inf */
142 destpath
= GetDestinationPath();
143 if (strlen(destpath
) > 0)
145 strcpy(buf
, destpath
);
146 strcat(buf
, InfFileName
);
149 strcpy(buf
, InfFileName
);
151 /* Create .inf file, overwrite if it already exists */
153 InfFileHandle
= CreateFile(buf
, // Create this file
154 GENERIC_WRITE
, // Open for writing
157 CREATE_ALWAYS
, // Create or overwrite
158 FILE_ATTRIBUTE_NORMAL
, // Normal file
159 NULL
); // No attribute template
160 if (InfFileHandle
== INVALID_HANDLE_VALUE
)
162 DPRINT(MID_TRACE
, ("Error creating '%u'.\n", (UINT
)GetLastError()));
166 InfFileHandle
= fopen(buf
, "wb");
167 if (InfFileHandle
== NULL
)
169 DPRINT(MID_TRACE
, ("Error creating '%i'.\n", errno
));
176 if (!WriteFile(InfFileHandle
, InfLine
, (DWORD
)strlen(InfLine
), (LPDWORD
)&BytesWritten
, NULL
))
178 DPRINT(MID_TRACE
, ("ERROR WRITING '%u'.\n", (UINT
)GetLastError()));
182 if (fwrite(InfLine
, strlen(InfLine
), 1, InfFileHandle
) < 1)
190 if (!WriteFile(InfFileHandle
, eolbuf
, sizeof(eolbuf
), (LPDWORD
)&BytesWritten
, NULL
))
192 DPRINT(MID_TRACE
, ("ERROR WRITING '%u'.\n", (UINT
)GetLastError()));
196 if (fwrite(eolbuf
, 1, sizeof(eolbuf
), InfFileHandle
) < 1)
202 ULONG
CDFParser::Load(char* FileName
)
204 * FUNCTION: Loads a directive file into memory
206 * FileName = Pointer to name of directive file
208 * Status of operation
215 return CAB_STATUS_SUCCESS
;
217 /* Create cabinet file, overwrite if it already exists */
219 FileHandle
= CreateFile(FileName
, // Create this file
220 GENERIC_READ
, // Open for reading
223 OPEN_EXISTING
, // Open the file
224 FILE_ATTRIBUTE_NORMAL
, // Normal file
225 NULL
); // No attribute template
226 if (FileHandle
== INVALID_HANDLE_VALUE
)
227 return CAB_STATUS_CANNOT_OPEN
;
229 FileHandle
= fopen(FileName
, "rb");
230 if (FileHandle
== NULL
)
231 return CAB_STATUS_CANNOT_OPEN
;
234 FileSize
= GetSizeOfFile(FileHandle
);
237 CloseFile(FileHandle
);
238 return CAB_STATUS_CANNOT_OPEN
;
241 FileBufferSize
= (ULONG
)FileSize
;
243 FileBuffer
= (char*)AllocateMemory(FileBufferSize
);
246 CloseFile(FileHandle
);
247 return CAB_STATUS_NOMEMORY
;
250 if (!ReadFileData(FileHandle
, FileBuffer
, FileBufferSize
, &BytesRead
))
252 CloseFile(FileHandle
);
253 FreeMemory(FileBuffer
);
255 return CAB_STATUS_CANNOT_READ
;
258 CloseFile(FileHandle
);
262 DPRINT(MAX_TRACE
, ("File (%u bytes)\n", (UINT
)FileBufferSize
));
264 return CAB_STATUS_SUCCESS
;
268 ULONG
CDFParser::Parse()
270 * FUNCTION: Parses a loaded directive file
272 * Status of operation
279 return CAB_STATUS_NOFILE
;
287 bool WriteLine
= true;
288 while (CurrentToken
!= TokenEnd
)
290 switch (CurrentToken
)
292 case TokenIdentifier
:
296 Status
= PerformCommand();
297 if (Status
== CAB_STATUS_FAILURE
)
303 CurrentToken
= TokenEnd
;
309 CurrentToken
= TokenEnd
;
323 CurrentToken
= TokenEnd
;
333 while (CurrentToken
!= TokenEnd
)
335 switch (CurrentToken
)
338 sprintf(CurrentString
, "%u", (UINT
)CurrentInteger
);
339 case TokenIdentifier
:
344 Status
= PerformCommand();
346 if (Status
== CAB_STATUS_FAILURE
)
348 printf("ERROR: Directive file contains errors at line %u.\n", (UINT
)CurrentLine
);
349 DPRINT(MID_TRACE
, ("Error while executing command.\n"));
352 if (Status
!= CAB_STATUS_SUCCESS
)
358 Status
= PerformFileCopy();
360 if (Status
!= CAB_STATUS_SUCCESS
)
362 printf("ERROR: Directive file contains errors at line %u.\n", (UINT
)CurrentLine
);
363 DPRINT(MID_TRACE
, ("Error while copying file.\n"));
373 CurrentToken
= TokenEnd
;
381 printf("ERROR: Directive file contains errors at line %u.\n", (UINT
)CurrentLine
);
382 DPRINT(MID_TRACE
, ("Token is (%u).\n", (UINT
)CurrentToken
));
383 return CAB_STATUS_SUCCESS
;
392 if (CABMgr
.IsVerbose())
394 printf("Writing cabinet. This may take a while...\n");
399 Status
= WriteDisk(false);
400 if (Status
== CAB_STATUS_SUCCESS
)
401 Status
= CloseDisk();
402 if (Status
!= CAB_STATUS_SUCCESS
)
404 DPRINT(MIN_TRACE
, ("Cannot write disk (%u).\n", (UINT
)Status
));
411 Status
= CloseCabinet();
412 if (Status
!= CAB_STATUS_SUCCESS
)
414 DPRINT(MIN_TRACE
, ("Cannot close cabinet (%u).\n", (UINT
)Status
));
419 if (CABMgr
.IsVerbose())
425 return CAB_STATUS_SUCCESS
;
429 void CDFParser::SetFileRelativePath(char* Path
)
431 * FUNCTION: Sets path where files in the .dff is assumed relative to
433 * Path = Pointer to string with path
436 strcpy(FileRelativePath
, Path
);
437 ConvertPath(FileRelativePath
, false);
438 if (strlen(FileRelativePath
) > 0)
439 NormalizePath(FileRelativePath
, PATH_MAX
);
443 bool CDFParser::OnDiskLabel(ULONG Number
, char* Label
)
445 * FUNCTION: Called when a disk needs a label
447 * Number = Cabinet number that needs a label
448 * Label = Pointer to buffer to place label of disk
450 * true if a disk label was returned, false if not
460 DPRINT(MID_TRACE
, ("Giving disk (%u) a label...\n", (UINT
)Number
));
462 if (GetDiskName(&DiskLabel
, Number
, Label
))
465 if (DiskLabelTemplateSet
)
469 for (i
= 0; i
< strlen(DiskLabelTemplate
); i
++)
471 ch
= DiskLabelTemplate
[i
];
474 sprintf(Buffer
, "%u", (UINT
)Number
);
475 strcat(Label
, Buffer
);
476 j
+= (LONG
)strlen(Buffer
);
486 DPRINT(MID_TRACE
, ("Giving disk (%s) as a label...\n", Label
));
495 bool CDFParser::OnCabinetName(ULONG Number
, char* Name
)
497 * FUNCTION: Called when a cabinet needs a name
499 * Number = Disk number that needs a name
500 * Name = Pointer to buffer to place name of cabinet
502 * true if a cabinet name was returned, false if not
505 char Buffer
[PATH_MAX
];
512 DPRINT(MID_TRACE
, ("Giving cabinet (%u) a name...\n", (UINT
)Number
));
514 if (GetDiskName(&CabinetName
, Number
, Buffer
))
516 strcpy(Name
, GetDestinationPath());
517 strcat(Name
, Buffer
);
521 if (CabinetNameTemplateSet
)
523 strcpy(Name
, GetDestinationPath());
524 j
= (LONG
)strlen(Name
);
525 for (i
= 0; i
< strlen(CabinetNameTemplate
); i
++)
527 ch
= CabinetNameTemplate
[i
];
530 sprintf(Buffer
, "%u", (UINT
)Number
);
531 strcat(Name
, Buffer
);
532 j
+= (LONG
)strlen(Buffer
);
542 DPRINT(MID_TRACE
, ("Giving cabinet (%s) as a name...\n", Name
));
550 bool CDFParser::SetDiskName(PCABINET_NAME
*List
, ULONG Number
, char* String
)
552 * FUNCTION: Sets an entry in a list
554 * List = Address of pointer to list
555 * Number = Disk number
556 * String = Pointer to string
558 * false if there was not enough free memory available
566 if (CN
->DiskNumber
== Number
)
568 strcpy(CN
->Name
, String
);
574 CN
= (PCABINET_NAME
)AllocateMemory(sizeof(CABINET_NAME
));
578 CN
->DiskNumber
= Number
;
579 strcpy(CN
->Name
, String
);
588 bool CDFParser::GetDiskName(PCABINET_NAME
*List
, ULONG Number
, char* String
)
590 * FUNCTION: Returns an entry in a list
592 * List = Address of pointer to list
593 * Number = Disk number
594 * String = Address of buffer to copy string to
596 * false if there was not enough free memory available
604 if (CN
->DiskNumber
== Number
)
606 strcpy(String
, CN
->Name
);
616 bool CDFParser::SetDiskNumber(PDISK_NUMBER
*List
, ULONG Number
, ULONG Value
)
618 * FUNCTION: Sets an entry in a list
620 * List = Address of pointer to list
621 * Number = Disk number
622 * Value = Value to set
624 * false if there was not enough free memory available
632 if (DN
->DiskNumber
== Number
)
640 DN
= (PDISK_NUMBER
)AllocateMemory(sizeof(DISK_NUMBER
));
644 DN
->DiskNumber
= Number
;
654 bool CDFParser::GetDiskNumber(PDISK_NUMBER
*List
, ULONG Number
, PULONG Value
)
656 * FUNCTION: Returns an entry in a list
658 * List = Address of pointer to list
659 * Number = Disk number
660 * Value = Address of buffer to place value
662 * true if the entry was found
670 if (DN
->DiskNumber
== Number
)
682 bool CDFParser::DoDiskLabel(ULONG Number
, char* Label
)
684 * FUNCTION: Sets the label of a disk
686 * Number = Disk number
687 * Label = Pointer to label of disk
689 * false if there was not enough free memory available
692 DPRINT(MID_TRACE
, ("Setting label of disk (%u) to '%s'\n", (UINT
)Number
, Label
));
694 return SetDiskName(&DiskLabel
, Number
, Label
);
698 void CDFParser::DoDiskLabelTemplate(char* Template
)
700 * FUNCTION: Sets a disk label template to use
702 * Template = Pointer to disk label template
705 DPRINT(MID_TRACE
, ("Setting disk label template to '%s'\n", Template
));
707 strcpy(DiskLabelTemplate
, Template
);
708 DiskLabelTemplateSet
= true;
712 bool CDFParser::DoCabinetName(ULONG Number
, char* Name
)
714 * FUNCTION: Sets the name of a cabinet
716 * Number = Disk number
717 * Name = Pointer to name of cabinet
719 * false if there was not enough free memory available
722 DPRINT(MID_TRACE
, ("Setting name of cabinet (%u) to '%s'\n", (UINT
)Number
, Name
));
724 return SetDiskName(&CabinetName
, Number
, Name
);
728 void CDFParser::DoCabinetNameTemplate(char* Template
)
730 * FUNCTION: Sets a cabinet name template to use
732 * Template = Pointer to cabinet name template
735 DPRINT(MID_TRACE
, ("Setting cabinet name template to '%s'\n", Template
));
737 strcpy(CabinetNameTemplate
, Template
);
738 CabinetNameTemplateSet
= true;
742 ULONG
CDFParser::DoMaxDiskSize(bool NumberValid
, ULONG Number
)
744 * FUNCTION: Sets the maximum disk size
746 * NumberValid = true if disk number is valid
747 * Number = Disk number
749 * Status of operation
751 * Standard sizes are 2.88M, 1.44M, 1.25M, 1.2M, 720K, 360K, and CDROM
756 if (IsNextToken(TokenInteger
, true))
760 if (IsNextToken(TokenPeriod
, false))
762 if (!IsNextToken(TokenInteger
, false))
763 return CAB_STATUS_FAILURE
;
771 if (CurrentToken
== TokenIdentifier
)
773 switch (CurrentString
[0])
777 return CAB_STATUS_FAILURE
;
786 return CAB_STATUS_FAILURE
;
797 Value
= 1300000; // FIXME: Value?
802 return CAB_STATUS_FAILURE
;
810 return CAB_STATUS_FAILURE
;
813 return CAB_STATUS_FAILURE
;
817 DPRINT(MID_TRACE
, ("Bad suffix (%c)\n", CurrentString
[0]));
818 return CAB_STATUS_FAILURE
;
826 if ((CurrentToken
!= TokenString
) &&
827 (strcasecmp(CurrentString
, "CDROM") != 0))
828 return CAB_STATUS_FAILURE
;
830 Value
= 640*1024*1024; // FIXME: Correct size for CDROM?
834 return (SetDiskNumber(&MaxDiskSize
, Number
, Value
)?
835 CAB_STATUS_SUCCESS
: CAB_STATUS_FAILURE
);
837 MaxDiskSizeAll
= Value
;
838 MaxDiskSizeAllSet
= true;
840 SetMaxDiskSize(Value
);
842 return CAB_STATUS_SUCCESS
;
846 void CDFParser::DoInfFileName(char* FileName
)
848 * FUNCTION: Sets filename of the generated .inf file
850 * FileName = Pointer to .inf filename
853 DPRINT(MID_TRACE
, ("Setting .inf filename to '%s'\n", FileName
));
855 strcpy(InfFileName
, FileName
);
856 InfFileNameSet
= true;
859 ULONG
CDFParser::SetupNewDisk()
861 * FUNCTION: Sets up parameters for a new disk
863 * Status of operation
868 if (!GetDiskNumber(&MaxDiskSize
, GetCurrentDiskNumber(), &Value
))
870 if (MaxDiskSizeAllSet
)
871 Value
= MaxDiskSizeAll
;
875 SetMaxDiskSize(Value
);
877 return CAB_STATUS_SUCCESS
;
881 ULONG
CDFParser::PerformSetCommand()
883 * FUNCTION: Performs a set variable command
885 * Status of operation
889 bool NumberValid
= false;
892 if (!IsNextToken(TokenIdentifier
, true))
893 return CAB_STATUS_FAILURE
;
895 if (strcasecmp(CurrentString
, "DiskLabel") == 0)
896 SetType
= stDiskLabel
;
897 else if (strcasecmp(CurrentString
, "DiskLabelTemplate") == 0)
898 SetType
= stDiskLabelTemplate
;
899 else if (strcasecmp(CurrentString
, "CabinetName") == 0)
900 SetType
= stCabinetName
;
901 else if (strcasecmp(CurrentString
, "CabinetNameTemplate") == 0)
902 SetType
= stCabinetNameTemplate
;
903 else if (strcasecmp(CurrentString
, "MaxDiskSize") == 0)
904 SetType
= stMaxDiskSize
;
905 else if (strcasecmp(CurrentString
, "InfFileName") == 0)
906 SetType
= stInfFileName
;
908 return CAB_STATUS_FAILURE
;
910 if ((SetType
== stDiskLabel
) || (SetType
== stCabinetName
))
912 if (!IsNextToken(TokenInteger
, false))
913 return CAB_STATUS_FAILURE
;
914 Number
= CurrentInteger
;
916 if (!IsNextToken(TokenEqual
, true))
917 return CAB_STATUS_FAILURE
;
919 else if (SetType
== stMaxDiskSize
)
921 if (IsNextToken(TokenInteger
, false))
924 Number
= CurrentInteger
;
929 while (CurrentToken
== TokenSpace
)
931 if (CurrentToken
!= TokenEqual
)
932 return CAB_STATUS_FAILURE
;
935 else if (!IsNextToken(TokenEqual
, true))
936 return CAB_STATUS_FAILURE
;
938 if (SetType
!= stMaxDiskSize
)
940 if (!IsNextToken(TokenString
, true))
941 return CAB_STATUS_FAILURE
;
947 if (!DoDiskLabel(Number
, CurrentString
))
948 DPRINT(MIN_TRACE
, ("Not enough available free memory.\n"));
949 return CAB_STATUS_SUCCESS
;
952 if (!DoCabinetName(Number
, CurrentString
))
953 DPRINT(MIN_TRACE
, ("Not enough available free memory.\n"));
954 return CAB_STATUS_SUCCESS
;
956 case stDiskLabelTemplate
:
957 DoDiskLabelTemplate(CurrentString
);
958 return CAB_STATUS_SUCCESS
;
960 case stCabinetNameTemplate
:
961 DoCabinetNameTemplate(CurrentString
);
962 return CAB_STATUS_SUCCESS
;
965 return DoMaxDiskSize(NumberValid
, Number
);
968 DoInfFileName(CurrentString
);
969 return CAB_STATUS_SUCCESS
;
972 return CAB_STATUS_FAILURE
;
977 ULONG
CDFParser::PerformNewCommand()
979 * FUNCTION: Performs a new disk|cabinet|folder command
981 * Status of operation
987 if (!IsNextToken(TokenIdentifier
, true))
988 return CAB_STATUS_FAILURE
;
990 if (strcasecmp(CurrentString
, "Disk") == 0)
992 else if (strcasecmp(CurrentString
, "Cabinet") == 0)
994 else if (strcasecmp(CurrentString
, "Folder") == 0)
997 return CAB_STATUS_FAILURE
;
1004 Status
= WriteDisk(true);
1005 if (Status
== CAB_STATUS_SUCCESS
)
1006 Status
= CloseDisk();
1007 if (Status
!= CAB_STATUS_SUCCESS
)
1009 DPRINT(MIN_TRACE
, ("Cannot write disk (%u).\n", (UINT
)Status
));
1010 return CAB_STATUS_SUCCESS
;
1012 DiskCreated
= false;
1016 if (Status
!= CAB_STATUS_SUCCESS
)
1018 DPRINT(MIN_TRACE
, ("Cannot create disk (%u).\n", (UINT
)Status
));
1019 return CAB_STATUS_SUCCESS
;
1023 return CAB_STATUS_SUCCESS
;
1028 Status
= WriteDisk(true);
1029 if (Status
== CAB_STATUS_SUCCESS
)
1030 Status
= CloseDisk();
1031 if (Status
!= CAB_STATUS_SUCCESS
)
1033 DPRINT(MIN_TRACE
, ("Cannot write disk (%u).\n", (UINT
)Status
));
1034 return CAB_STATUS_SUCCESS
;
1036 DiskCreated
= false;
1039 Status
= NewCabinet();
1040 if (Status
!= CAB_STATUS_SUCCESS
)
1042 DPRINT(MIN_TRACE
, ("Cannot create cabinet (%u).\n", (UINT
)Status
));
1043 return CAB_STATUS_SUCCESS
;
1047 return CAB_STATUS_SUCCESS
;
1050 Status
= NewFolder();
1051 ASSERT(Status
== CAB_STATUS_SUCCESS
);
1052 return CAB_STATUS_SUCCESS
;
1055 return CAB_STATUS_FAILURE
;
1060 ULONG
CDFParser::PerformInfBeginCommand()
1062 * FUNCTION: Begins inf mode
1064 * Status of operation
1067 InfModeEnabled
= true;
1068 return CAB_STATUS_SUCCESS
;
1072 ULONG
CDFParser::PerformInfEndCommand()
1074 * FUNCTION: Begins inf mode
1076 * Status of operation
1079 InfModeEnabled
= false;
1080 return CAB_STATUS_SUCCESS
;
1084 ULONG
CDFParser::PerformCommand()
1086 * FUNCTION: Performs a command
1088 * Status of operation
1091 if (strcasecmp(CurrentString
, "Set") == 0)
1092 return PerformSetCommand();
1093 if (strcasecmp(CurrentString
, "New") == 0)
1094 return PerformNewCommand();
1095 if (strcasecmp(CurrentString
, "InfBegin") == 0)
1096 return PerformInfBeginCommand();
1097 if (strcasecmp(CurrentString
, "InfEnd") == 0)
1098 return PerformInfEndCommand();
1100 return CAB_STATUS_FAILURE
;
1104 ULONG
CDFParser::PerformFileCopy()
1106 * FUNCTION: Performs a file copy
1108 * Status of operation
1114 char SrcName
[PATH_MAX
];
1115 char DstName
[PATH_MAX
];
1116 char InfLine
[PATH_MAX
];
1118 char BaseFilename
[PATH_MAX
];
1126 while ((i
< LineLength
) &&
1127 ((ch
= Line
[i
]) != ' ') &&
1131 CurrentString
[i
] = ch
;
1134 CurrentString
[i
] = '\0';
1135 CurrentToken
= TokenString
;
1136 CurrentChar
= i
+ 1;
1137 strcpy(BaseFilename
, CurrentString
);
1138 strcat(SrcName
, BaseFilename
);
1143 if (CurrentToken
!= TokenEnd
)
1145 j
= (ULONG
)strlen(CurrentString
); i
= 0;
1146 while ((CurrentChar
+ i
< LineLength
) &&
1147 ((ch
= Line
[CurrentChar
+ i
]) != ' ') &&
1151 CurrentString
[j
+ i
] = ch
;
1154 CurrentString
[j
+ i
] = '\0';
1155 CurrentToken
= TokenString
;
1156 CurrentChar
+= i
+ 1;
1157 strcpy(DstName
, CurrentString
);
1160 // options (it may be empty)
1163 if (CurrentToken
!= TokenEnd
)
1165 j
= (ULONG
)strlen(CurrentString
); i
= 0;
1166 while ((CurrentChar
+ i
< LineLength
) &&
1167 ((ch
= Line
[CurrentChar
+ i
]) != ' ') &&
1171 CurrentString
[j
+ i
] = ch
;
1174 CurrentString
[j
+ i
] = '\0';
1175 CurrentToken
= TokenString
;
1176 CurrentChar
+= i
+ 1;
1177 strcpy(Options
, CurrentString
);
1180 if (!CabinetCreated
)
1182 DPRINT(MID_TRACE
, ("Creating cabinet.\n"));
1184 Status
= NewCabinet();
1185 if (Status
!= CAB_STATUS_SUCCESS
)
1187 DPRINT(MIN_TRACE
, ("Cannot create cabinet (%u).\n", (UINT
)Status
));
1188 printf("ERROR: Cannot create cabinet.\n");
1189 return CAB_STATUS_FAILURE
;
1191 CabinetCreated
= true;
1193 DPRINT(MID_TRACE
, ("Creating disk.\n"));
1196 if (Status
!= CAB_STATUS_SUCCESS
)
1198 DPRINT(MIN_TRACE
, ("Cannot create disk (%u).\n", (UINT
)Status
));
1199 printf("ERROR: Cannot create disk.\n");
1200 return CAB_STATUS_FAILURE
;
1206 DPRINT(MID_TRACE
, ("Adding file: '%s' destination: '%s'.\n", SrcName
, DstName
));
1208 Status
= AddFile(SrcName
);
1209 if (Status
== CAB_STATUS_CANNOT_OPEN
)
1211 strcpy(SrcName
, FileRelativePath
);
1212 strcat(SrcName
, BaseFilename
);
1213 Status
= AddFile(SrcName
);
1217 case CAB_STATUS_SUCCESS
:
1218 sprintf(InfLine
, "%s=%s", GetFileName(SrcName
), DstName
);
1219 WriteInfLine(InfLine
);
1222 case CAB_STATUS_CANNOT_OPEN
:
1223 if (strstr(Options
,"optional"))
1225 Status
= CAB_STATUS_SUCCESS
;
1226 printf("Optional file skipped (does not exist): %s.\n", SrcName
);
1229 printf("ERROR: File not found: %s.\n", SrcName
);
1233 case CAB_STATUS_NOMEMORY
:
1234 printf("ERROR: Insufficient memory to add file: %s.\n", SrcName
);
1238 printf("ERROR: Cannot add file: %s (%u).\n", SrcName
, (UINT
)Status
);
1245 void CDFParser::SkipSpaces()
1247 * FUNCTION: Skips any spaces in the current line
1251 while (CurrentToken
== TokenSpace
)
1256 bool CDFParser::IsNextToken(DFP_TOKEN Token
, bool NoSpaces
)
1258 * FUNCTION: Checks if next token equals Token
1260 * Token = Token to compare with
1261 * SkipSp = true if spaces should be skipped
1263 * false if next token is diffrent from Token
1270 return (CurrentToken
== Token
);
1274 bool CDFParser::ReadLine()
1276 * FUNCTION: Reads the next line into the line buffer
1278 * true if there is a new line, false if not
1284 if (CurrentOffset
>= FileBufferSize
)
1288 while (((j
= CurrentOffset
+ i
) < FileBufferSize
) && (i
< sizeof(Line
) - 1) &&
1289 ((ch
= FileBuffer
[j
]) != 0x0D && (ch
= FileBuffer
[j
]) != 0x0A))
1298 if ((FileBuffer
[CurrentOffset
+ i
] == 0x0D) && (FileBuffer
[CurrentOffset
+ i
+ 1] == 0x0A))
1301 CurrentOffset
+= i
+ 1;
1313 void CDFParser::NextToken()
1315 * FUNCTION: Reads the next token from the current line
1321 if (CurrentChar
>= LineLength
)
1323 CurrentToken
= TokenEnd
;
1327 switch (Line
[CurrentChar
])
1331 CurrentToken
= TokenSpace
;
1335 CurrentToken
= TokenSemi
;
1339 CurrentToken
= TokenEqual
;
1343 CurrentToken
= TokenPeriod
;
1347 CurrentToken
= TokenBackslash
;
1352 while ((CurrentChar
+ i
+ 1 < LineLength
) &&
1353 ((ch
= Line
[CurrentChar
+ i
+ 1]) != '"'))
1355 CurrentString
[i
] = ch
;
1358 CurrentString
[i
] = '\0';
1359 CurrentToken
= TokenString
;
1360 CurrentChar
+= i
+ 2;
1365 while ((CurrentChar
+ i
< LineLength
) &&
1366 ((ch
= Line
[CurrentChar
+ i
]) >= '0') && (ch
<= '9'))
1368 CurrentString
[i
] = ch
;
1373 CurrentString
[i
] = '\0';
1374 CurrentInteger
= atoi(CurrentString
);
1375 CurrentToken
= TokenInteger
;
1380 while (((CurrentChar
+ i
< LineLength
) &&
1381 (((ch
= Line
[CurrentChar
+ i
]) >= 'a') && (ch
<= 'z'))) ||
1382 ((ch
>= 'A') && (ch
<= 'Z')) || (ch
== '_'))
1384 CurrentString
[i
] = ch
;
1389 CurrentString
[i
] = '\0';
1390 CurrentToken
= TokenIdentifier
;
1394 CurrentToken
= TokenEnd
;