--- /dev/null
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS cabinet manager
+ * FILE: tools/cabman/dfp.cpp
+ * PURPOSE: Directive file parser
+ * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * NOTES: The directive file format is similar to the
+ * directive file format used by Microsoft's MAKECAB
+ * REVISIONS:
+ * CSH 21/03-2001 Created
+ * CSH 15/08-2003 Made it portable
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include "cabinet.h"
+#include "dfp.h"
+
+
+/* CDFParser */
+
+CDFParser::CDFParser()
+/*
+ * FUNCTION: Default constructor
+ */
+{
+ InfFileOnly = false;
+ DontGenerateInf = false;
+
+ FileBuffer = NULL;
+ FileLoaded = false;
+ CurrentOffset = 0;
+ CurrentLine = 0;
+ CabinetCreated = false;
+ DiskCreated = false;
+ FolderCreated = false;
+ CabinetName = NULL;
+ DiskLabel = NULL;
+ MaxDiskSize = NULL;
+
+ MaxDiskSizeAllSet = false;
+ CabinetNameTemplateSet = false;
+ DiskLabelTemplateSet = false;
+ InfFileNameSet = false;
+
+ InfModeEnabled = false;
+ InfFileHandle = NULL;
+}
+
+CDFParser::~CDFParser()
+/*
+ * FUNCTION: Default destructor
+ */
+{
+ PCABINET_NAME CNPrev;
+ PCABINET_NAME CNNext;
+ PDISK_NUMBER DNPrev;
+ PDISK_NUMBER DNNext;
+
+ if (FileBuffer)
+ FreeMemory(FileBuffer);
+ CNNext = CabinetName;
+ while (CNNext != NULL) {
+ CNPrev = CNNext->Next;
+ FreeMemory(CNNext);
+ CNNext = CNPrev;
+ }
+ CNNext = DiskLabel;
+ while (CNNext != NULL) {
+ CNPrev = CNNext->Next;
+ FreeMemory(CNNext);
+ CNNext = CNPrev;
+ }
+ DNNext = MaxDiskSize;
+ while (DNNext != NULL) {
+ DNPrev = DNNext->Next;
+ FreeMemory(DNNext);
+ DNNext = DNPrev;
+ }
+
+ if (InfFileHandle != NULL) {
+ CloseFile(InfFileHandle);
+ }
+}
+
+void CDFParser::WriteInfLine(char* InfLine)
+{
+ char buf[MAX_PATH];
+ char eolbuf[2];
+ char* destpath;
+#if defined(WIN32)
+ unsigned long BytesWritten;
+#endif
+
+ if (DontGenerateInf) {
+ return;
+ }
+
+ if (InfFileHandle == NULL) {
+ if (!InfFileNameSet) {
+ /* FIXME: Use cabinet name with extension .inf */
+ return;
+ }
+
+ destpath = GetDestinationPath();
+ if (strlen(destpath) > 0) {
+ strcpy(buf, destpath);
+ strcat(buf, InfFileName);
+ } else {
+ strcpy(buf, InfFileName);
+ }
+
+ /* Create .inf file, overwrite if it already exists */
+#if defined(WIN32)
+ InfFileHandle = CreateFile(buf, // Create this file
+ GENERIC_WRITE, // Open for writing
+ 0, // No sharing
+ NULL, // No security
+ CREATE_ALWAYS, // Create or overwrite
+ FILE_ATTRIBUTE_NORMAL, // Normal file
+ NULL); // No attribute template
+ if (InfFileHandle == INVALID_HANDLE_VALUE) {
+ DPRINT(MID_TRACE, ("Error creating '%d'.\n", (unsigned int)GetLastError()));
+ return;
+ }
+#else /* !WIN32 */
+ InfFileHandle = fopen(buf, "wb");
+ if (InfFileHandle == NULL) {
+ DPRINT(MID_TRACE, ("Error creating '%d'.\n", (unsigned int)errno));
+ return;
+ }
+#endif
+ }
+
+#if defined(WIN32)
+ if (!WriteFile(InfFileHandle, InfLine, strlen(InfLine), &BytesWritten, NULL)) {
+ DPRINT(MID_TRACE, ("ERROR WRITING '%d'.\n", (unsigned int)GetLastError()));
+ return;
+ }
+#else
+ if (fwrite(InfLine, strlen(InfLine), 1, InfFileHandle) < 1)
+ return;
+#endif
+
+ eolbuf[0] = 0x0d;
+ eolbuf[1] = 0x0a;
+
+#if defined(WIN32)
+ if (!WriteFile(InfFileHandle, eolbuf, sizeof(eolbuf), &BytesWritten, NULL)) {
+ DPRINT(MID_TRACE, ("ERROR WRITING '%d'.\n", (unsigned int)GetLastError()));
+ return;
+ }
+#else
+ if (fwrite(eolbuf, 1, sizeof(eolbuf), InfFileHandle) < 1)
+ return;
+#endif
+}
+
+
+unsigned long CDFParser::Load(char* FileName)
+/*
+ * FUNCTION: Loads a directive file into memory
+ * ARGUMENTS:
+ * FileName = Pointer to name of directive file
+ * RETURNS:
+ * Status of operation
+ */
+{
+ unsigned long BytesRead;
+ long FileSize;
+
+ if (FileLoaded)
+ return CAB_STATUS_SUCCESS;
+
+ /* Create cabinet file, overwrite if it already exists */
+#if defined(WIN32)
+ FileHandle = CreateFile(FileName, // Create this file
+ GENERIC_READ, // Open for reading
+ 0, // No sharing
+ NULL, // No security
+ OPEN_EXISTING, // Open the file
+ FILE_ATTRIBUTE_NORMAL, // Normal file
+ NULL); // No attribute template
+ if (FileHandle == INVALID_HANDLE_VALUE)
+ return CAB_STATUS_CANNOT_OPEN;
+#else /* !WIN32 */
+ FileHandle = fopen(FileName, "rb");
+ if (FileHandle == NULL) {
+ return CAB_STATUS_CANNOT_OPEN;
+ }
+#endif
+
+ FileSize = GetSizeOfFile(FileHandle);
+ if (FileSize == (unsigned long)-1) {
+ CloseFile(FileHandle);
+ return CAB_STATUS_CANNOT_OPEN;
+ }
+
+ FileBufferSize = (unsigned long)FileSize;
+
+ FileBuffer = (char*)AllocateMemory(FileBufferSize);
+ if (!FileBuffer) {
+ CloseFile(FileHandle);
+ return CAB_STATUS_NOMEMORY;
+ }
+
+ if (!ReadFileData(FileHandle, FileBuffer, FileBufferSize, &BytesRead)) {
+ CloseFile(FileHandle);
+ FreeMemory(FileBuffer);
+ FileBuffer = NULL;
+ return CAB_STATUS_CANNOT_READ;
+ }
+
+ CloseFile(FileHandle);
+
+ FileLoaded = true;
+
+ DPRINT(MAX_TRACE, ("File (%d bytes)\n", FileBufferSize));
+
+ return CAB_STATUS_SUCCESS;
+}
+
+
+unsigned long CDFParser::Parse()
+/*
+ * FUNCTION: Parses a loaded directive file
+ * RETURNS:
+ * Status of operation
+ */
+{
+ bool Command;
+ unsigned long Status;
+
+ if (!FileLoaded)
+ return CAB_STATUS_NOFILE;
+
+ while (ReadLine()) {
+ Command = false;
+
+ if (InfModeEnabled) {
+ bool WriteLine = true;
+ while (CurrentToken != TokenEnd) {
+ switch (CurrentToken) {
+ case TokenIdentifier:
+ if (Command) {
+ /* Command */
+ Status = PerformCommand();
+ if (Status == CAB_STATUS_FAILURE) {
+ WriteLine = true;
+ } else {
+ if (!InfModeEnabled) {
+ WriteLine = false;
+ }
+ }
+ CurrentToken = TokenEnd;
+ continue;
+ } else {
+ WriteLine = true;
+ CurrentToken = TokenEnd;
+ continue;
+ }
+ break;
+ case TokenSpace:
+ break;
+ case TokenPeriod:
+ Command = true;
+ break;
+ default:
+ WriteLine = true;
+ CurrentToken = TokenEnd;
+ continue;
+ }
+ NextToken();
+ }
+ if (WriteLine) {
+ WriteInfLine(Line);
+ }
+ } else {
+ while (CurrentToken != TokenEnd) {
+ switch (CurrentToken) {
+ case TokenInteger:
+ sprintf(CurrentString, "%d", CurrentInteger);
+ case TokenIdentifier:
+ if (Command) {
+ /* Command */
+ Status = PerformCommand();
+
+ if (Status == CAB_STATUS_FAILURE) {
+ printf("Directive file contains errors at line %d.\n", (unsigned int)CurrentLine);
+ DPRINT(MID_TRACE, ("Error while executing command.\n"));
+ }
+
+ if (Status != CAB_STATUS_SUCCESS)
+ return Status;
+ } else {
+ /* File copy */
+ Status = PerformFileCopy();
+
+ if (Status == CAB_STATUS_FAILURE) {
+ printf("Directive file contains errors at line %d.\n", (unsigned int)CurrentLine);
+ DPRINT(MID_TRACE, ("Error while copying file.\n"));
+ }
+
+ if (Status != CAB_STATUS_SUCCESS)
+ return Status;
+ }
+ break;
+ case TokenSpace:
+ break;
+ case TokenSemi:
+ CurrentToken = TokenEnd;
+ continue;
+ case TokenPeriod:
+ Command = true;
+ break;
+ default:
+ printf("Directive file contains errors at line %d.\n", (unsigned int)CurrentLine);
+ DPRINT(MID_TRACE, ("Token is (%d).\n", (unsigned int)CurrentToken));
+ return CAB_STATUS_SUCCESS;
+ }
+ NextToken();
+ }
+ }
+ }
+
+ if (!InfFileOnly) {
+ printf("\nWriting cabinet. This may take a while...\n\n");
+
+ if (DiskCreated) {
+ Status = WriteDisk(false);
+ if (Status == CAB_STATUS_SUCCESS)
+ Status = CloseDisk();
+ if (Status != CAB_STATUS_SUCCESS) {
+ DPRINT(MIN_TRACE, ("Cannot write disk (%d).\n", (unsigned int)Status));
+ return Status;
+ }
+ }
+
+ if (CabinetCreated) {
+ Status = CloseCabinet();
+ if (Status != CAB_STATUS_SUCCESS) {
+ DPRINT(MIN_TRACE, ("Cannot close cabinet (%d).\n", (unsigned int)Status));
+ return Status;
+ }
+ }
+
+ printf("\nDone.\n");
+ }
+
+ return CAB_STATUS_SUCCESS;
+}
+
+
+bool CDFParser::OnDiskLabel(unsigned long Number, char* Label)
+/*
+ * FUNCTION: Called when a disk needs a label
+ * ARGUMENTS:
+ * Number = Cabinet number that needs a label
+ * Label = Pointer to buffer to place label of disk
+ * RETURNS:
+ * true if a disk label was returned, false if not
+ */
+{
+ char Buffer[20];
+ int i, j;
+ char ch;
+
+ Number += 1;
+
+ DPRINT(MID_TRACE, ("Giving disk (%d) a label...\n", (unsigned int)Number));
+
+ if (GetDiskName(&DiskLabel, Number, Label))
+ return true;
+
+ if (DiskLabelTemplateSet) {
+ j = 0;
+ strcpy(Label, "");
+ for (i = 0; i < strlen(DiskLabelTemplate); i++) {
+ ch = DiskLabelTemplate[i];
+ if (ch == '*') {
+ sprintf(Buffer, "%d", Number);
+ strcat(Label, Buffer);
+ j += strlen(Buffer);
+ } else {
+ Label[j] = ch;
+ j++;
+ }
+ Label[j] = '\0';
+ }
+
+ DPRINT(MID_TRACE, ("Giving disk (%s) as a label...\n", Label));
+
+ return true;
+ } else
+ return false;
+}
+
+
+bool CDFParser::OnCabinetName(unsigned long Number, char* Name)
+/*
+ * FUNCTION: Called when a cabinet needs a name
+ * ARGUMENTS:
+ * Number = Disk number that needs a name
+ * Name = Pointer to buffer to place name of cabinet
+ * RETURNS:
+ * true if a cabinet name was returned, false if not
+ */
+{
+ char Buffer[MAX_PATH];
+ int i, j;
+ char ch;
+
+ Number += 1;
+
+ DPRINT(MID_TRACE, ("Giving cabinet (%d) a name...\n", (unsigned int)Number));
+
+ if (GetDiskName(&CabinetName, Number, Buffer)) {
+ strcpy(Name, GetDestinationPath());
+ strcat(Name, Buffer);
+ return true;
+ }
+
+ if (CabinetNameTemplateSet) {
+ strcpy(Name, GetDestinationPath());
+ j = strlen(Name);
+ for (i = 0; i < strlen(CabinetNameTemplate); i++) {
+ ch = CabinetNameTemplate[i];
+ if (ch == '*') {
+ sprintf(Buffer, "%d", Number);
+ strcat(Name, Buffer);
+ j += strlen(Buffer);
+ } else {
+ Name[j] = ch;
+ j++;
+ }
+ Name[j] = '\0';
+ }
+
+ DPRINT(MID_TRACE, ("Giving cabinet (%s) as a name...\n", Name));
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
+bool CDFParser::SetDiskName(PCABINET_NAME *List, unsigned long Number, char* String)
+/*
+ * FUNCTION: Sets an entry in a list
+ * ARGUMENTS:
+ * List = Address of pointer to list
+ * Number = Disk number
+ * String = Pointer to string
+ * RETURNS:
+ * false if there was not enough free memory available
+ */
+{
+ PCABINET_NAME CN;
+
+ CN = *List;
+ while (CN != NULL) {
+ if (CN->DiskNumber == Number) {
+ strcpy(CN->Name, String);
+ return true;
+ }
+ CN = CN->Next;
+ }
+
+ CN = (PCABINET_NAME)AllocateMemory(sizeof(CABINET_NAME));
+ if (!CN)
+ return false;
+
+ CN->DiskNumber = Number;
+ strcpy(CN->Name, String);
+
+ CN->Next = *List;
+ *List = CN;
+
+ return true;
+}
+
+
+bool CDFParser::GetDiskName(PCABINET_NAME *List, unsigned long Number, char* String)
+/*
+ * FUNCTION: Returns an entry in a list
+ * ARGUMENTS:
+ * List = Address of pointer to list
+ * Number = Disk number
+ * String = Address of buffer to copy string to
+ * RETURNS:
+ * false if there was not enough free memory available
+ */
+{
+ PCABINET_NAME CN;
+
+ CN = *List;
+ while (CN != NULL) {
+ if (CN->DiskNumber == Number) {
+ strcpy(String, CN->Name);
+ return true;
+ }
+ CN = CN->Next;
+ }
+
+ return false;
+}
+
+
+bool CDFParser::SetDiskNumber(PDISK_NUMBER *List, unsigned long Number, unsigned long Value)
+/*
+ * FUNCTION: Sets an entry in a list
+ * ARGUMENTS:
+ * List = Address of pointer to list
+ * Number = Disk number
+ * Value = Value to set
+ * RETURNS:
+ * false if there was not enough free memory available
+ */
+{
+ PDISK_NUMBER DN;
+
+ DN = *List;
+ while (DN != NULL) {
+ if (DN->DiskNumber == Number) {
+ DN->Number = Value;
+ return true;
+ }
+ DN = DN->Next;
+ }
+
+ DN = (PDISK_NUMBER)AllocateMemory(sizeof(DISK_NUMBER));
+ if (!DN)
+ return false;
+
+ DN->DiskNumber = Number;
+ DN->Number = Value;
+
+ DN->Next = *List;
+ *List = DN;
+
+ return true;
+}
+
+
+bool CDFParser::GetDiskNumber(PDISK_NUMBER *List, unsigned long Number, unsigned long* Value)
+/*
+ * FUNCTION: Returns an entry in a list
+ * ARGUMENTS:
+ * List = Address of pointer to list
+ * Number = Disk number
+ * Value = Address of buffer to place value
+ * RETURNS:
+ * true if the entry was found
+ */
+{
+ PDISK_NUMBER DN;
+
+ DN = *List;
+ while (DN != NULL) {
+ if (DN->DiskNumber == Number) {
+ *Value = DN->Number;
+ return true;
+ }
+ DN = DN->Next;
+ }
+
+ return false;
+}
+
+
+bool CDFParser::DoDiskLabel(unsigned long Number, char* Label)
+/*
+ * FUNCTION: Sets the label of a disk
+ * ARGUMENTS:
+ * Number = Disk number
+ * Label = Pointer to label of disk
+ * RETURNS:
+ * false if there was not enough free memory available
+ */
+{
+ DPRINT(MID_TRACE, ("Setting label of disk (%d) to '%s'\n", (unsigned int)Number, Label));
+
+ return SetDiskName(&DiskLabel, Number, Label);
+}
+
+
+void CDFParser::DoDiskLabelTemplate(char* Template)
+/*
+ * FUNCTION: Sets a disk label template to use
+ * ARGUMENTS:
+ * Template = Pointer to disk label template
+ */
+{
+ DPRINT(MID_TRACE, ("Setting disk label template to '%s'\n", Template));
+
+ strcpy(DiskLabelTemplate, Template);
+ DiskLabelTemplateSet = true;
+}
+
+
+bool CDFParser::DoCabinetName(unsigned long Number, char* Name)
+/*
+ * FUNCTION: Sets the name of a cabinet
+ * ARGUMENTS:
+ * Number = Disk number
+ * Name = Pointer to name of cabinet
+ * RETURNS:
+ * false if there was not enough free memory available
+ */
+{
+ DPRINT(MID_TRACE, ("Setting name of cabinet (%d) to '%s'\n", (unsigned int)Number, Name));
+
+ return SetDiskName(&CabinetName, Number, Name);
+}
+
+
+void CDFParser::DoCabinetNameTemplate(char* Template)
+/*
+ * FUNCTION: Sets a cabinet name template to use
+ * ARGUMENTS:
+ * Template = Pointer to cabinet name template
+ */
+{
+ DPRINT(MID_TRACE, ("Setting cabinet name template to '%s'\n", Template));
+
+ strcpy(CabinetNameTemplate, Template);
+ CabinetNameTemplateSet = true;
+}
+
+
+unsigned long CDFParser::DoMaxDiskSize(bool NumberValid, unsigned long Number)
+/*
+ * FUNCTION: Sets the maximum disk size
+ * ARGUMENTS:
+ * NumberValid = true if disk number is valid
+ * Number = Disk number
+ * RETURNS:
+ * Status of operation
+ * NOTES:
+ * Standard sizes are 2.88M, 1.44M, 1.25M, 1.2M, 720K, 360K, and CDROM
+ */
+{
+ unsigned long A, B, Value;
+
+ if (IsNextToken(TokenInteger, true)) {
+
+ A = CurrentInteger;
+
+ if (IsNextToken(TokenPeriod, false)) {
+ if (!IsNextToken(TokenInteger, false))
+ return CAB_STATUS_FAILURE;
+
+ B = CurrentInteger;
+
+ } else
+ B = 0;
+
+ if (CurrentToken == TokenIdentifier) {
+ switch (CurrentString[0]) {
+ case 'K':
+ if (B != 0)
+ return CAB_STATUS_FAILURE;
+
+ if (A == 720)
+ /* 720K disk */
+ Value = 730112;
+ else if (A == 360)
+ /* 360K disk */
+ Value = 362496;
+ else
+ return CAB_STATUS_FAILURE;
+ break;
+ case 'M':
+ if (A == 1) {
+ if (B == 44)
+ /* 1.44M disk */
+ Value = 1457664;
+ else if (B == 25)
+ /* 1.25M disk */
+ Value = 1300000; // FIXME: Value?
+ else if (B == 2)
+ /* 1.2M disk */
+ Value = 1213952;
+ else
+ return CAB_STATUS_FAILURE;
+ } else if (A == 2) {
+ if (B == 88)
+ /* 2.88M disk */
+ Value = 2915328;
+ else
+ return CAB_STATUS_FAILURE;
+ } else
+ return CAB_STATUS_FAILURE;
+ break;
+ default:
+ DPRINT(MID_TRACE, ("Bad suffix (%c)\n", CurrentString[0]));
+ return CAB_STATUS_FAILURE;
+ }
+ } else
+ Value = A;
+ } else {
+ if ((CurrentToken != TokenString) &&
+ (strcasecmp(CurrentString, "CDROM") != 0))
+ return CAB_STATUS_FAILURE;
+ /* CDROM */
+ Value = 640*1024*1024; // FIXME: Correct size for CDROM?
+ }
+
+ if (NumberValid)
+ return (SetDiskNumber(&MaxDiskSize, Number, Value)?
+ CAB_STATUS_SUCCESS : CAB_STATUS_FAILURE);
+
+ MaxDiskSizeAll = Value;
+ MaxDiskSizeAllSet = true;
+
+ SetMaxDiskSize(Value);
+
+ return CAB_STATUS_SUCCESS;
+}
+
+
+void CDFParser::DoInfFileName(char* FileName)
+/*
+ * FUNCTION: Sets filename of the generated .inf file
+ * ARGUMENTS:
+ * FileName = Pointer to .inf filename
+ */
+{
+ DPRINT(MID_TRACE, ("Setting .inf filename to '%s'\n", FileName));
+
+ strcpy(InfFileName, FileName);
+ InfFileNameSet = true;
+}
+
+unsigned long CDFParser::SetupNewDisk()
+/*
+ * FUNCTION: Sets up parameters for a new disk
+ * RETURNS:
+ * Status of operation
+ */
+{
+ unsigned long Value;
+
+ if (!GetDiskNumber(&MaxDiskSize, GetCurrentDiskNumber(), &Value)) {
+ if (MaxDiskSizeAllSet)
+ Value = MaxDiskSizeAll;
+ else
+ Value = 0;
+ }
+ SetMaxDiskSize(Value);
+
+ return CAB_STATUS_SUCCESS;
+}
+
+
+unsigned long CDFParser::PerformSetCommand()
+/*
+ * FUNCTION: Performs a set variable command
+ * RETURNS:
+ * Status of operation
+ */
+{
+ SETTYPE SetType;
+ bool NumberValid = false;
+ unsigned long Number = 0;
+
+ if (!IsNextToken(TokenIdentifier, true))
+ return CAB_STATUS_FAILURE;
+
+ if (strcasecmp(CurrentString, "DiskLabel") == 0)
+ SetType = stDiskLabel;
+ else if (strcasecmp(CurrentString, "DiskLabelTemplate") == 0)
+ SetType = stDiskLabelTemplate;
+ else if (strcasecmp(CurrentString, "CabinetName") == 0)
+ SetType = stCabinetName;
+ else if (strcasecmp(CurrentString, "CabinetNameTemplate") == 0)
+ SetType = stCabinetNameTemplate;
+ else if (strcasecmp(CurrentString, "MaxDiskSize") == 0)
+ SetType = stMaxDiskSize;
+ else if (strcasecmp(CurrentString, "InfFileName") == 0)
+ SetType = stInfFileName;
+ else
+ return CAB_STATUS_FAILURE;
+
+ if ((SetType == stDiskLabel) || (SetType == stCabinetName)) {
+ if (!IsNextToken(TokenInteger, false))
+ return CAB_STATUS_FAILURE;
+ Number = CurrentInteger;
+
+ if (!IsNextToken(TokenEqual, true))
+ return CAB_STATUS_FAILURE;
+ } else if (SetType == stMaxDiskSize) {
+ if (IsNextToken(TokenInteger, false)) {
+ NumberValid = true;
+ Number = CurrentInteger;
+ } else {
+ NumberValid = false;
+ while (CurrentToken == TokenSpace)
+ NextToken();
+ if (CurrentToken != TokenEqual)
+ return CAB_STATUS_FAILURE;
+ }
+ } else if (!IsNextToken(TokenEqual, true))
+ return CAB_STATUS_FAILURE;
+
+ if (SetType != stMaxDiskSize) {
+ if (!IsNextToken(TokenString, true))
+ return CAB_STATUS_FAILURE;
+ }
+
+ switch (SetType) {
+ case stDiskLabel:
+ if (!DoDiskLabel(Number, CurrentString))
+ DPRINT(MIN_TRACE, ("Not enough available free memory.\n"));
+ return CAB_STATUS_SUCCESS;
+ case stCabinetName:
+ if (!DoCabinetName(Number, CurrentString))
+ DPRINT(MIN_TRACE, ("Not enough available free memory.\n"));
+ return CAB_STATUS_SUCCESS;
+ case stDiskLabelTemplate:
+ DoDiskLabelTemplate(CurrentString);
+ return CAB_STATUS_SUCCESS;
+ case stCabinetNameTemplate:
+ DoCabinetNameTemplate(CurrentString);
+ return CAB_STATUS_SUCCESS;
+ case stMaxDiskSize:
+ return DoMaxDiskSize(NumberValid, Number);
+ case stInfFileName:
+ DoInfFileName(CurrentString);
+ return CAB_STATUS_SUCCESS;
+ default:
+ return CAB_STATUS_FAILURE;
+ }
+}
+
+
+unsigned long CDFParser::PerformNewCommand()
+/*
+ * FUNCTION: Performs a new disk|cabinet|folder command
+ * RETURNS:
+ * Status of operation
+ */
+{
+ NEWTYPE NewType;
+ unsigned long Status;
+
+ if (!IsNextToken(TokenIdentifier, true))
+ return CAB_STATUS_FAILURE;
+
+ if (strcasecmp(CurrentString, "Disk") == 0)
+ NewType = ntDisk;
+ else if (strcasecmp(CurrentString, "Cabinet") == 0)
+ NewType = ntCabinet;
+ else if (strcasecmp(CurrentString, "Folder") == 0)
+ NewType = ntFolder;
+ else
+ return CAB_STATUS_FAILURE;
+
+ switch (NewType) {
+ case ntDisk:
+ if (DiskCreated) {
+ Status = WriteDisk(true);
+ if (Status == CAB_STATUS_SUCCESS)
+ Status = CloseDisk();
+ if (Status != CAB_STATUS_SUCCESS) {
+ DPRINT(MIN_TRACE, ("Cannot write disk (%d).\n", (unsigned int)Status));
+ return CAB_STATUS_SUCCESS;
+ }
+ DiskCreated = false;
+ }
+
+ Status = NewDisk();
+ if (Status != CAB_STATUS_SUCCESS) {
+ DPRINT(MIN_TRACE, ("Cannot create disk (%d).\n", (unsigned int)Status));
+ return CAB_STATUS_SUCCESS;
+ }
+ DiskCreated = true;
+ SetupNewDisk();
+ return CAB_STATUS_SUCCESS;
+ case ntCabinet:
+ if (DiskCreated) {
+ Status = WriteDisk(true);
+ if (Status == CAB_STATUS_SUCCESS)
+ Status = CloseDisk();
+ if (Status != CAB_STATUS_SUCCESS) {
+ DPRINT(MIN_TRACE, ("Cannot write disk (%d).\n", (unsigned int)Status));
+ return CAB_STATUS_SUCCESS;
+ }
+ DiskCreated = false;
+ }
+
+ Status = NewCabinet();
+ if (Status != CAB_STATUS_SUCCESS) {
+ DPRINT(MIN_TRACE, ("Cannot create cabinet (%d).\n", (unsigned int)Status));
+ return CAB_STATUS_SUCCESS;
+ }
+ DiskCreated = true;
+ SetupNewDisk();
+ return CAB_STATUS_SUCCESS;
+ case ntFolder:
+ Status = NewFolder();
+ ASSERT(Status == CAB_STATUS_SUCCESS);
+ return CAB_STATUS_SUCCESS;
+ default:
+ return CAB_STATUS_FAILURE;
+ }
+}
+
+
+unsigned long CDFParser::PerformInfBeginCommand()
+/*
+ * FUNCTION: Begins inf mode
+ * RETURNS:
+ * Status of operation
+ */
+{
+ InfModeEnabled = true;
+ return CAB_STATUS_SUCCESS;
+}
+
+
+unsigned long CDFParser::PerformInfEndCommand()
+/*
+ * FUNCTION: Begins inf mode
+ * RETURNS:
+ * Status of operation
+ */
+{
+ InfModeEnabled = false;
+ return CAB_STATUS_SUCCESS;
+}
+
+
+unsigned long CDFParser::PerformCommand()
+/*
+ * FUNCTION: Performs a command
+ * RETURNS:
+ * Status of operation
+ */
+{
+ if (strcasecmp(CurrentString, "Set") == 0)
+ return PerformSetCommand();
+ if (strcasecmp(CurrentString, "New") == 0)
+ return PerformNewCommand();
+ if (strcasecmp(CurrentString, "InfBegin") == 0)
+ return PerformInfBeginCommand();
+ if (strcasecmp(CurrentString, "InfEnd") == 0)
+ return PerformInfEndCommand();
+
+ return CAB_STATUS_FAILURE;
+}
+
+
+unsigned long CDFParser::PerformFileCopy()
+/*
+ * FUNCTION: Performs a file copy
+ * RETURNS:
+ * Status of operation
+ */
+{
+ unsigned long Status;
+ unsigned long i, j;
+ char ch;
+ char SrcName[MAX_PATH];
+ char DstName[MAX_PATH];
+ char InfLine[MAX_PATH];
+
+ strcpy(SrcName, "");
+ strcpy(DstName, "");
+
+ i = strlen(CurrentString);
+ while ((i < LineLength) &&
+ ((ch = Line[i]) != ' ') &&
+ (ch != 0x09) &&
+ (ch != ';')) {
+ CurrentString[i] = ch;
+ i++;
+ }
+ CurrentString[i] = '\0';
+ CurrentToken = TokenString;
+ CurrentChar = i + 1;
+ strcpy(SrcName, CurrentString);
+
+ SkipSpaces();
+
+ if (CurrentToken != TokenEnd) {
+ j = strlen(CurrentString); i = 0;
+ while ((CurrentChar + i < LineLength) &&
+ ((ch = Line[CurrentChar + i]) != ' ') &&
+ (ch != 0x09) &&
+ (ch != ';')) {
+ CurrentString[j + i] = ch;
+ i++;
+ }
+ CurrentString[j + i] = '\0';
+ CurrentToken = TokenString;
+ CurrentChar += i + 1;
+ strcpy(DstName, CurrentString);
+ }
+
+ if (!CabinetCreated) {
+
+ DPRINT(MID_TRACE, ("Creating cabinet.\n"));
+
+ Status = NewCabinet();
+ if (Status != CAB_STATUS_SUCCESS) {
+ DPRINT(MIN_TRACE, ("Cannot create cabinet (%d).\n", (unsigned int)Status));
+ printf("Cannot create cabinet.\n");
+ return CAB_STATUS_FAILURE;
+ }
+ CabinetCreated = true;
+
+ DPRINT(MID_TRACE, ("Creating disk.\n"));
+
+ Status = NewDisk();
+ if (Status != CAB_STATUS_SUCCESS) {
+ DPRINT(MIN_TRACE, ("Cannot create disk (%d).\n", (unsigned int)Status));
+ printf("Cannot create disk.\n");
+ return CAB_STATUS_FAILURE;
+ }
+ DiskCreated = true;
+ SetupNewDisk();
+ }
+
+ DPRINT(MID_TRACE, ("Adding file: '%s' destination: '%s'.\n", SrcName, DstName));
+
+ sprintf(InfLine, "%s=%s", GetFileName(SrcName), DstName);
+ WriteInfLine(InfLine);
+
+ Status = AddFile(SrcName);
+ if (Status != CAB_STATUS_SUCCESS) {
+ if (Status == CAB_STATUS_CANNOT_OPEN)
+ printf("File does not exist: %s.\n", SrcName);
+ else if (Status == CAB_STATUS_NOMEMORY)
+ printf("Insufficient memory to add file: %s.\n", SrcName);
+ else
+ printf("Cannot add file: %s (%d).\n", SrcName, Status);
+ return Status;
+ }
+
+ return CAB_STATUS_SUCCESS;
+}
+
+
+void CDFParser::SkipSpaces()
+/*
+ * FUNCTION: Skips any spaces in the current line
+ */
+{
+ NextToken();
+ while (CurrentToken == TokenSpace)
+ NextToken();
+}
+
+
+bool CDFParser::IsNextToken(TOKEN Token, bool NoSpaces)
+/*
+ * FUNCTION: Checks if next token equals Token
+ * ARGUMENTS:
+ * Token = Token to compare with
+ * SkipSp = true if spaces should be skipped
+ * RETURNS:
+ * false if next token is diffrent from Token
+ */
+{
+ if (NoSpaces)
+ SkipSpaces();
+ else
+ NextToken();
+ return (CurrentToken == Token);
+}
+
+
+bool CDFParser::ReadLine()
+/*
+ * FUNCTION: Reads the next line into the line buffer
+ * RETURNS:
+ * true if there is a new line, false if not
+ */
+{
+ unsigned long i, j;
+ char ch;
+
+ if (CurrentOffset >= FileBufferSize)
+ return false;
+
+ i = 0;
+ while (((j = CurrentOffset + i) < FileBufferSize) && (i < 127) &&
+ ((ch = FileBuffer[j]) != 0x0D && (ch = FileBuffer[j]) != 0x0A)) {
+ Line[i] = ch;
+ i++;
+ }
+
+ Line[i] = '\0';
+ LineLength = i;
+
+ if ((FileBuffer[CurrentOffset + i] == 0x0D) && (FileBuffer[CurrentOffset + i + 1] == 0x0A))
+ CurrentOffset++;
+
+ CurrentOffset += i + 1;
+
+ CurrentChar = 0;
+
+ CurrentLine++;
+
+ NextToken();
+
+ return true;
+}
+
+
+void CDFParser::NextToken()
+/*
+ * FUNCTION: Reads the next token from the current line
+ */
+{
+ unsigned long i;
+ char ch = ' ';
+
+ if (CurrentChar >= LineLength) {
+ CurrentToken = TokenEnd;
+ return;
+ }
+
+ switch (Line[CurrentChar]) {
+ case ' ':
+ case 0x09: CurrentToken = TokenSpace;
+ break;
+ case ';': CurrentToken = TokenSemi;
+ break;
+ case '=': CurrentToken = TokenEqual;
+ break;
+ case '.': CurrentToken = TokenPeriod;
+ break;
+ case '\\': CurrentToken = TokenBackslash;
+ break;
+ case '"':
+ i = 0;
+ while ((CurrentChar + i + 1 < LineLength) &&
+ ((ch = Line[CurrentChar + i + 1]) != '"')) {
+ CurrentString[i] = ch;
+ i++;
+ }
+ CurrentString[i] = '\0';
+ CurrentToken = TokenString;
+ CurrentChar += i + 2;
+ return;
+ default:
+ i = 0;
+ while ((CurrentChar + i < LineLength) &&
+ ((ch = Line[CurrentChar + i]) >= '0') && (ch <= '9')) {
+ CurrentString[i] = ch;
+ i++;
+ }
+ if (i > 0) {
+ CurrentString[i] = '\0';
+ CurrentInteger = atoi((char*)CurrentString);
+ CurrentToken = TokenInteger;
+ CurrentChar += i;
+ return;
+ }
+ i = 0;
+ while (((CurrentChar + i < LineLength) &&
+ (((ch = Line[CurrentChar + i]) >= 'a') && (ch <= 'z')) ||
+ ((ch >= 'A') && (ch <= 'Z')) || (ch == '_'))) {
+ CurrentString[i] = ch;
+ i++;
+ }
+ if (i > 0) {
+ CurrentString[i] = '\0';
+ CurrentToken = TokenIdentifier;
+ CurrentChar += i;
+ return;
+ }
+ CurrentToken = TokenEnd;
+ }
+ CurrentChar++;
+}
+
+/* EOF */