/* * Descent 3 * Copyright (C) 2024 Parallax Software * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . --- HISTORICAL COMMENTS FOLLOW --- * $Logfile: /DescentIII/Main/linux/registry.cpp $ * $Revision: 1.4 $ * $Date: 2004/02/25 00:04:06 $ * $Author: ryan $ * * Linux registry routines * * $Log: registry.cpp,v $ * Revision 1.4 2004/02/25 00:04:06 ryan * Removed loki_utils dependency and ported to MacOS X (runs, but incomplete). * * Revision 1.3 2000/06/24 01:15:15 icculus * patched to compile. * * Revision 1.2 2000/04/28 20:19:29 icculus * Minor mprintf update * * Revision 1.1.1.1 2000/04/18 00:00:39 icculus * initial checkin * * * 8 8/20/99 1:59p Jeff * removed mprintfs... * * 7 7/14/99 9:09p Jeff * added comment header * * $NoKeywords: $ */ #include #include #include #include // #include "local_malloc.h" #include "registry.h" #include "mono.h" #if defined(_WIN32) #define strcasecmp stricmp #endif // Convert a string that represents a hex value into an int int hextoi(char *p) { int value = 0; while ((p) && (*p) && isalnum(*p)) { *p = toupper(*p); if ((*p >= '0') && (*p <= '9')) value = (value * 16) + ((*p) - '0'); else if ((*p >= 'A') && (*p <= 'F')) value = (value * 16) + ((*p) - 'A'); else return value; p++; } return value; } // Removes whitespace from the start of the given string. // Returns a pointer to the first non-white character char *SkipWhite(char *p) { while (isspace(*p)) p++; return p; } // Parses a quoted string // Returns true if got string ok, else false char *ParseString(char *p, char *buf, int bufsize, char sdelim, char edelim) { char *save_p; p = SkipWhite(p); save_p = p; if (*p != sdelim) { return NULL; } else p++; // skip initial quote // Copy chars until endquote or out of space while (*p && (*p != edelim) && --bufsize) *buf++ = *p++; // Check for buffer overflow if (bufsize <= 0) { return NULL; } // Check for missing endquote if (!*p) { return NULL; } // Write terminator *buf = 0; // Return new pointer (move over a char for end quote) return p + 1; } // Parses a sequence of non-space characters char *ParseToken(char *p, char *buf, int bufsize) { char *save_p; p = SkipWhite(p); save_p = p; while (!isspace(*p) && (*p != ',') && *p && --bufsize) *buf++ = *p++; *buf = 0; // Check for buffer overflow if (bufsize <= 0) { return NULL; } return p; } #define PARSE_KEY(buf) \ do { \ ptr = ParseString(ptr, buf, sizeof(buf), '[', ']'); \ } while (0) #define PARSE_STRING(buf) \ do { \ ptr = ParseString(ptr, buf, sizeof(buf), '"', '"'); \ } while (0) #define PARSE_TOKEN(buf) \ do { \ ptr = ParseToken(ptr, buf, sizeof(buf)); \ } while (0) CRegistry::CRegistry(const char *str) { currentkey = root = NULL; strcpy(name, str); } CRegistry::~CRegistry() { Destroy(); } void CRegistry::GetSystemName(char *n) { strcpy(n, name); } void CRegistry::SetSystemName(const char *n) { strcpy(name, n); } void CRegistry::Destroy(void) { tKey *curr, *next; curr = next = root; while (curr) { next = curr->next; DestroyKey(curr); curr = next; } root = NULL; } void CRegistry::DestroyKey(tKey *key) { tRecord *curr, *next; curr = next = key->records; while (curr) { next = curr->next; DestroyRecord(curr); curr = next; } free(key); } void CRegistry::DestroyRecord(tRecord *record) { if (record->data) { free(record->data); record->data = NULL; } free(record); } void CRegistry::Export() { tKey *curr, *next; curr = next = root; FILE *file; file = fopen(name, "wt"); if (!file) return; while (curr) { next = curr->next; ExportKey(curr, file); curr = next; } fclose(file); } void CRegistry::ExportKey(tKey *key, FILE *file) { tRecord *curr, *next; curr = next = key->records; // write out name char buffer[256+16]; snprintf(buffer, sizeof(buffer), "[%s]\n", key->name); fputs(buffer, file); while (curr) { next = curr->next; ExportRecord(curr, file); curr = next; } } void CRegistry::ExportRecord(tRecord *record, FILE *file) { int *dw; char *st; char buffer[512]; switch (record->type) { case REGT_STRING: { st = (char *)record->data; snprintf(buffer, sizeof(buffer), "\"%s\"=\"%s\"\n", record->name, st); } break; case REGT_DWORD: { dw = (int *)record->data; snprintf(buffer, sizeof(buffer), "\"%s\"=dword:%X\n", record->name, *dw); } break; }; fputs(buffer, file); } bool CRegistry::Import() { char buffer[500]; char newbuff[500]; FILE *file; char *ptr; file = fopen(name, "rt"); if (!file) { mprintf(0, "REGISTRY: Unable to import %s\n", name); return false; } mprintf(0, "REGISTRY: Importing %s\n", name); Destroy(); bool oktocreate; // loop till we are done while (!feof(file)) { oktocreate = true; char type = REGT_STRING; // read in the string fgets(buffer, 500, file); ptr = buffer; if (feof(file)) // we are at the end of the file so there isn't data to continue oktocreate = false; // see what we read, a key or record, if the first character is a [ than a key " is record if (oktocreate) { if (buffer[0] == '[') { // Create a key! PARSE_KEY(newbuff); // mprintf(0,"Found Key: |%s|\n",newbuff); CreateKey(newbuff); } else if (buffer[0] == '\"') { // Create a record // see what type of record by looking at whats after the = char *p; p = buffer; bool done = false; type = REGT_STRING; while (!done) { if ((!p) || (!*p)) done = true; if ((p) && (*p == '=')) { if (*(p + 1) == 'd') type = REGT_DWORD; else type = REGT_STRING; done = true; } p++; } // now we "SHOULD" know the type, parse the info char data[300]; int idata; switch (type) { case REGT_STRING: PARSE_STRING(newbuff); // rcg06212000 getting a NULL ptr in here...added a check. if (ptr == NULL) continue; ptr++; // blow by = PARSE_STRING(data); if (!CreateRecord(newbuff, REGT_STRING, data)) { // mprintf(0,"Unable to create String record: %s\n",newbuff); } else { // mprintf(0,"Created String record %s = %s\n",newbuff,data); } break; case REGT_DWORD: PARSE_STRING(newbuff); ptr += 7; // blow by =dword: PARSE_TOKEN(data); idata = hextoi(data); if (!CreateRecord(newbuff, REGT_DWORD, &idata)) { // mprintf(0,"Unable to create dword record: %s\n",newbuff); } else { // mprintf(0,"Created dword record %s = %X\n",newbuff,idata); } break; }; } else { // mprintf(0,"Expected [ or \"\n"); } } } fclose(file); return true; } void CRegistry::CreateKey(const char *name) { tKey *curr; if (LookupKey(name)) { // mprintf(0,"Key: %s already exists\n",name); return; } if (!root) { root = (tKey *)malloc(sizeof(tKey)); if (!root) return; curr = root; } else { curr = root; while (curr->next) { curr = curr->next; } curr->next = (tKey *)malloc(sizeof(tKey)); if (!curr->next) return; curr = curr->next; } curr->next = NULL; strcpy(curr->name, name); curr->records = NULL; currentkey = curr; } bool CRegistry::LookupKey(const char *name) { tKey *curr; curr = root; while (curr) { if (!strcasecmp(name, curr->name)) { // found a match currentkey = curr; return true; } curr = curr->next; } return false; } tRecord *CRegistry::LookupRecord(const char *record, void *data) { if (!currentkey) return NULL; tRecord *curr; curr = currentkey->records; while (curr) { if (!strcasecmp(record, curr->name)) { // found the record switch (curr->type) { case REGT_STRING: char *st; st = (char *)curr->data; strcpy((char *)data, st); break; case REGT_DWORD: int *dw; dw = (int *)curr->data; *((int *)data) = *dw; break; }; return curr; } curr = curr->next; } return NULL; } int CRegistry::GetDataSize(const char *record) { if (!currentkey) return false; tRecord *curr; curr = currentkey->records; while (curr) { if (!strcasecmp(record, curr->name)) { // found the record switch (curr->type) { case REGT_STRING: return strlen((char *)curr->data) + 1; break; case REGT_DWORD: return sizeof(int); break; }; return 0; } curr = curr->next; } return 0; } bool CRegistry::CreateRecord(const char *name, char type, void *data) { if (!currentkey) return false; tRecord *curr; // first see if the record exists under this key int datasize = GetDataSize(name); if (datasize) { char *olddata = (char *)malloc(datasize); if (olddata) { curr = LookupRecord(name, olddata); if (curr) { // ok we have an old value, replace it! // mprintf(0,"Replacing %s\n",name); if (curr->data) free(curr->data); free(olddata); curr->type = type; switch (type) { case REGT_STRING: curr->data = malloc(strlen((char *)data) + 1); strcpy((char *)curr->data, (char *)data); break; case REGT_DWORD: curr->data = malloc(sizeof(int)); *((int *)curr->data) = *((int *)data); break; } return true; } } } // it is a new record if (currentkey->records) { curr = currentkey->records; while (curr->next) curr = curr->next; curr->next = (tRecord *)malloc(sizeof(tRecord)); if (!curr->next) return false; curr = curr->next; } else { currentkey->records = (tRecord *)malloc(sizeof(tRecord)); if (!currentkey->records) return false; curr = currentkey->records; } curr->next = NULL; strcpy(curr->name, name); switch (type) { case REGT_STRING: curr->data = malloc(strlen((char *)data) + 1); curr->type = REGT_STRING; strcpy((char *)curr->data, (char *)data); break; case REGT_DWORD: curr->data = malloc(sizeof(int)); curr->type = REGT_DWORD; *((int *)curr->data) = *((int *)data); break; }; return true; }