mirror of
https://github.com/kevinbentley/Descent3.git
synced 2025-01-22 19:55:23 +00:00
428 lines
8.7 KiB
C++
428 lines
8.7 KiB
C++
#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;
|
|
}
|
|
|