assignment bugfix for casper
[reactos.git] / reactos / tools / cabman / dfp.cxx
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS cabinet manager
4 * FILE: tools/cabman/dfp.cpp
5 * PURPOSE: Directive file parser
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * NOTES: The directive file format is similar to the
8 * directive file format used by Microsoft's MAKECAB
9 * REVISIONS:
10 * CSH 21/03-2001 Created
11 * CSH 15/08-2003 Made it portable
12 */
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include "cabinet.h"
16 #include "dfp.h"
17
18
19 /* CDFParser */
20
21 CDFParser::CDFParser()
22 /*
23 * FUNCTION: Default constructor
24 */
25 {
26 InfFileOnly = false;
27 DontGenerateInf = false;
28
29 FileBuffer = NULL;
30 FileLoaded = false;
31 CurrentOffset = 0;
32 CurrentLine = 0;
33 CabinetCreated = false;
34 DiskCreated = false;
35 FolderCreated = false;
36 CabinetName = NULL;
37 DiskLabel = NULL;
38 MaxDiskSize = NULL;
39
40 MaxDiskSizeAllSet = false;
41 CabinetNameTemplateSet = false;
42 DiskLabelTemplateSet = false;
43 InfFileNameSet = false;
44
45 InfModeEnabled = false;
46 InfFileHandle = NULL;
47 }
48
49 CDFParser::~CDFParser()
50 /*
51 * FUNCTION: Default destructor
52 */
53 {
54 PCABINET_NAME CNPrev;
55 PCABINET_NAME CNNext;
56 PDISK_NUMBER DNPrev;
57 PDISK_NUMBER DNNext;
58
59 if (FileBuffer)
60 FreeMemory(FileBuffer);
61 CNNext = CabinetName;
62 while (CNNext != NULL) {
63 CNPrev = CNNext->Next;
64 FreeMemory(CNNext);
65 CNNext = CNPrev;
66 }
67 CNNext = DiskLabel;
68 while (CNNext != NULL) {
69 CNPrev = CNNext->Next;
70 FreeMemory(CNNext);
71 CNNext = CNPrev;
72 }
73 DNNext = MaxDiskSize;
74 while (DNNext != NULL) {
75 DNPrev = DNNext->Next;
76 FreeMemory(DNNext);
77 DNNext = DNPrev;
78 }
79
80 if (InfFileHandle != NULL) {
81 CloseFile(InfFileHandle);
82 }
83 }
84
85 void CDFParser::WriteInfLine(char* InfLine)
86 {
87 char buf[MAX_PATH];
88 char eolbuf[2];
89 char* destpath;
90 #if defined(WIN32)
91 unsigned long BytesWritten;
92 #endif
93
94 if (DontGenerateInf) {
95 return;
96 }
97
98 if (InfFileHandle == NULL) {
99 if (!InfFileNameSet) {
100 /* FIXME: Use cabinet name with extension .inf */
101 return;
102 }
103
104 destpath = GetDestinationPath();
105 if (strlen(destpath) > 0) {
106 strcpy(buf, destpath);
107 strcat(buf, InfFileName);
108 } else {
109 strcpy(buf, InfFileName);
110 }
111
112 /* Create .inf file, overwrite if it already exists */
113 #if defined(WIN32)
114 InfFileHandle = CreateFile(buf, // Create this file
115 GENERIC_WRITE, // Open for writing
116 0, // No sharing
117 NULL, // No security
118 CREATE_ALWAYS, // Create or overwrite
119 FILE_ATTRIBUTE_NORMAL, // Normal file
120 NULL); // No attribute template
121 if (InfFileHandle == INVALID_HANDLE_VALUE) {
122 DPRINT(MID_TRACE, ("Error creating '%d'.\n", (unsigned int)GetLastError()));
123 return;
124 }
125 #else /* !WIN32 */
126 InfFileHandle = fopen(buf, "wb");
127 if (InfFileHandle == NULL) {
128 DPRINT(MID_TRACE, ("Error creating '%d'.\n", (unsigned int)errno));
129 return;
130 }
131 #endif
132 }
133
134 #if defined(WIN32)
135 if (!WriteFile(InfFileHandle, InfLine, strlen(InfLine), &BytesWritten, NULL)) {
136 DPRINT(MID_TRACE, ("ERROR WRITING '%d'.\n", (unsigned int)GetLastError()));
137 return;
138 }
139 #else
140 if (fwrite(InfLine, strlen(InfLine), 1, InfFileHandle) < 1)
141 return;
142 #endif
143
144 eolbuf[0] = 0x0d;
145 eolbuf[1] = 0x0a;
146
147 #if defined(WIN32)
148 if (!WriteFile(InfFileHandle, eolbuf, sizeof(eolbuf), &BytesWritten, NULL)) {
149 DPRINT(MID_TRACE, ("ERROR WRITING '%d'.\n", (unsigned int)GetLastError()));
150 return;
151 }
152 #else
153 if (fwrite(eolbuf, 1, sizeof(eolbuf), InfFileHandle) < 1)
154 return;
155 #endif
156 }
157
158
159 unsigned long CDFParser::Load(char* FileName)
160 /*
161 * FUNCTION: Loads a directive file into memory
162 * ARGUMENTS:
163 * FileName = Pointer to name of directive file
164 * RETURNS:
165 * Status of operation
166 */
167 {
168 unsigned long BytesRead;
169 long FileSize;
170
171 if (FileLoaded)
172 return CAB_STATUS_SUCCESS;
173
174 /* Create cabinet file, overwrite if it already exists */
175 #if defined(WIN32)
176 FileHandle = CreateFile(FileName, // Create this file
177 GENERIC_READ, // Open for reading
178 0, // No sharing
179 NULL, // No security
180 OPEN_EXISTING, // Open the file
181 FILE_ATTRIBUTE_NORMAL, // Normal file
182 NULL); // No attribute template
183 if (FileHandle == INVALID_HANDLE_VALUE)
184 return CAB_STATUS_CANNOT_OPEN;
185 #else /* !WIN32 */
186 FileHandle = fopen(FileName, "rb");
187 if (FileHandle == NULL) {
188 return CAB_STATUS_CANNOT_OPEN;
189 }
190 #endif
191
192 FileSize = GetSizeOfFile(FileHandle);
193 if (FileSize == (unsigned long)-1) {
194 CloseFile(FileHandle);
195 return CAB_STATUS_CANNOT_OPEN;
196 }
197
198 FileBufferSize = (unsigned long)FileSize;
199
200 FileBuffer = (char*)AllocateMemory(FileBufferSize);
201 if (!FileBuffer) {
202 CloseFile(FileHandle);
203 return CAB_STATUS_NOMEMORY;
204 }
205
206 if (!ReadFileData(FileHandle, FileBuffer, FileBufferSize, &BytesRead)) {
207 CloseFile(FileHandle);
208 FreeMemory(FileBuffer);
209 FileBuffer = NULL;
210 return CAB_STATUS_CANNOT_READ;
211 }
212
213 CloseFile(FileHandle);
214
215 FileLoaded = true;
216
217 DPRINT(MAX_TRACE, ("File (%d bytes)\n", FileBufferSize));
218
219 return CAB_STATUS_SUCCESS;
220 }
221
222
223 unsigned long CDFParser::Parse()
224 /*
225 * FUNCTION: Parses a loaded directive file
226 * RETURNS:
227 * Status of operation
228 */
229 {
230 bool Command;
231 unsigned long Status;
232
233 if (!FileLoaded)
234 return CAB_STATUS_NOFILE;
235
236 while (ReadLine()) {
237 Command = false;
238
239 if (InfModeEnabled) {
240 bool WriteLine = true;
241 while (CurrentToken != TokenEnd) {
242 switch (CurrentToken) {
243 case TokenIdentifier:
244 if (Command) {
245 /* Command */
246 Status = PerformCommand();
247 if (Status == CAB_STATUS_FAILURE) {
248 WriteLine = true;
249 } else {
250 if (!InfModeEnabled) {
251 WriteLine = false;
252 }
253 }
254 CurrentToken = TokenEnd;
255 continue;
256 } else {
257 WriteLine = true;
258 CurrentToken = TokenEnd;
259 continue;
260 }
261 break;
262 case TokenSpace:
263 break;
264 case TokenPeriod:
265 Command = true;
266 break;
267 default:
268 WriteLine = true;
269 CurrentToken = TokenEnd;
270 continue;
271 }
272 NextToken();
273 }
274 if (WriteLine) {
275 WriteInfLine(Line);
276 }
277 } else {
278 while (CurrentToken != TokenEnd) {
279 switch (CurrentToken) {
280 case TokenInteger:
281 sprintf(CurrentString, "%d", CurrentInteger);
282 case TokenIdentifier:
283 if (Command) {
284 /* Command */
285 Status = PerformCommand();
286
287 if (Status == CAB_STATUS_FAILURE) {
288 printf("Directive file contains errors at line %d.\n", (unsigned int)CurrentLine);
289 DPRINT(MID_TRACE, ("Error while executing command.\n"));
290 }
291
292 if (Status != CAB_STATUS_SUCCESS)
293 return Status;
294 } else {
295 /* File copy */
296 Status = PerformFileCopy();
297
298 if (Status == CAB_STATUS_FAILURE) {
299 printf("Directive file contains errors at line %d.\n", (unsigned int)CurrentLine);
300 DPRINT(MID_TRACE, ("Error while copying file.\n"));
301 }
302
303 if (Status != CAB_STATUS_SUCCESS)
304 return Status;
305 }
306 break;
307 case TokenSpace:
308 break;
309 case TokenSemi:
310 CurrentToken = TokenEnd;
311 continue;
312 case TokenPeriod:
313 Command = true;
314 break;
315 default:
316 printf("Directive file contains errors at line %d.\n", (unsigned int)CurrentLine);
317 DPRINT(MID_TRACE, ("Token is (%d).\n", (unsigned int)CurrentToken));
318 return CAB_STATUS_SUCCESS;
319 }
320 NextToken();
321 }
322 }
323 }
324
325 if (!InfFileOnly) {
326 printf("\nWriting cabinet. This may take a while...\n\n");
327
328 if (DiskCreated) {
329 Status = WriteDisk(false);
330 if (Status == CAB_STATUS_SUCCESS)
331 Status = CloseDisk();
332 if (Status != CAB_STATUS_SUCCESS) {
333 DPRINT(MIN_TRACE, ("Cannot write disk (%d).\n", (unsigned int)Status));
334 return Status;
335 }
336 }
337
338 if (CabinetCreated) {
339 Status = CloseCabinet();
340 if (Status != CAB_STATUS_SUCCESS) {
341 DPRINT(MIN_TRACE, ("Cannot close cabinet (%d).\n", (unsigned int)Status));
342 return Status;
343 }
344 }
345
346 printf("\nDone.\n");
347 }
348
349 return CAB_STATUS_SUCCESS;
350 }
351
352
353 bool CDFParser::OnDiskLabel(unsigned long Number, char* Label)
354 /*
355 * FUNCTION: Called when a disk needs a label
356 * ARGUMENTS:
357 * Number = Cabinet number that needs a label
358 * Label = Pointer to buffer to place label of disk
359 * RETURNS:
360 * true if a disk label was returned, false if not
361 */
362 {
363 char Buffer[20];
364 int i, j;
365 char ch;
366
367 Number += 1;
368
369 DPRINT(MID_TRACE, ("Giving disk (%d) a label...\n", (unsigned int)Number));
370
371 if (GetDiskName(&DiskLabel, Number, Label))
372 return true;
373
374 if (DiskLabelTemplateSet) {
375 j = 0;
376 strcpy(Label, "");
377 for (i = 0; i < strlen(DiskLabelTemplate); i++) {
378 ch = DiskLabelTemplate[i];
379 if (ch == '*') {
380 sprintf(Buffer, "%d", Number);
381 strcat(Label, Buffer);
382 j += strlen(Buffer);
383 } else {
384 Label[j] = ch;
385 j++;
386 }
387 Label[j] = '\0';
388 }
389
390 DPRINT(MID_TRACE, ("Giving disk (%s) as a label...\n", Label));
391
392 return true;
393 } else
394 return false;
395 }
396
397
398 bool CDFParser::OnCabinetName(unsigned long Number, char* Name)
399 /*
400 * FUNCTION: Called when a cabinet needs a name
401 * ARGUMENTS:
402 * Number = Disk number that needs a name
403 * Name = Pointer to buffer to place name of cabinet
404 * RETURNS:
405 * true if a cabinet name was returned, false if not
406 */
407 {
408 char Buffer[MAX_PATH];
409 int i, j;
410 char ch;
411
412 Number += 1;
413
414 DPRINT(MID_TRACE, ("Giving cabinet (%d) a name...\n", (unsigned int)Number));
415
416 if (GetDiskName(&CabinetName, Number, Buffer)) {
417 strcpy(Name, GetDestinationPath());
418 strcat(Name, Buffer);
419 return true;
420 }
421
422 if (CabinetNameTemplateSet) {
423 strcpy(Name, GetDestinationPath());
424 j = strlen(Name);
425 for (i = 0; i < strlen(CabinetNameTemplate); i++) {
426 ch = CabinetNameTemplate[i];
427 if (ch == '*') {
428 sprintf(Buffer, "%d", Number);
429 strcat(Name, Buffer);
430 j += strlen(Buffer);
431 } else {
432 Name[j] = ch;
433 j++;
434 }
435 Name[j] = '\0';
436 }
437
438 DPRINT(MID_TRACE, ("Giving cabinet (%s) as a name...\n", Name));
439 return true;
440 } else {
441 return false;
442 }
443 }
444
445
446 bool CDFParser::SetDiskName(PCABINET_NAME *List, unsigned long Number, char* String)
447 /*
448 * FUNCTION: Sets an entry in a list
449 * ARGUMENTS:
450 * List = Address of pointer to list
451 * Number = Disk number
452 * String = Pointer to string
453 * RETURNS:
454 * false if there was not enough free memory available
455 */
456 {
457 PCABINET_NAME CN;
458
459 CN = *List;
460 while (CN != NULL) {
461 if (CN->DiskNumber == Number) {
462 strcpy(CN->Name, String);
463 return true;
464 }
465 CN = CN->Next;
466 }
467
468 CN = (PCABINET_NAME)AllocateMemory(sizeof(CABINET_NAME));
469 if (!CN)
470 return false;
471
472 CN->DiskNumber = Number;
473 strcpy(CN->Name, String);
474
475 CN->Next = *List;
476 *List = CN;
477
478 return true;
479 }
480
481
482 bool CDFParser::GetDiskName(PCABINET_NAME *List, unsigned long Number, char* String)
483 /*
484 * FUNCTION: Returns an entry in a list
485 * ARGUMENTS:
486 * List = Address of pointer to list
487 * Number = Disk number
488 * String = Address of buffer to copy string to
489 * RETURNS:
490 * false if there was not enough free memory available
491 */
492 {
493 PCABINET_NAME CN;
494
495 CN = *List;
496 while (CN != NULL) {
497 if (CN->DiskNumber == Number) {
498 strcpy(String, CN->Name);
499 return true;
500 }
501 CN = CN->Next;
502 }
503
504 return false;
505 }
506
507
508 bool CDFParser::SetDiskNumber(PDISK_NUMBER *List, unsigned long Number, unsigned long Value)
509 /*
510 * FUNCTION: Sets an entry in a list
511 * ARGUMENTS:
512 * List = Address of pointer to list
513 * Number = Disk number
514 * Value = Value to set
515 * RETURNS:
516 * false if there was not enough free memory available
517 */
518 {
519 PDISK_NUMBER DN;
520
521 DN = *List;
522 while (DN != NULL) {
523 if (DN->DiskNumber == Number) {
524 DN->Number = Value;
525 return true;
526 }
527 DN = DN->Next;
528 }
529
530 DN = (PDISK_NUMBER)AllocateMemory(sizeof(DISK_NUMBER));
531 if (!DN)
532 return false;
533
534 DN->DiskNumber = Number;
535 DN->Number = Value;
536
537 DN->Next = *List;
538 *List = DN;
539
540 return true;
541 }
542
543
544 bool CDFParser::GetDiskNumber(PDISK_NUMBER *List, unsigned long Number, unsigned long* Value)
545 /*
546 * FUNCTION: Returns an entry in a list
547 * ARGUMENTS:
548 * List = Address of pointer to list
549 * Number = Disk number
550 * Value = Address of buffer to place value
551 * RETURNS:
552 * true if the entry was found
553 */
554 {
555 PDISK_NUMBER DN;
556
557 DN = *List;
558 while (DN != NULL) {
559 if (DN->DiskNumber == Number) {
560 *Value = DN->Number;
561 return true;
562 }
563 DN = DN->Next;
564 }
565
566 return false;
567 }
568
569
570 bool CDFParser::DoDiskLabel(unsigned long Number, char* Label)
571 /*
572 * FUNCTION: Sets the label of a disk
573 * ARGUMENTS:
574 * Number = Disk number
575 * Label = Pointer to label of disk
576 * RETURNS:
577 * false if there was not enough free memory available
578 */
579 {
580 DPRINT(MID_TRACE, ("Setting label of disk (%d) to '%s'\n", (unsigned int)Number, Label));
581
582 return SetDiskName(&DiskLabel, Number, Label);
583 }
584
585
586 void CDFParser::DoDiskLabelTemplate(char* Template)
587 /*
588 * FUNCTION: Sets a disk label template to use
589 * ARGUMENTS:
590 * Template = Pointer to disk label template
591 */
592 {
593 DPRINT(MID_TRACE, ("Setting disk label template to '%s'\n", Template));
594
595 strcpy(DiskLabelTemplate, Template);
596 DiskLabelTemplateSet = true;
597 }
598
599
600 bool CDFParser::DoCabinetName(unsigned long Number, char* Name)
601 /*
602 * FUNCTION: Sets the name of a cabinet
603 * ARGUMENTS:
604 * Number = Disk number
605 * Name = Pointer to name of cabinet
606 * RETURNS:
607 * false if there was not enough free memory available
608 */
609 {
610 DPRINT(MID_TRACE, ("Setting name of cabinet (%d) to '%s'\n", (unsigned int)Number, Name));
611
612 return SetDiskName(&CabinetName, Number, Name);
613 }
614
615
616 void CDFParser::DoCabinetNameTemplate(char* Template)
617 /*
618 * FUNCTION: Sets a cabinet name template to use
619 * ARGUMENTS:
620 * Template = Pointer to cabinet name template
621 */
622 {
623 DPRINT(MID_TRACE, ("Setting cabinet name template to '%s'\n", Template));
624
625 strcpy(CabinetNameTemplate, Template);
626 CabinetNameTemplateSet = true;
627 }
628
629
630 unsigned long CDFParser::DoMaxDiskSize(bool NumberValid, unsigned long Number)
631 /*
632 * FUNCTION: Sets the maximum disk size
633 * ARGUMENTS:
634 * NumberValid = true if disk number is valid
635 * Number = Disk number
636 * RETURNS:
637 * Status of operation
638 * NOTES:
639 * Standard sizes are 2.88M, 1.44M, 1.25M, 1.2M, 720K, 360K, and CDROM
640 */
641 {
642 unsigned long A, B, Value;
643
644 if (IsNextToken(TokenInteger, true)) {
645
646 A = CurrentInteger;
647
648 if (IsNextToken(TokenPeriod, false)) {
649 if (!IsNextToken(TokenInteger, false))
650 return CAB_STATUS_FAILURE;
651
652 B = CurrentInteger;
653
654 } else
655 B = 0;
656
657 if (CurrentToken == TokenIdentifier) {
658 switch (CurrentString[0]) {
659 case 'K':
660 if (B != 0)
661 return CAB_STATUS_FAILURE;
662
663 if (A == 720)
664 /* 720K disk */
665 Value = 730112;
666 else if (A == 360)
667 /* 360K disk */
668 Value = 362496;
669 else
670 return CAB_STATUS_FAILURE;
671 break;
672 case 'M':
673 if (A == 1) {
674 if (B == 44)
675 /* 1.44M disk */
676 Value = 1457664;
677 else if (B == 25)
678 /* 1.25M disk */
679 Value = 1300000; // FIXME: Value?
680 else if (B == 2)
681 /* 1.2M disk */
682 Value = 1213952;
683 else
684 return CAB_STATUS_FAILURE;
685 } else if (A == 2) {
686 if (B == 88)
687 /* 2.88M disk */
688 Value = 2915328;
689 else
690 return CAB_STATUS_FAILURE;
691 } else
692 return CAB_STATUS_FAILURE;
693 break;
694 default:
695 DPRINT(MID_TRACE, ("Bad suffix (%c)\n", CurrentString[0]));
696 return CAB_STATUS_FAILURE;
697 }
698 } else
699 Value = A;
700 } else {
701 if ((CurrentToken != TokenString) &&
702 (strcasecmp(CurrentString, "CDROM") != 0))
703 return CAB_STATUS_FAILURE;
704 /* CDROM */
705 Value = 640*1024*1024; // FIXME: Correct size for CDROM?
706 }
707
708 if (NumberValid)
709 return (SetDiskNumber(&MaxDiskSize, Number, Value)?
710 CAB_STATUS_SUCCESS : CAB_STATUS_FAILURE);
711
712 MaxDiskSizeAll = Value;
713 MaxDiskSizeAllSet = true;
714
715 SetMaxDiskSize(Value);
716
717 return CAB_STATUS_SUCCESS;
718 }
719
720
721 void CDFParser::DoInfFileName(char* FileName)
722 /*
723 * FUNCTION: Sets filename of the generated .inf file
724 * ARGUMENTS:
725 * FileName = Pointer to .inf filename
726 */
727 {
728 DPRINT(MID_TRACE, ("Setting .inf filename to '%s'\n", FileName));
729
730 strcpy(InfFileName, FileName);
731 InfFileNameSet = true;
732 }
733
734 unsigned long CDFParser::SetupNewDisk()
735 /*
736 * FUNCTION: Sets up parameters for a new disk
737 * RETURNS:
738 * Status of operation
739 */
740 {
741 unsigned long Value;
742
743 if (!GetDiskNumber(&MaxDiskSize, GetCurrentDiskNumber(), &Value)) {
744 if (MaxDiskSizeAllSet)
745 Value = MaxDiskSizeAll;
746 else
747 Value = 0;
748 }
749 SetMaxDiskSize(Value);
750
751 return CAB_STATUS_SUCCESS;
752 }
753
754
755 unsigned long CDFParser::PerformSetCommand()
756 /*
757 * FUNCTION: Performs a set variable command
758 * RETURNS:
759 * Status of operation
760 */
761 {
762 SETTYPE SetType;
763 bool NumberValid = false;
764 unsigned long Number = 0;
765
766 if (!IsNextToken(TokenIdentifier, true))
767 return CAB_STATUS_FAILURE;
768
769 if (strcasecmp(CurrentString, "DiskLabel") == 0)
770 SetType = stDiskLabel;
771 else if (strcasecmp(CurrentString, "DiskLabelTemplate") == 0)
772 SetType = stDiskLabelTemplate;
773 else if (strcasecmp(CurrentString, "CabinetName") == 0)
774 SetType = stCabinetName;
775 else if (strcasecmp(CurrentString, "CabinetNameTemplate") == 0)
776 SetType = stCabinetNameTemplate;
777 else if (strcasecmp(CurrentString, "MaxDiskSize") == 0)
778 SetType = stMaxDiskSize;
779 else if (strcasecmp(CurrentString, "InfFileName") == 0)
780 SetType = stInfFileName;
781 else
782 return CAB_STATUS_FAILURE;
783
784 if ((SetType == stDiskLabel) || (SetType == stCabinetName)) {
785 if (!IsNextToken(TokenInteger, false))
786 return CAB_STATUS_FAILURE;
787 Number = CurrentInteger;
788
789 if (!IsNextToken(TokenEqual, true))
790 return CAB_STATUS_FAILURE;
791 } else if (SetType == stMaxDiskSize) {
792 if (IsNextToken(TokenInteger, false)) {
793 NumberValid = true;
794 Number = CurrentInteger;
795 } else {
796 NumberValid = false;
797 while (CurrentToken == TokenSpace)
798 NextToken();
799 if (CurrentToken != TokenEqual)
800 return CAB_STATUS_FAILURE;
801 }
802 } else if (!IsNextToken(TokenEqual, true))
803 return CAB_STATUS_FAILURE;
804
805 if (SetType != stMaxDiskSize) {
806 if (!IsNextToken(TokenString, true))
807 return CAB_STATUS_FAILURE;
808 }
809
810 switch (SetType) {
811 case stDiskLabel:
812 if (!DoDiskLabel(Number, CurrentString))
813 DPRINT(MIN_TRACE, ("Not enough available free memory.\n"));
814 return CAB_STATUS_SUCCESS;
815 case stCabinetName:
816 if (!DoCabinetName(Number, CurrentString))
817 DPRINT(MIN_TRACE, ("Not enough available free memory.\n"));
818 return CAB_STATUS_SUCCESS;
819 case stDiskLabelTemplate:
820 DoDiskLabelTemplate(CurrentString);
821 return CAB_STATUS_SUCCESS;
822 case stCabinetNameTemplate:
823 DoCabinetNameTemplate(CurrentString);
824 return CAB_STATUS_SUCCESS;
825 case stMaxDiskSize:
826 return DoMaxDiskSize(NumberValid, Number);
827 case stInfFileName:
828 DoInfFileName(CurrentString);
829 return CAB_STATUS_SUCCESS;
830 default:
831 return CAB_STATUS_FAILURE;
832 }
833 }
834
835
836 unsigned long CDFParser::PerformNewCommand()
837 /*
838 * FUNCTION: Performs a new disk|cabinet|folder command
839 * RETURNS:
840 * Status of operation
841 */
842 {
843 NEWTYPE NewType;
844 unsigned long Status;
845
846 if (!IsNextToken(TokenIdentifier, true))
847 return CAB_STATUS_FAILURE;
848
849 if (strcasecmp(CurrentString, "Disk") == 0)
850 NewType = ntDisk;
851 else if (strcasecmp(CurrentString, "Cabinet") == 0)
852 NewType = ntCabinet;
853 else if (strcasecmp(CurrentString, "Folder") == 0)
854 NewType = ntFolder;
855 else
856 return CAB_STATUS_FAILURE;
857
858 switch (NewType) {
859 case ntDisk:
860 if (DiskCreated) {
861 Status = WriteDisk(true);
862 if (Status == CAB_STATUS_SUCCESS)
863 Status = CloseDisk();
864 if (Status != CAB_STATUS_SUCCESS) {
865 DPRINT(MIN_TRACE, ("Cannot write disk (%d).\n", (unsigned int)Status));
866 return CAB_STATUS_SUCCESS;
867 }
868 DiskCreated = false;
869 }
870
871 Status = NewDisk();
872 if (Status != CAB_STATUS_SUCCESS) {
873 DPRINT(MIN_TRACE, ("Cannot create disk (%d).\n", (unsigned int)Status));
874 return CAB_STATUS_SUCCESS;
875 }
876 DiskCreated = true;
877 SetupNewDisk();
878 return CAB_STATUS_SUCCESS;
879 case ntCabinet:
880 if (DiskCreated) {
881 Status = WriteDisk(true);
882 if (Status == CAB_STATUS_SUCCESS)
883 Status = CloseDisk();
884 if (Status != CAB_STATUS_SUCCESS) {
885 DPRINT(MIN_TRACE, ("Cannot write disk (%d).\n", (unsigned int)Status));
886 return CAB_STATUS_SUCCESS;
887 }
888 DiskCreated = false;
889 }
890
891 Status = NewCabinet();
892 if (Status != CAB_STATUS_SUCCESS) {
893 DPRINT(MIN_TRACE, ("Cannot create cabinet (%d).\n", (unsigned int)Status));
894 return CAB_STATUS_SUCCESS;
895 }
896 DiskCreated = true;
897 SetupNewDisk();
898 return CAB_STATUS_SUCCESS;
899 case ntFolder:
900 Status = NewFolder();
901 ASSERT(Status == CAB_STATUS_SUCCESS);
902 return CAB_STATUS_SUCCESS;
903 default:
904 return CAB_STATUS_FAILURE;
905 }
906 }
907
908
909 unsigned long CDFParser::PerformInfBeginCommand()
910 /*
911 * FUNCTION: Begins inf mode
912 * RETURNS:
913 * Status of operation
914 */
915 {
916 InfModeEnabled = true;
917 return CAB_STATUS_SUCCESS;
918 }
919
920
921 unsigned long CDFParser::PerformInfEndCommand()
922 /*
923 * FUNCTION: Begins inf mode
924 * RETURNS:
925 * Status of operation
926 */
927 {
928 InfModeEnabled = false;
929 return CAB_STATUS_SUCCESS;
930 }
931
932
933 unsigned long CDFParser::PerformCommand()
934 /*
935 * FUNCTION: Performs a command
936 * RETURNS:
937 * Status of operation
938 */
939 {
940 if (strcasecmp(CurrentString, "Set") == 0)
941 return PerformSetCommand();
942 if (strcasecmp(CurrentString, "New") == 0)
943 return PerformNewCommand();
944 if (strcasecmp(CurrentString, "InfBegin") == 0)
945 return PerformInfBeginCommand();
946 if (strcasecmp(CurrentString, "InfEnd") == 0)
947 return PerformInfEndCommand();
948
949 return CAB_STATUS_FAILURE;
950 }
951
952
953 unsigned long CDFParser::PerformFileCopy()
954 /*
955 * FUNCTION: Performs a file copy
956 * RETURNS:
957 * Status of operation
958 */
959 {
960 unsigned long Status;
961 unsigned long i, j;
962 char ch;
963 char SrcName[MAX_PATH];
964 char DstName[MAX_PATH];
965 char InfLine[MAX_PATH];
966
967 strcpy(SrcName, "");
968 strcpy(DstName, "");
969
970 i = strlen(CurrentString);
971 while ((i < LineLength) &&
972 ((ch = Line[i]) != ' ') &&
973 (ch != 0x09) &&
974 (ch != ';')) {
975 CurrentString[i] = ch;
976 i++;
977 }
978 CurrentString[i] = '\0';
979 CurrentToken = TokenString;
980 CurrentChar = i + 1;
981 strcpy(SrcName, CurrentString);
982
983 SkipSpaces();
984
985 if (CurrentToken != TokenEnd) {
986 j = strlen(CurrentString); i = 0;
987 while ((CurrentChar + i < LineLength) &&
988 ((ch = Line[CurrentChar + i]) != ' ') &&
989 (ch != 0x09) &&
990 (ch != ';')) {
991 CurrentString[j + i] = ch;
992 i++;
993 }
994 CurrentString[j + i] = '\0';
995 CurrentToken = TokenString;
996 CurrentChar += i + 1;
997 strcpy(DstName, CurrentString);
998 }
999
1000 if (!CabinetCreated) {
1001
1002 DPRINT(MID_TRACE, ("Creating cabinet.\n"));
1003
1004 Status = NewCabinet();
1005 if (Status != CAB_STATUS_SUCCESS) {
1006 DPRINT(MIN_TRACE, ("Cannot create cabinet (%d).\n", (unsigned int)Status));
1007 printf("Cannot create cabinet.\n");
1008 return CAB_STATUS_FAILURE;
1009 }
1010 CabinetCreated = true;
1011
1012 DPRINT(MID_TRACE, ("Creating disk.\n"));
1013
1014 Status = NewDisk();
1015 if (Status != CAB_STATUS_SUCCESS) {
1016 DPRINT(MIN_TRACE, ("Cannot create disk (%d).\n", (unsigned int)Status));
1017 printf("Cannot create disk.\n");
1018 return CAB_STATUS_FAILURE;
1019 }
1020 DiskCreated = true;
1021 SetupNewDisk();
1022 }
1023
1024 DPRINT(MID_TRACE, ("Adding file: '%s' destination: '%s'.\n", SrcName, DstName));
1025
1026 sprintf(InfLine, "%s=%s", GetFileName(SrcName), DstName);
1027 WriteInfLine(InfLine);
1028
1029 Status = AddFile(SrcName);
1030 if (Status != CAB_STATUS_SUCCESS) {
1031 if (Status == CAB_STATUS_CANNOT_OPEN)
1032 printf("File does not exist: %s.\n", SrcName);
1033 else if (Status == CAB_STATUS_NOMEMORY)
1034 printf("Insufficient memory to add file: %s.\n", SrcName);
1035 else
1036 printf("Cannot add file: %s (%d).\n", SrcName, Status);
1037 return Status;
1038 }
1039
1040 return CAB_STATUS_SUCCESS;
1041 }
1042
1043
1044 void CDFParser::SkipSpaces()
1045 /*
1046 * FUNCTION: Skips any spaces in the current line
1047 */
1048 {
1049 NextToken();
1050 while (CurrentToken == TokenSpace)
1051 NextToken();
1052 }
1053
1054
1055 bool CDFParser::IsNextToken(TOKEN Token, bool NoSpaces)
1056 /*
1057 * FUNCTION: Checks if next token equals Token
1058 * ARGUMENTS:
1059 * Token = Token to compare with
1060 * SkipSp = true if spaces should be skipped
1061 * RETURNS:
1062 * false if next token is diffrent from Token
1063 */
1064 {
1065 if (NoSpaces)
1066 SkipSpaces();
1067 else
1068 NextToken();
1069 return (CurrentToken == Token);
1070 }
1071
1072
1073 bool CDFParser::ReadLine()
1074 /*
1075 * FUNCTION: Reads the next line into the line buffer
1076 * RETURNS:
1077 * true if there is a new line, false if not
1078 */
1079 {
1080 unsigned long i, j;
1081 char ch;
1082
1083 if (CurrentOffset >= FileBufferSize)
1084 return false;
1085
1086 i = 0;
1087 while (((j = CurrentOffset + i) < FileBufferSize) && (i < 127) &&
1088 ((ch = FileBuffer[j]) != 0x0D && (ch = FileBuffer[j]) != 0x0A)) {
1089 Line[i] = ch;
1090 i++;
1091 }
1092
1093 Line[i] = '\0';
1094 LineLength = i;
1095
1096 if ((FileBuffer[CurrentOffset + i] == 0x0D) && (FileBuffer[CurrentOffset + i + 1] == 0x0A))
1097 CurrentOffset++;
1098
1099 CurrentOffset += i + 1;
1100
1101 CurrentChar = 0;
1102
1103 CurrentLine++;
1104
1105 NextToken();
1106
1107 return true;
1108 }
1109
1110
1111 void CDFParser::NextToken()
1112 /*
1113 * FUNCTION: Reads the next token from the current line
1114 */
1115 {
1116 unsigned long i;
1117 char ch = ' ';
1118
1119 if (CurrentChar >= LineLength) {
1120 CurrentToken = TokenEnd;
1121 return;
1122 }
1123
1124 switch (Line[CurrentChar]) {
1125 case ' ':
1126 case 0x09: CurrentToken = TokenSpace;
1127 break;
1128 case ';': CurrentToken = TokenSemi;
1129 break;
1130 case '=': CurrentToken = TokenEqual;
1131 break;
1132 case '.': CurrentToken = TokenPeriod;
1133 break;
1134 case '\\': CurrentToken = TokenBackslash;
1135 break;
1136 case '"':
1137 i = 0;
1138 while ((CurrentChar + i + 1 < LineLength) &&
1139 ((ch = Line[CurrentChar + i + 1]) != '"')) {
1140 CurrentString[i] = ch;
1141 i++;
1142 }
1143 CurrentString[i] = '\0';
1144 CurrentToken = TokenString;
1145 CurrentChar += i + 2;
1146 return;
1147 default:
1148 i = 0;
1149 while ((CurrentChar + i < LineLength) &&
1150 ((ch = Line[CurrentChar + i]) >= '0') && (ch <= '9')) {
1151 CurrentString[i] = ch;
1152 i++;
1153 }
1154 if (i > 0) {
1155 CurrentString[i] = '\0';
1156 CurrentInteger = atoi((char*)CurrentString);
1157 CurrentToken = TokenInteger;
1158 CurrentChar += i;
1159 return;
1160 }
1161 i = 0;
1162 while (((CurrentChar + i < LineLength) &&
1163 (((ch = Line[CurrentChar + i]) >= 'a') && (ch <= 'z')) ||
1164 ((ch >= 'A') && (ch <= 'Z')) || (ch == '_'))) {
1165 CurrentString[i] = ch;
1166 i++;
1167 }
1168 if (i > 0) {
1169 CurrentString[i] = '\0';
1170 CurrentToken = TokenIdentifier;
1171 CurrentChar += i;
1172 return;
1173 }
1174 CurrentToken = TokenEnd;
1175 }
1176 CurrentChar++;
1177 }
1178
1179 /* EOF */