Release 960421
Sat Apr 20 23:23:16 1996 Robert Pouliot <krynos@qbc.clic.net>
* [resources/sysres_Fr.rc] [resources/TODO]
Made changes for Choose_Color dialog.
Sat Apr 20 15:43:49 1996 Alexandre Julliard <julliard@lrc.epfl.ch>
* [controls/button.c]
Fixed test that got miscompiled by some old gcc versions.
* [memory/local.c]
Fixed the layout of handle tables so that moveable handle entries
can be freed on LocalFree().
Implemented LocalFlags(), LocalCountFree(), LocalHandleDelta() and
GetHeapSpaces().
* [misc/main.c] [ANNOUNCE]
Update the list of contributors. Please let me know if I forgot
someone.
Fri Apr 19 20:07:20 1996 Frans van Dorsselaer <dorssel@rulhm1.leidenuniv.nl>
* [controls/edit.c] [controls/EDIT.TODO]
Fixed EM_SETHANDLE / WM_CREATE / EDIT_MakeFir() buffer allocation.
Fixed ES_NOHIDESEL / WM_MOUSEMOVE / WM_LBUTTONDOWN implementation.
Added WM_ENABLE implementation (gray text).
Fixed buffer > 32767 bug.
Fixed argument types / typecasting.
Faster selection (re)drawing.
Thu Apr 18 13:38:26 1996 Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>
* [misc/registry.c] [include/winreg.h]
Changed savefile format again to human readable/editable
(UNICODE chars >0xff are specified by \uXXXX, data by XX).
Has now global / local registry databases (including merging them).
HKEY_CLASSES_ROOT == HKEY_LOCAL_MACHINE\\SOFTWARE\\Classes.
HKEY_CURRENT_USER == HKEY_USERS\\<loginname>.
* [misc/comm.c]
Allow " " as COMx: ... spec delimiter too.
(AOL-CD setup.exe tries to initialize modem2 as "9600,x,x x" (can't
remember the x).
Thu Apr 18 09:00:00 1996 Alex Korobka <alex@phm30.pharm.sunysb.edu>
* [windows/mdi.c]
Miscellaneous changes.
* [windows/winpos.c]
Use BitBlt whenever possible in SetWindowPos.
* [windows/painting.c]
Fix incompatibilities with hrgnUpdate being 1.
Wed Apr 17 19:19:22 1996 Albrecht Kleine <kleine@ak.sax.de>
* [misc/commdlg.c]
Many bugfixes in ChooseColor dialog.
Added a user defined dialog title in FileOpen-/FileSave- dialog.
* [misc/commdlg.c][include/commdlg.h]
[if1632/commdlg.spec][if1632/winprocs.spec]
Introduced dialog-, callback- and enum- stub functions
for ChooseFont dialog
Wed Apr 17 19:08:38 1996 Niels de Carpentier <niels@cindy.et.tudelft.nl>
* [objects/metafile.c] [include/metafile.h] [if1632/gdi.spec]
Implemented EnumMetaFile and CopyMetaFile. Removed METAFILE struct.
Implemented META_STRETCHDIB in PlayMetaFileRecord, several bug
fixes.
* [windows/winpos.c]
Don't try to hide the window if it's already hidden.
* [windows/message.c]
Let MSG_PeekHardwareMsg fill the message queue with events if
it's empty.
Wed Apr 17 17:54:04 1996 Tristan Tarrant <tst@sthinc.demon.co.uk>
* [resources/sysres_It.rc]
Updated to support the new CHOOSE_COLOR_DIALOG.
Tue Apr 16 11:50:00 1996 Anand Kumria <akumria@ozemail.com.au>
* [if1632/Makefile] [if1632/relay.c] [if1631/w32sys.spec]
[include/w32sys.h] [include/dlls.h]
[misc/Makefile] [misc/w32sys.c]
W32SYS.DLL partially implemented.
diff --git a/misc/registry.c b/misc/registry.c
index 6483078..7e72b71 100644
--- a/misc/registry.c
+++ b/misc/registry.c
@@ -10,22 +10,32 @@
#include <unistd.h>
#include <ctype.h>
#include <errno.h>
+#include <sys/types.h>
+#include <sys/fcntl.h>
+#include <sys/stat.h>
+#include <pwd.h>
+#include <time.h>
#include "windows.h"
#include "win.h"
#include "winerror.h"
#include "string32.h"
-#include "kernel32.h" /* LPSECURITY_ATTRIBUTES */
#include "stddebug.h"
#include "debug.h"
#include "xmalloc.h"
#include "winreg.h"
-#define SAVE_CLASSES_ROOT "/tmp/reg.classes_root"
-#define SAVE_CURRENT_USER "/tmp/reg.current_user"
-#define SAVE_LOCAL_MACHINE "/tmp/reg.local_machine"
-#define SAVE_USERS "/tmp/reg.users"
+/* FIXME: following defines should be configured global ... */
-static KEYSTRUCT *key_classes_root=NULL; /* windows global values */
+/* NOTE: do not append a /. linux' mkdir() WILL FAIL if you do that */
+#define WINE_PREFIX "/.wine"
+#define SAVE_CURRENT_USER_DEFAULT "/usr/local/etc/wine.userreg"
+ /* relative in ~user/.wine/ */
+#define SAVE_CURRENT_USER "user.reg"
+#define SAVE_LOCAL_MACHINE_DEFAULT "/usr/local/etc/wine.systemreg"
+ /* relative in ~user/.wine/ */
+#define SAVE_LOCAL_MACHINE "system.reg"
+
+static KEYSTRUCT *key_classes_root=NULL; /* windows 3.1 global values */
static KEYSTRUCT *key_current_user=NULL; /* user specific values */
static KEYSTRUCT *key_local_machine=NULL;/* machine specific values */
static KEYSTRUCT *key_users=NULL; /* all users? */
@@ -181,21 +191,46 @@
}
#define FREE_KEY_PATH free(wps[0]);free(wps);
-/**
+/*
* Shell initialisation, allocates keys.
- * FIXME:should set default values too
*/
void
SHELL_Init() {
+ struct passwd *pwd;
+
+ HKEY cl_r_hkey,c_u_hkey;
#define ADD_ROOT_KEY(xx) \
xx = (LPKEYSTRUCT)xmalloc(sizeof(KEYSTRUCT));\
memset(xx,'\0',sizeof(KEYSTRUCT));\
xx->keyname= strdupA2W("<should_not_appear_anywhere>");
- ADD_ROOT_KEY(key_classes_root);
- ADD_ROOT_KEY(key_current_user);
ADD_ROOT_KEY(key_local_machine);
+ if (RegCreateKey(HKEY_LOCAL_MACHINE,"\\SOFTWARE\\Classes",&cl_r_hkey)!=ERROR_SUCCESS) {
+ fprintf(stderr,"couldn't create HKEY_LOCAL_MACHINE\\SOFTWARE\\Classes. This is impossible.\n");
+ exit(1);
+ }
+ key_classes_root = lookup_hkey(cl_r_hkey);
+
ADD_ROOT_KEY(key_users);
+
+#if 0
+ /* FIXME: load all users and their resp. pwd->pw_dir/.wine/user.reg
+ * (later, when a win32 registry editing tool becomes avail.)
+ */
+ while (pwd=getpwent()) {
+ if (pwd->pw_name == NULL)
+ continue;
+ RegCreateKey(HKEY_USERS,pwd->pw_name,&c_u_hkey);
+ RegCloseKey(c_u_hkey);
+ }
+#endif
+ pwd=getpwuid(getuid());
+ if (pwd && pwd->pw_name) {
+ RegCreateKey(HKEY_USERS,pwd->pw_name,&c_u_hkey);
+ key_current_user = lookup_hkey(c_u_hkey);
+ } else {
+ ADD_ROOT_KEY(key_current_user);
+ }
ADD_ROOT_KEY(key_performance_data);
ADD_ROOT_KEY(key_current_config);
ADD_ROOT_KEY(key_dyn_data);
@@ -211,96 +246,83 @@
* old registry database files.
*
* Global:
- * DWORD version
- * DWORD nrofkeys
- * KEY keys[nrofkeys]
- *
- * KEY:
- * USTRING name
- * USTRING class
- * DWORD nrofvalues
- * VALUE vals[nrofvalues]
- * DWORD nrofsubkeys
- * KEY keys[nrofsubkeys]
- *
- * Value:
- * USTRING name
- * DWORD type
- * DWORD len
- * BYTE data[len]
- *
- * USTRING:
- * DWORD len (len==0 means data=NULL)
- * BYTE data[len]
+ * "WINE REGISTRY Version %d"
+ * subkeys....
+ * Subkeys:
+ * keyname
+ * valuename=lastmodified,type,data
+ * ...
+ * subkeys
+ * ...
+ * keyname,valuename,stringdata:
+ * the usual ascii characters from 0x00-0xff (well, not 0x00)
+ * and \uXXXX as UNICODE value XXXX with XXXX>0xff
+ * ( "=\\\t" escaped in \uXXXX form.)
+ * type,lastmodified:
+ * int
*
- *
- * All _write_XXX and _read_XXX functions return !0 on sucess.
+ * FIXME: doesn't save 'class' (what does it mean anyway?), nor flags.
*/
+static void
+_write_USTRING(FILE *F,LPWSTR wstr,int escapeeq) {
+ LPWSTR s;
+ int doescape;
-static int
-_write_DWORD(FILE *F,DWORD dw) {
- return fwrite(&dw,sizeof(dw),1,F);
-}
-
-static int
-_write_USTRING(FILE *F,LPWSTR str) {
- int len;
-
- if (str==NULL) {
- if (!_write_DWORD(F,0))
- return 0;
- } else {
- len=strlenW(str)*2+2;
-
- if (!_write_DWORD(F,len))
- return 0;
- if (!fwrite(str,len,1,F))
- return 0;
+ if (wstr==NULL) {
+ /* FIXME: NULL equals empty string... I hope
+ * the empty string isn't a valid valuename
+ */
+ return;
}
- return 1;
+ s=wstr;
+ while (*s) {
+ doescape=0;
+ if (*s>0xff)
+ doescape = 1;
+ if (*s=='\n')
+ doescape = 1;
+ if (escapeeq && *s=='=')
+ doescape = 1;
+ if (*s=='\\')
+ fputc(*s,F); /* if \\ than put it twice. */
+ if (doescape)
+ fprintf(F,"\\u%04x",*((unsigned short*)s));
+ else
+ fputc(*s,F);
+ s++;
+ }
}
-
static int
-_do_save_subkey(FILE *F,LPKEYSTRUCT lpkey) {
+_do_save_subkey(FILE *F,LPKEYSTRUCT lpkey,int level) {
LPKEYSTRUCT lpxkey;
- int nrofkeys;
- int i;
-
- nrofkeys= 0;
- lpxkey = lpkey;
- while (lpxkey) {
- if (!(lpxkey->flags & REG_OPTION_VOLATILE))
- nrofkeys++;
- lpxkey = lpxkey->next;
- }
- if (!_write_DWORD(F,nrofkeys))
- return 0;
+ int i,tabs,j;
lpxkey = lpkey;
while (lpxkey) {
if (!(lpxkey->flags & REG_OPTION_VOLATILE)) {
- if (!_write_USTRING(F,lpxkey->keyname))
- return 0;
- if (!_write_USTRING(F,lpxkey->class))
- return 0;
- if (!_write_DWORD(F,lpxkey->nrofvalues))
- return 0;
+ for (tabs=level;tabs--;)
+ fputc('\t',F);
+ _write_USTRING(F,lpxkey->keyname,1);
+ fputs("\n",F);
for (i=0;i<lpxkey->nrofvalues;i++) {
LPKEYVALUE val=lpxkey->values+i;
- if (!_write_USTRING(F,val->name))
- return 0;
- if (!_write_DWORD(F,val->type))
- return 0;
- if (!_write_DWORD(F,val->len))
- return 0;
- if (!fwrite(val->data,val->len,1,F))
- return 0;
+ for (tabs=level+1;tabs--;)
+ fputc('\t',F);
+ _write_USTRING(F,val->name,0);
+ fputc('=',F);
+ fprintf(F,"%ld,%ld,",val->type,val->lastmodified);
+ if ((1<<val->type) & UNICONVMASK)
+ _write_USTRING(F,(LPWSTR)val->data,0);
+ else
+ for (j=0;j<val->len;j++)
+ fprintf(F,"%02x",*((unsigned char*)val->data+j));
+ fputs("\n",F);
}
/* descend recursively */
- if (!_do_save_subkey(F,lpxkey->nextsub))
+ if (!_do_save_subkey(F,lpxkey->nextsub,level+1))
return 0;
}
lpxkey=lpxkey->next;
@@ -310,16 +332,15 @@
static int
_do_savesubreg(FILE *F,LPKEYSTRUCT lpkey) {
- if (!_write_DWORD(F,REGISTRY_SAVE_VERSION))
- return 0;
- return _do_save_subkey(F,lpkey->nextsub);
+ fprintf(F,"WINE REGISTRY Version %d\n",REGISTRY_SAVE_VERSION);
+ return _do_save_subkey(F,lpkey->nextsub,0);
}
static void
_SaveSubReg(LPKEYSTRUCT lpkey,char *fn) {
FILE *F;
- F=fopen(fn,"wb");
+ F=fopen(fn,"w");
if (F==NULL) {
fprintf(stddeb,__FILE__":_SaveSubReg:Couldn't open %s for writing: %s\n",
fn,strerror(errno)
@@ -337,105 +358,307 @@
void
SHELL_SaveRegistry() {
- _SaveSubReg(key_classes_root,SAVE_CLASSES_ROOT);
- _SaveSubReg(key_current_user,SAVE_CURRENT_USER);
- _SaveSubReg(key_local_machine,SAVE_LOCAL_MACHINE);
- _SaveSubReg(key_users,SAVE_USERS);
+ char *fn;
+ struct passwd *pwd;
+
+ pwd=getpwuid(getuid());
+ if (pwd!=NULL && pwd->pw_dir!=NULL) {
+ fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_CURRENT_USER)+2);
+ strcpy(fn,pwd->pw_dir);
+ strcat(fn,WINE_PREFIX);
+ /* create the directory. don't care about errorcodes. */
+ mkdir(fn,0755); /* drwxr-xr-x */
+ strcat(fn,"/");
+ strcat(fn,SAVE_CURRENT_USER);
+ _SaveSubReg(key_current_user,fn);
+ free(fn);
+ fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_LOCAL_MACHINE)+1);
+ strcpy(fn,pwd->pw_dir);
+ strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_MACHINE);
+ _SaveSubReg(key_local_machine,fn);
+ free(fn);
+ } else {
+ fprintf(stderr,"SHELL_SaveRegistry:failed to get homedirectory of UID %d.\n",getuid());
+ }
}
/************************ LOAD Registry Function ****************************/
-/* FIXME:
- * Currently overwrites any old registry data (leaks it away)
- * should better be a merge, or ?
+/* reads a line including dynamically enlarging the readbuffer and throwing
+ * away comments
*/
+static int
+_read_line(FILE *F,char **buf,int *len) {
+ char *s,*curread;
+ int mylen,curoff;
-static int
-_read_DWORD(FILE *F,DWORD *dw) {
- return fread(dw,sizeof(DWORD),1,F);
-}
-
-static int
-_read_USTRING(FILE *F,LPWSTR *str) {
- DWORD len;
-
- if (!_read_DWORD(F,&len))
- return 0;
- if (len==0) {
- *str=NULL;
- return 1;
- }
- *str=xmalloc(len);
- return fread(*str,len,1,F);
-}
-
-static int
-_do_load_subkey(FILE *F,LPKEYSTRUCT lpkey) {
- DWORD howmuch;
- LPKEYSTRUCT *lplpkey,lpxkey;
- int i;
-
- if (!_read_DWORD(F,&howmuch))
- return 0;
-
- /* no subkeys? */
- if (howmuch==0)
- return 1;
-
- lplpkey = &(lpkey->nextsub);
- while (howmuch--) {
- *lplpkey= (LPKEYSTRUCT)xmalloc(sizeof(KEYSTRUCT));
- memset(*lplpkey,'\0',sizeof(KEYSTRUCT));
- lpxkey = *lplpkey;
- if (!_read_USTRING(F,&(lpxkey->keyname)))
- return 0;
- if (!_read_USTRING(F,&(lpxkey->class)))
- return 0;
- if (!_read_DWORD(F,&(lpxkey->nrofvalues)))
- return 0;
- if (lpxkey->nrofvalues) {
- lpxkey->values = (LPKEYVALUE)xmalloc(
- lpxkey->nrofvalues*sizeof(KEYVALUE)
- );
- for (i=0;i<lpxkey->nrofvalues;i++) {
- LPKEYVALUE val=lpxkey->values+i;
-
- memset(val,'\0',sizeof(KEYVALUE));
- if (!_read_USTRING(F,&(val->name)))
- return 0;
- if (!_read_DWORD(F,&(val->type)))
- return 0;
- if (!_read_DWORD(F,&(val->len)))
- return 0;
- val->data = (LPBYTE)xmalloc(val->len);
- if (!fread(val->data,val->len,1,F))
- return 0;
+ curread = *buf;
+ mylen = *len;
+ **buf = '\0';
+ while (1) {
+ while (1) {
+ s=fgets(curread,mylen,F);
+ if (s==NULL)
+ return 0; /* EOF */
+ if (NULL==(s=strchr(curread,'\n'))) {
+ /* buffer wasn't large enough */
+ curoff = strlen(*buf);
+ *buf = xrealloc(*buf,*len*2);
+ curread = *buf + curoff;
+ mylen = *len; /* we filled up the buffer and
+ * got new '*len' bytes to fill
+ */
+ *len = *len * 2;
+ } else {
+ *s='\0';
+ break;
}
}
- if (!_do_load_subkey(F,*lplpkey))
- return 0;
- lplpkey = &(lpxkey->next);
+ /* throw away comments */
+ if (**buf=='#' || **buf==';') {
+ curread = *buf;
+ mylen = *len;
+ continue;
+ }
+ if (s) /* got end of line */
+ break;
+ }
+ return 1;
+}
+
+/* converts a char* into a UNICODE string (up to a special char)
+ * and returns the position exactly after that string
+ */
+static char*
+_read_USTRING(char *buf,LPWSTR *str) {
+ char *s;
+ LPWSTR ws;
+
+ /* read up to "=" or "\0" or "\n" */
+ s = buf;
+ if (*s == '=') {
+ /* empty string is the win3.1 default value(NULL)*/
+ *str = NULL;
+ return s;
+ }
+ *str = (LPWSTR)xmalloc(2*strlen(buf)+2);
+ ws = *str;
+ while (*s && (*s!='\n') && (*s!='=')) {
+ if (*s!='\\')
+ *ws++=*((unsigned char*)s++);
+ else {
+ s++;
+ if (*s=='\\') {
+ *ws+='\\';
+ s++;
+ continue;
+ }
+ if (*s!='u') {
+ fprintf(stderr,"_read_USTRING:Non unicode escape sequence \\%c found in |%s|\n",*s,buf);
+ *ws++='\\';
+ *ws++=*s++;
+ } else {
+ char xbuf[5];
+ int wc;
+
+ s++;
+ memcpy(xbuf,s,4);xbuf[4]='\0';
+ if (!sscanf(xbuf,"%x",&wc))
+ fprintf(stderr,"_read_USTRING:strange escape sequence %s found in |%s|\n",xbuf,buf);
+ s+=4;
+ *ws++ =(unsigned short)wc;
+ }
+ }
+ }
+ *ws = 0;
+ ws = *str;
+ *str = strdupW(*str);
+ free(ws);
+ return s;
+}
+
+static int
+_do_load_subkey(FILE *F,LPKEYSTRUCT lpkey,int level,char **buf,int *buflen) {
+ LPKEYSTRUCT lpxkey,*lplpkey;
+ int i;
+ char *s;
+ LPWSTR name;
+
+ /* good. we already got a line here ... so parse it */
+ lpxkey = NULL;
+ while (1) {
+ i=0;s=*buf;
+ while (*s=='\t') {
+ s++;
+ i++;
+ }
+ if (i>level) {
+ if (lpxkey==NULL) {
+ fprintf(stderr,"_do_load_subkey:Got a subhierarchy without resp. key?\n");
+ return 0;
+ }
+ _do_load_subkey(F,lpxkey,level+1,buf,buflen);
+ continue;
+ }
+ /* let the caller handle this line */
+ if (i<level || **buf=='\0')
+ return 1;
+ /* good. this is one line for us.
+ * it can be: a value or a keyname. Parse the name first
+ */
+ s=_read_USTRING(s,&name);
+
+ /* switch() default: hack to avoid gotos */
+ switch (0) {
+ default:
+ if (*s=='\0') {
+ /* this is a new key
+ * look for the name in the already existing keys
+ * on this level.
+ */
+ lplpkey= &(lpkey->nextsub);
+ lpxkey = *lplpkey;
+ while (lpxkey) {
+ if (!strcmpW(lpxkey->keyname,name))
+ break;
+ lplpkey = &(lpxkey->next);
+ lpxkey = *lplpkey;
+ }
+ if (lpxkey==NULL) {
+ /* we have no key with that name yet. allocate
+ * it.
+ */
+ *lplpkey = (LPKEYSTRUCT)xmalloc(sizeof(KEYSTRUCT));
+ lpxkey = *lplpkey;
+ memset(lpxkey,'\0',sizeof(KEYSTRUCT));
+ lpxkey->keyname = name;
+ } else {
+ /* already got it. we just remember it in
+ * 'lpxkey'
+ */
+ free(name);
+ }
+ } else {
+ LPKEYVALUE val=NULL;
+ LPBYTE data;
+ int len,lastmodified,type;
+
+ if (*s!='=') {
+ fprintf(stderr,"_do_load_subkey:unexpected character: %c\n",*s);
+ break;
+ }
+ /* good. this looks like a value to me */
+ s++;
+ for (i=0;i<lpkey->nrofvalues;i++) {
+ val=lpkey->values+i;
+ if (name==NULL) {
+ if (val->name==NULL)
+ break;
+ } else {
+ if ( val->name!=NULL &&
+ !strcmpW(val->name,name)
+ )
+ break;
+ }
+ }
+ if (i==lpkey->nrofvalues) {
+ lpkey->values = xrealloc(
+ lpkey->values,
+ (++lpkey->nrofvalues)*sizeof(KEYVALUE)
+ );
+ val=lpkey->values+i;
+ memset(val,'\0',sizeof(KEYVALUE));
+ val->name = name;
+ } else {
+ /* value already exists, free name */
+ free(name);
+ }
+ if (2!=sscanf(s,"%d,%d,",&type,&lastmodified)) {
+ fprintf(stderr,"_do_load_subkey: haven't understood possible value in |%s|, skipping.\n",*buf);
+ break;
+ }
+ /* skip the 2 , */
+ s=strchr(s,',');s++;
+ s=strchr(s,',');s++;
+ if ((1<<type) & UNICONVMASK) {
+ s=_read_USTRING(s,(LPWSTR*)&data);
+ if (data)
+ len = strlenW((LPWSTR)data)*2+2;
+ else
+ len = 0;
+ } else {
+ len=strlen(s)/2;
+ data = (LPBYTE)xmalloc(len+1);
+ for (i=0;i<len;i++) {
+ data[i]=0;
+ if (*s>='0' && *s<='9')
+ data[i]=(*s-'0')<<4;
+ if (*s>='a' && *s<='f')
+ data[i]=(*s-'a')<<4;
+ if (*s>='A' && *s<='F')
+ data[i]=(*s-'A')<<4;
+ s++;
+ if (*s>='0' && *s<='9')
+ data[i]|=*s-'0';
+ if (*s>='a' && *s<='f')
+ data[i]|=*s-'a';
+ if (*s>='A' && *s<='F')
+ data[i]|=*s-'A';
+ s++;
+ }
+ }
+ if (val->lastmodified<lastmodified) {
+ val->lastmodified=lastmodified;
+ val->type = type;
+ val->len = len;
+ if (val->data)
+ free(val->data);
+ val->data = data;
+ } else {
+ free(data);
+ }
+ }
+ }
+ /* read the next line */
+ if (!_read_line(F,buf,buflen))
+ return 1;
}
return 1;
}
static int
_do_loadsubreg(FILE *F,LPKEYSTRUCT lpkey) {
- DWORD ver;
+ int ver;
+ char *buf;
+ int buflen;
- if (!_read_DWORD(F,&ver))
- return 0;
- if (ver!=REGISTRY_SAVE_VERSION) {
- dprintf_reg(stddeb,__FILE__":_do_loadsubreg:Old format (%lx) registry found, ignoring it.\n",ver);
+ buf=xmalloc(10);buflen=10;
+ if (!_read_line(F,&buf,&buflen)) {
+ free(buf);
return 0;
}
- if (!_do_load_subkey(F,lpkey)) {
+ if (!sscanf(buf,"WINE REGISTRY Version %d",&ver)) {
+ free(buf);
+ return 0;
+ }
+ if (ver!=REGISTRY_SAVE_VERSION) {
+ dprintf_reg(stddeb,__FILE__":_do_loadsubreg:Old format (%d) registry found, ignoring it. (buf was %s).\n",ver,buf);
+ free(buf);
+ return 0;
+ }
+ if (!_read_line(F,&buf,&buflen)) {
+ free(buf);
+ return 0;
+ }
+ if (!_do_load_subkey(F,lpkey,0,&buf,&buflen)) {
+ free(buf);
/* FIXME: memory leak on failure to read registry ...
* But this won't happen very often.
*/
lpkey->nextsub=NULL;
return 0;
}
+ free(buf);
return 1;
}
@@ -459,18 +682,40 @@
void
SHELL_LoadRegistry() {
+ char *fn;
+ struct passwd *pwd;
+
if (key_classes_root==NULL)
SHELL_Init();
- _LoadSubReg(key_classes_root,SAVE_CLASSES_ROOT);
- _LoadSubReg(key_current_user,SAVE_CURRENT_USER);
- _LoadSubReg(key_local_machine,SAVE_LOCAL_MACHINE);
- _LoadSubReg(key_users,SAVE_USERS);
+ /* load the machine-wide defaults first */
+ _LoadSubReg(key_current_user,SAVE_CURRENT_USER_DEFAULT);
+ _LoadSubReg(key_local_machine,SAVE_LOCAL_MACHINE_DEFAULT);
+
+ /* load the user saved registry. overwriting only newer entries */
+ pwd=getpwuid(getuid());
+ if (pwd!=NULL && pwd->pw_dir!=NULL) {
+ fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_CURRENT_USER)+1);
+ strcpy(fn,pwd->pw_dir);
+ strcat(fn,WINE_PREFIX"/"SAVE_CURRENT_USER);
+ _LoadSubReg(key_current_user,fn);
+ free(fn);
+ fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_LOCAL_MACHINE)+1);
+ strcpy(fn,pwd->pw_dir);
+ strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_MACHINE);
+ _LoadSubReg(key_local_machine,fn);
+ free(fn);
+ } else {
+ fprintf(stderr,"SHELL_LoadRegistry:failed to get homedirectory of UID %d.\n",getuid());
+ }
+ /* FIXME: load all users and their resp. pwd->pw_dir/.wine/user.reg
+ * (later, when a win32 registry editing tool becomes avail.)
+ */
}
/********************* API FUNCTIONS ***************************************/
/*
- * Open Keys.
+ * Open Keys.
*
* All functions are stubs to RegOpenKeyExW where all the
* magic happens.
@@ -508,6 +753,7 @@
}
split_keypath(lpszSubKey,&wps,&wpc);
i = 0;
+ while ((i<wpc) && (wps[i][0]=='\0')) i++;
lpxkey = lpNextKey;
while (i<wpc) {
lpxkey=lpNextKey->nextsub;
@@ -647,6 +893,7 @@
}
split_keypath(lpszSubKey,&wps,&wpc);
i = 0;
+ while ((i<wpc) && (wps[i][0]=='\0')) i++;
lpxkey = lpNextKey;
while (i<wpc) {
lpxkey=lpNextKey->nextsub;
@@ -1131,6 +1378,7 @@
if (lpkey->values[i].data !=NULL)
free(lpkey->values[i].data);
lpkey->values[i].data = (LPBYTE)xmalloc(cbData);
+ lpkey->values[i].lastmodified = time(NULL);
memcpy(lpkey->values[i].data,lpbData,cbData);
return SHELL_ERROR_SUCCESS;
}