Descent3/mac/MACREGISTRY.CPP

428 lines
8.7 KiB
C++
Raw Normal View History

2024-04-16 03:43:29 +00:00
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <ctype.h>
#include "registry.h"
#include "mono.h"
//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(char *str)
{
currentkey = root = NULL;
strcpy(name,str);
}
CRegistry::~CRegistry()
{
Destroy();
}
void CRegistry::GetSystemName(char *n)
{
strcpy(n,name);
}
void CRegistry::SetSystemName(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[258];
sprintf(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;
sprintf(buffer,"\"%s\"=\"%s\"\n",record->name,st);
}break;
case REGT_DWORD:
{
dw = (int *)record->data;
sprintf(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,"Unable to import %s\n",name));
return false;
}
mprintf((0,"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);
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(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(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(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(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(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;
}