4 * Copyright 1996 Marcus Meissner
17 #include "kernel32.h" /* LPSECURITY_ATTRIBUTES */
23 #define SAVE_CLASSES_ROOT "/tmp/reg.classes_root"
24 #define SAVE_CURRENT_USER "/tmp/reg.current_user"
25 #define SAVE_LOCAL_MACHINE "/tmp/reg.local_machine"
26 #define SAVE_USERS "/tmp/reg.users"
28 static KEYSTRUCT *key_classes_root=NULL; /* windows global values */
29 static KEYSTRUCT *key_current_user=NULL; /* user specific values */
30 static KEYSTRUCT *key_local_machine=NULL;/* machine specific values */
31 static KEYSTRUCT *key_users=NULL; /* all users? */
33 /* dynamic, not saved */
34 static KEYSTRUCT *key_performance_data=NULL;
35 static KEYSTRUCT *key_current_config=NULL;
36 static KEYSTRUCT *key_dyn_data=NULL;
38 /* what valuetypes do we need to convert? */
39 #define UNICONVMASK ((1<<REG_SZ)|(1<<REG_MULTI_SZ)|(1<<REG_EXPAND_SZ))
41 #define strdupA2W(x) STRING32_DupAnsiToUni(x)
42 #define strdupW2A(x) STRING32_DupUniToAnsi(x)
43 #define strdupW(x) STRING32_strdupW(x)
44 #define strcmpW(a,b) STRING32_lstrcmpW(a,b)
45 #define strcmpniW(a,b) STRING32_lstrcmpniW(a,b)
46 #define strchrW(a,c) STRING32_lstrchrW(a,c)
47 #define strlenW(a) STRING32_UniLen(a)
48 #define strcpyWA(a,b) STRING32_UniToAnsi(a,b)
50 static struct openhandle {
55 static int nrofopenhandles=0;
56 static int currenthandle=1;
59 add_handle(HKEY hkey,LPKEYSTRUCT lpkey,REGSAM accessmask) {
62 for (i=0;i<nrofopenhandles;i++) {
63 if (openhandles[i].lpkey==lpkey) {
64 dprintf_reg(stddeb,"add_handle:Tried to add %p twice!\n",lpkey);
66 if (openhandles[i].hkey==hkey) {
67 dprintf_reg(stddeb,"add_handle:Tried to add %lx twice!\n",(LONG)hkey);
70 openhandles=xrealloc( openhandles,
71 sizeof(struct openhandle)*(nrofopenhandles+1)
73 openhandles[i].lpkey = lpkey;
74 openhandles[i].hkey = hkey;
75 openhandles[i].accessmask= accessmask;
80 get_handle(HKEY hkey) {
83 for (i=0;i<nrofopenhandles;i++)
84 if (openhandles[i].hkey==hkey)
85 return openhandles[i].lpkey;
86 dprintf_reg(stddeb,"get_handle:Didn't find handle %lx?\n",(LONG)hkey);
91 remove_handle(HKEY hkey) {
94 for (i=0;i<nrofopenhandles;i++)
95 if (openhandles[i].hkey==hkey)
97 if (i==nrofopenhandles) {
98 dprintf_reg(stddeb,"remove_handle:Didn't find handle %lx?\n",hkey);
101 memcpy( openhandles+i,
103 sizeof(struct openhandle)*(nrofopenhandles-i-1)
105 openhandles=xrealloc(openhandles,sizeof(struct openhandle)*(nrofopenhandles-1));
111 /* debug function, converts a unicode into a static memory area
112 * (sub for using two static strings, in case we need them in a single call)
115 W2C(LPCWSTR x,int sub) {
116 static LPSTR unicodedebug[2]={NULL,NULL};
119 if (sub!=0 && sub!=1)
120 return "<W2C:bad sub>";
121 if (unicodedebug[sub]) free(unicodedebug[sub]);
122 unicodedebug[sub] = strdupW2A(x);
123 return unicodedebug[sub];
127 lookup_hkey(HKEY hkey) {
131 case HKEY_CLASSES_ROOT:
132 return key_classes_root;
133 case HKEY_CURRENT_USER:
134 return key_current_user;
135 case HKEY_LOCAL_MACHINE:
136 return key_local_machine;
139 case HKEY_PERFORMANCE_DATA:
140 return key_performance_data;
143 case HKEY_CURRENT_CONFIG:
144 return key_current_config;
146 dprintf_reg(stddeb,"lookup_hkey(%lx), special key!\n",
149 return get_handle(hkey);
155 * splits the unicode string 'wp' into an array of strings.
156 * the array is allocated by this function.
157 * the number of components will be stored in 'wpc'
158 * Free the array using FREE_KEY_PATH
161 split_keypath(LPCWSTR wp,LPWSTR **wpv,int *wpc) {
167 for (i=0;ws[i];i++) {
174 *wpv = (LPWSTR*)xmalloc(sizeof(LPWSTR)*(*wpc+2));
182 #define FREE_KEY_PATH free(wps[0]);free(wps);
185 * Shell initialisation, allocates keys.
186 * FIXME:should set default values too
190 #define ADD_ROOT_KEY(xx) \
191 xx = (LPKEYSTRUCT)xmalloc(sizeof(KEYSTRUCT));\
192 memset(xx,'\0',sizeof(KEYSTRUCT));\
193 xx->keyname= strdupA2W("<should_not_appear_anywhere>");
195 ADD_ROOT_KEY(key_classes_root);
196 ADD_ROOT_KEY(key_current_user);
197 ADD_ROOT_KEY(key_local_machine);
198 ADD_ROOT_KEY(key_users);
199 ADD_ROOT_KEY(key_performance_data);
200 ADD_ROOT_KEY(key_current_config);
201 ADD_ROOT_KEY(key_dyn_data);
205 /************************ SAVE Registry Function ****************************/
207 #define REGISTRY_SAVE_VERSION 0x00000001
209 /* Registry saveformat:
210 * If you change it, increase above number by 1, which will flush
211 * old registry database files.
222 * VALUE vals[nrofvalues]
224 * KEY keys[nrofsubkeys]
233 * DWORD len (len==0 means data=NULL)
237 * All _write_XXX and _read_XXX functions return !0 on sucess.
242 _write_DWORD(FILE *F,DWORD dw) {
243 return fwrite(&dw,sizeof(dw),1,F);
247 _write_USTRING(FILE *F,LPWSTR str) {
251 if (!_write_DWORD(F,0))
254 len=strlenW(str)*2+2;
256 if (!_write_DWORD(F,len))
258 if (!fwrite(str,len,1,F))
266 _do_save_subkey(FILE *F,LPKEYSTRUCT lpkey) {
274 if (!(lpxkey->flags & REG_OPTION_VOLATILE))
276 lpxkey = lpxkey->next;
278 if (!_write_DWORD(F,nrofkeys))
283 if (!(lpxkey->flags & REG_OPTION_VOLATILE)) {
284 if (!_write_USTRING(F,lpxkey->keyname))
286 if (!_write_USTRING(F,lpxkey->class))
288 if (!_write_DWORD(F,lpxkey->nrofvalues))
290 for (i=0;i<lpxkey->nrofvalues;i++) {
291 LPKEYVALUE val=lpxkey->values+i;
293 if (!_write_USTRING(F,val->name))
295 if (!_write_DWORD(F,val->type))
297 if (!_write_DWORD(F,val->len))
299 if (!fwrite(val->data,val->len,1,F))
302 /* descend recursively */
303 if (!_do_save_subkey(F,lpxkey->nextsub))
312 _do_savesubreg(FILE *F,LPKEYSTRUCT lpkey) {
313 if (!_write_DWORD(F,REGISTRY_SAVE_VERSION))
315 return _do_save_subkey(F,lpkey->nextsub);
319 _SaveSubReg(LPKEYSTRUCT lpkey,char *fn) {
324 fprintf(stddeb,__FILE__":_SaveSubReg:Couldn't open %s for writing: %s\n",
329 if (!_do_savesubreg(F,lpkey)) {
332 fprintf(stddeb,__FILE__":_SaveSubReg:Failed to save keys, perhaps no more diskspace for %s?\n",fn);
339 SHELL_SaveRegistry() {
340 _SaveSubReg(key_classes_root,SAVE_CLASSES_ROOT);
341 _SaveSubReg(key_current_user,SAVE_CURRENT_USER);
342 _SaveSubReg(key_local_machine,SAVE_LOCAL_MACHINE);
343 _SaveSubReg(key_users,SAVE_USERS);
346 /************************ LOAD Registry Function ****************************/
349 * Currently overwrites any old registry data (leaks it away)
350 * should better be a merge, or ?
354 _read_DWORD(FILE *F,DWORD *dw) {
355 return fread(dw,sizeof(DWORD),1,F);
359 _read_USTRING(FILE *F,LPWSTR *str) {
362 if (!_read_DWORD(F,&len))
369 return fread(*str,len,1,F);
373 _do_load_subkey(FILE *F,LPKEYSTRUCT lpkey) {
375 LPKEYSTRUCT *lplpkey,lpxkey;
378 if (!_read_DWORD(F,&howmuch))
385 lplpkey = &(lpkey->nextsub);
387 *lplpkey= (LPKEYSTRUCT)xmalloc(sizeof(KEYSTRUCT));
388 memset(*lplpkey,'\0',sizeof(KEYSTRUCT));
390 if (!_read_USTRING(F,&(lpxkey->keyname)))
392 if (!_read_USTRING(F,&(lpxkey->class)))
394 if (!_read_DWORD(F,&(lpxkey->nrofvalues)))
396 if (lpxkey->nrofvalues) {
397 lpxkey->values = (LPKEYVALUE)xmalloc(
398 lpxkey->nrofvalues*sizeof(KEYVALUE)
400 for (i=0;i<lpxkey->nrofvalues;i++) {
401 LPKEYVALUE val=lpxkey->values+i;
403 memset(val,'\0',sizeof(KEYVALUE));
404 if (!_read_USTRING(F,&(val->name)))
406 if (!_read_DWORD(F,&(val->type)))
408 if (!_read_DWORD(F,&(val->len)))
410 val->data = (LPBYTE)xmalloc(val->len);
411 if (!fread(val->data,val->len,1,F))
415 if (!_do_load_subkey(F,*lplpkey))
417 lplpkey = &(lpxkey->next);
423 _do_loadsubreg(FILE *F,LPKEYSTRUCT lpkey) {
426 if (!_read_DWORD(F,&ver))
428 if (ver!=REGISTRY_SAVE_VERSION) {
429 dprintf_reg(stddeb,__FILE__":_do_loadsubreg:Old format (%lx) registry found, ignoring it.\n",ver);
432 if (!_do_load_subkey(F,lpkey)) {
433 /* FIXME: memory leak on failure to read registry ...
434 * But this won't happen very often.
443 _LoadSubReg(LPKEYSTRUCT lpkey,char *fn) {
448 dprintf_reg(stddeb,__FILE__":Couldn't open %s for reading: %s\n",
453 if (!_do_loadsubreg(F,lpkey)) {
461 SHELL_LoadRegistry() {
462 if (key_classes_root==NULL)
464 _LoadSubReg(key_classes_root,SAVE_CLASSES_ROOT);
465 _LoadSubReg(key_current_user,SAVE_CURRENT_USER);
466 _LoadSubReg(key_local_machine,SAVE_LOCAL_MACHINE);
467 _LoadSubReg(key_users,SAVE_USERS);
470 /********************* API FUNCTIONS ***************************************/
475 * All functions are stubs to RegOpenKeyExW where all the
478 * FIXME: security,options,desiredaccess,...
481 * RegOpenKey -> RegOpenKeyA -> RegOpenKeyExA \
482 * RegOpenKeyW -> RegOpenKeyExW
485 /* RegOpenKeyExW [ADVAPI32.150] */
494 LPKEYSTRUCT lpNextKey,lpxkey;
497 dprintf_reg(stddeb,"RegOpenKeyExW(%lx,%s,%ld,%lx,%p)\n",
498 (LONG)hkey,W2C(lpszSubKey,0),dwReserved,samDesired,retkey
501 lpNextKey = lookup_hkey(hkey);
503 return SHELL_ERROR_BADKEY;
504 if (!lpszSubKey || !*lpszSubKey) {
505 add_handle(++currenthandle,lpNextKey,samDesired);
506 *retkey=currenthandle;
507 return SHELL_ERROR_SUCCESS;
509 split_keypath(lpszSubKey,&wps,&wpc);
513 lpxkey=lpNextKey->nextsub;
515 if (!strcmpW(wps[i],lpxkey->keyname))
521 return SHELL_ERROR_BADKEY;
526 add_handle(++currenthandle,lpxkey,samDesired);
527 *retkey = currenthandle;
529 return SHELL_ERROR_SUCCESS;
532 /* RegOpenKeyW [ADVAPI32.151] */
539 dprintf_reg(stddeb,"RegOpenKeyW(%lx,%s,%p)\n",
540 (LONG)hkey,W2C(lpszSubKey,0),retkey
542 return RegOpenKeyExW(hkey,lpszSubKey,0,KEY_ALL_ACCESS,retkey);
546 /* RegOpenKeyExA [ADVAPI32.149] */
558 dprintf_reg(stddeb,"RegOpenKeyExA(%lx,%s,%ld,%lx,%p)\n",
559 (LONG)hkey,lpszSubKey,dwReserved,samDesired,retkey
562 lpszSubKeyW=strdupA2W(lpszSubKey);
565 ret=RegOpenKeyExW(hkey,lpszSubKeyW,dwReserved,samDesired,retkey);
571 /* RegOpenKeyA [ADVAPI32.148] */
578 dprintf_reg(stddeb,"RegOpenKeyA(%lx,%s,%p)\n",
579 (LONG)hkey,lpszSubKey,retkey
581 return RegOpenKeyExA(hkey,lpszSubKey,0,KEY_ALL_ACCESS,retkey);
584 /* RegOpenKey [SHELL.1] [KERNEL.217] */
591 dprintf_reg(stddeb,"RegOpenKey(%lx,%s,%p)\n",
592 (LONG)hkey,lpszSubKey,retkey
594 return RegOpenKeyA(hkey,lpszSubKey,retkey);
600 * All those functions convert their respective
601 * arguments and call RegCreateKeyExW at the end.
603 * FIXME: no security,no access attrib,no optionhandling yet.
606 * RegCreateKey -> RegCreateKeyA -> RegCreateKeyExA \
607 * RegCreateKeyW -> RegCreateKeyExW
610 /* RegCreateKeyExW [ADVAPI32.131] */
619 LPSECURITY_ATTRIBUTES lpSecAttribs,
623 LPKEYSTRUCT *lplpPrevKey,lpNextKey,lpxkey;
627 /*FIXME: handle security/access/whatever */
628 dprintf_reg(stddeb,"RegCreateKeyExW(%lx,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n",
640 lpNextKey = lookup_hkey(hkey);
642 return SHELL_ERROR_BADKEY;
643 if (!lpszSubKey || !*lpszSubKey) {
644 add_handle(++currenthandle,lpNextKey,samDesired);
645 *retkey=currenthandle;
646 return SHELL_ERROR_SUCCESS;
648 split_keypath(lpszSubKey,&wps,&wpc);
652 lpxkey=lpNextKey->nextsub;
654 if (!strcmpW(wps[i],lpxkey->keyname))
664 add_handle(++currenthandle,lpxkey,samDesired);
665 *retkey = currenthandle;
666 *lpDispos = REG_OPENED_EXISTING_KEY;
668 return SHELL_ERROR_SUCCESS;
670 /* good. now the hard part */
672 lplpPrevKey = &(lpNextKey->nextsub);
673 lpxkey = *lplpPrevKey;
675 lplpPrevKey = &(lpxkey->next);
676 lpxkey = *lplpPrevKey;
678 *lplpPrevKey=malloc(sizeof(KEYSTRUCT));
681 return SHELL_ERROR_OUTOFMEMORY;
683 memset(*lplpPrevKey,'\0',sizeof(KEYSTRUCT));
684 (*lplpPrevKey)->keyname = strdupW(wps[i]);
685 (*lplpPrevKey)->next = NULL;
686 (*lplpPrevKey)->nextsub = NULL;
687 (*lplpPrevKey)->values = NULL;
688 (*lplpPrevKey)->nrofvalues = 0;
690 (*lplpPrevKey)->class = strdupW(lpszClass);
692 (*lplpPrevKey)->class = NULL;
693 lpNextKey = *lplpPrevKey;
696 add_handle(++currenthandle,lpNextKey,samDesired);
698 /*FIXME: flag handling correct? */
699 lpNextKey->flags= fdwOptions;
701 lpNextKey->class = strdupW(lpszClass);
703 lpNextKey->class = NULL;
704 *retkey = currenthandle;
705 *lpDispos = REG_CREATED_NEW_KEY;
707 return SHELL_ERROR_SUCCESS;
710 /* RegCreateKeyW [ADVAPI32.132] */
719 dprintf_reg(stddeb,"RegCreateKeyW(%lx,%s,%p)\n",
720 (LONG)hkey,W2C(lpszSubKey,0),retkey
723 hkey, /* key handle */
724 lpszSubKey, /* subkey name */
725 0, /* reserved = 0 */
726 NULL, /* lpszClass? FIXME: ? */
727 REG_OPTION_NON_VOLATILE, /* options */
728 KEY_ALL_ACCESS, /* desired access attribs */
729 NULL, /* lpsecurity attributes */
730 retkey, /* lpretkey */
731 &junk /* disposition value */
736 /* RegCreateKeyExA [ADVAPI32.130] */
745 LPSECURITY_ATTRIBUTES lpSecAttribs,
749 LPWSTR lpszSubKeyW,lpszClassW;
752 dprintf_reg(stddeb,"RegCreateKeyExA(%lx,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n",
764 lpszSubKeyW=strdupA2W(lpszSubKey);
768 lpszClassW=strdupA2W(lpszClass);
789 /* RegCreateKeyA [ADVAPI32.129] */
798 dprintf_reg(stddeb,"RegCreateKeyA(%lx,%s,%p)\n",
799 (LONG)hkey,lpszSubKey,retkey
801 return RegCreateKeyExA(
802 hkey, /* key handle */
803 lpszSubKey, /* subkey name */
804 0, /* reserved = 0 */
805 NULL, /* lpszClass? FIXME: ? */
806 REG_OPTION_NON_VOLATILE,/* options */
807 KEY_ALL_ACCESS, /* desired access attribs */
808 NULL, /* lpsecurity attributes */
809 retkey, /* lpretkey */
810 &junk /* disposition value */
814 /* RegCreateKey [SHELL.2] [KERNEL.218] */
821 dprintf_reg(stddeb,"RegCreateKey(%lx,%s,%p)\n",
822 (LONG)hkey,lpszSubKey,retkey
824 return RegCreateKeyA(hkey,lpszSubKey,retkey);
828 * Query Value Functions
829 * Win32 differs between keynames and valuenames.
830 * multiple values may belong to one key, the special value
831 * with name NULL is the default value used by the win31
835 * RegQueryValue -> RegQueryValueA -> RegQueryValueExA \
836 * RegQueryValueW -> RegQueryValueExW
839 /* RegQueryValueExW [ADVAPI32.158] */
843 LPWSTR lpszValueName,
844 LPDWORD lpdwReserved,
852 dprintf_reg(stddeb,"RegQueryValueExW(%lx,%s,%p,%p,%p,%p)\n",
853 hkey,W2C(lpszValueName,0),lpdwReserved,lpdwType,lpbData,lpcbData
856 lpkey = lookup_hkey(hkey);
858 return SHELL_ERROR_BADKEY;
859 if (lpszValueName==NULL) {
860 for (i=0;i<lpkey->nrofvalues;i++)
861 if (lpkey->values[i].name==NULL)
864 for (i=0;i<lpkey->nrofvalues;i++)
865 if (!strcmpW(lpszValueName,lpkey->values[i].name))
868 if (i==lpkey->nrofvalues) {
869 if (lpszValueName==NULL) {
870 *(WCHAR*)lpbData = 0;
873 return SHELL_ERROR_SUCCESS;
875 return SHELL_ERROR_BADKEY;/*FIXME: correct return? */
878 *lpdwType = lpkey->values[i].type;
881 return SHELL_ERROR_SUCCESS;
882 *lpcbData = lpkey->values[i].len;
883 return SHELL_ERROR_SUCCESS;
885 if (*lpcbData<lpkey->values[i].len) {
888 *lpcbData = lpkey->values[i].len;
889 return ERROR_MORE_DATA;
891 memcpy(lpbData,lpkey->values[i].data,lpkey->values[i].len);
892 *lpcbData = lpkey->values[i].len;
893 return SHELL_ERROR_SUCCESS;
896 /* RegQueryValueW [ADVAPI32.159] */
907 dprintf_reg(stddeb,"RegQueryValueW(%lx,%s,%p,%p)\n->",
908 hkey,W2C(lpszSubKey,0),lpszData,lpcbData
911 /* only open subkey, if we really do descend */
912 if (lpszSubKey && *lpszSubKey) {
913 ret = RegOpenKeyW(hkey,lpszSubKey,&xhkey);
914 if (ret!=ERROR_SUCCESS)
920 ret = RegQueryValueExW(
922 NULL, /* varname NULL -> compat */
923 NULL, /* lpdwReserved, must be NULL */
933 /* RegQueryValueExA [ADVAPI32.157] */
938 LPDWORD lpdwReserved,
943 LPWSTR lpszValueNameW;
948 dprintf_reg(stddeb,"RegQueryValueExA(%lx,%s,%p,%p,%p,%p)\n->",
949 hkey,lpszValueName,lpdwReserved,lpdwType,lpbData,lpcbData
953 buf = (LPBYTE)xmalloc((*lpcbData)*2);
954 myxlen = *lpcbData*2;
959 myxlen = *lpcbData*2;
965 lpszValueNameW=strdupA2W(lpszValueName);
969 ret=RegQueryValueExW(
978 if (ret==ERROR_SUCCESS) {
980 if (UNICONVMASK & (1<<(*lpdwType))) {
981 /* convert UNICODE to ASCII */
982 strcpyWA(lpbData,(LPWSTR)buf);
983 *lpcbData = myxlen/2;
985 if (myxlen>*lpcbData)
986 ret = ERROR_MORE_DATA;
988 memcpy(lpbData,buf,myxlen);
993 if ((UNICONVMASK & (1<<(*lpdwType))) && lpcbData)
994 *lpcbData = myxlen/2;
997 if ((UNICONVMASK & (1<<(*lpdwType))) && lpcbData)
998 *lpcbData = myxlen/2;
1005 /* RegQueryValueEx [KERNEL.225] */
1009 LPSTR lpszValueName,
1010 LPDWORD lpdwReserved,
1015 dprintf_reg(stddeb,"RegQueryValueEx(%lx,%s,%p,%p,%p,%p)\n",
1016 hkey,lpszValueName,lpdwReserved,lpdwType,lpbData,lpcbData
1018 return RegQueryValueExA(
1028 /* RegQueryValueA [ADVAPI32.156] */
1039 dprintf_reg(stddeb,"RegQueryValueA(%lx,%s,%p,%p)\n",
1040 hkey,lpszSubKey,lpszData,lpcbData
1043 /* only open subkey, if we really do descend */
1044 if (lpszSubKey && *lpszSubKey) {
1045 ret = RegOpenKey(hkey,lpszSubKey,&xhkey);
1046 if (ret!=ERROR_SUCCESS)
1052 ret = RegQueryValueExA(
1054 NULL, /* lpszValueName NULL -> compat */
1055 NULL, /* lpdwReserved, must be NULL */
1065 /* RegQueryValue [SHELL.6] [KERNEL.224] */
1073 dprintf_reg(stddeb,"RegQueryValueA(%lx,%s,%p,%p)\n",
1074 hkey,lpszSubKey,lpszData,lpcbData
1076 return RegQueryValueA(hkey,lpszSubKey,lpszData,lpcbData);
1080 * Setting values of Registry keys
1083 * RegSetValue -> RegSetValueA -> RegSetValueExA \
1084 * RegSetValueW -> RegSetValueExW
1087 /* RegSetValueExW [ADVAPI32.170] */
1091 LPWSTR lpszValueName,
1100 dprintf_reg(stddeb,"RegSetValueExW(%lx,%s,%ld,%ld,%p,%ld)\n",
1101 hkey,W2C(lpszValueName,0),dwReserved,dwType,lpbData,cbData
1103 /* we no longer care about the lpbData dwType here... */
1104 lpkey = lookup_hkey(hkey);
1106 return SHELL_ERROR_BADKEY;
1107 if (lpszValueName==NULL) {
1108 for (i=0;i<lpkey->nrofvalues;i++)
1109 if (lpkey->values[i].name==NULL)
1112 for (i=0;i<lpkey->nrofvalues;i++)
1113 if (!strcmpW(lpszValueName,lpkey->values[i].name))
1116 if (i==lpkey->nrofvalues) {
1117 lpkey->values = (LPKEYVALUE)xrealloc(
1119 (lpkey->nrofvalues+1)*sizeof(KEYVALUE)
1121 lpkey->nrofvalues++;
1122 memset(lpkey->values+i,'\0',sizeof(KEYVALUE));
1124 if (lpkey->values[i].name==NULL)
1126 lpkey->values[i].name = strdupW(lpszValueName);
1128 lpkey->values[i].name = NULL;
1129 lpkey->values[i].len = cbData;
1130 lpkey->values[i].type = dwType;
1131 if (lpkey->values[i].data !=NULL)
1132 free(lpkey->values[i].data);
1133 lpkey->values[i].data = (LPBYTE)xmalloc(cbData);
1134 memcpy(lpkey->values[i].data,lpbData,cbData);
1135 return SHELL_ERROR_SUCCESS;
1138 /* RegSetValueExA [ADVAPI32.169] */
1142 LPSTR lpszValueName,
1149 LPWSTR lpszValueNameW;
1152 dprintf_reg(stddeb,"RegSetValueExA(%lx,%s,%ld,%ld,%p,%ld)\n->",
1153 hkey,lpszValueName,dwReserved,dwType,lpbData,cbData
1155 if ((1<<dwType) & UNICONVMASK) {
1156 buf=(LPBYTE)strdupA2W(lpbData);
1157 cbData=2*strlen(lpbData)+2;
1161 lpszValueNameW = strdupA2W(lpszValueName);
1163 lpszValueNameW = NULL;
1164 ret=RegSetValueExW(hkey,lpszValueNameW,dwReserved,dwType,buf,cbData);
1166 free(lpszValueNameW);
1172 /* RegSetValueEx [KERNEL.226] */
1176 LPSTR lpszValueName,
1182 dprintf_reg(stddeb,"RegSetValueEx(%lx,%s,%ld,%ld,%p,%ld)\n->",
1183 hkey,lpszValueName,dwReserved,dwType,lpbData,cbData
1185 return RegSetValueExA(hkey,lpszValueName,dwReserved,dwType,lpbData,cbData);
1188 /* RegSetValueW [ADVAPI32.171] */
1200 dprintf_reg(stddeb,"RegSetValueW(%lx,%s,%ld,%s,%ld)\n->",
1201 hkey,W2C(lpszSubKey,0),dwType,W2C(lpszData,0),cbData
1203 if (lpszSubKey && *lpszSubKey) {
1204 ret=RegCreateKeyW(hkey,lpszSubKey,&xhkey);
1205 if (ret!=ERROR_SUCCESS)
1209 if (dwType!=REG_SZ) {
1210 fprintf(stddeb,"RegSetValueX called with dwType=%ld!\n",dwType);
1213 if (cbData!=2*strlenW(lpszData)+2) {
1214 dprintf_reg(stddeb,"RegSetValueX called with len=%ld != strlen(%s)+1=%d!\n",
1215 cbData,W2C(lpszData,0),2*strlenW(lpszData)+2
1217 cbData=2*strlenW(lpszData)+2;
1219 ret=RegSetValueExW(xhkey,NULL,0,dwType,(LPBYTE)lpszData,cbData);
1225 /* RegSetValueA [ADVAPI32.168] */
1237 dprintf_reg(stddeb,"RegSetValueA(%lx,%s,%ld,%s,%ld)\n->",
1238 hkey,lpszSubKey,dwType,lpszData,cbData
1240 if (lpszSubKey && *lpszSubKey) {
1241 ret=RegCreateKey(hkey,lpszSubKey,&xhkey);
1242 if (ret!=ERROR_SUCCESS)
1247 if (dwType!=REG_SZ) {
1248 dprintf_reg(stddeb,"RegSetValueA called with dwType=%ld!\n",dwType);
1251 if (cbData!=strlen(lpszData)+1)
1252 cbData=strlen(lpszData)+1;
1253 ret=RegSetValueExA(xhkey,NULL,0,dwType,(LPBYTE)lpszData,cbData);
1259 /* RegSetValue [KERNEL.221] [SHELL.5] */
1269 dprintf_reg(stddeb,"RegSetValue(%lx,%s,%ld,%s,%ld)\n->",
1270 hkey,lpszSubKey,dwType,lpszData,cbData
1272 ret=RegSetValueA(hkey,lpszSubKey,dwType,lpszData,cbData);
1280 * RegEnumKey -> RegEnumKeyA -> RegEnumKeyExA \
1281 * RegEnumKeyW -> RegEnumKeyExW
1284 /* RegEnumKeyExW [ADVAPI32.139] */
1291 LPDWORD lpdwReserved,
1296 LPKEYSTRUCT lpkey,lpxkey;
1298 dprintf_reg(stddeb,"RegEnumKeyExW(%lx,%ld,%p,%ld,%p,%p,%p,%p)\n",
1299 hkey,iSubkey,lpszName,*lpcchName,lpdwReserved,lpszClass,lpcchClass,ft
1301 lpkey=lookup_hkey(hkey);
1303 return SHELL_ERROR_BADKEY;
1304 if (!lpkey->nextsub)
1305 return ERROR_NO_MORE_ITEMS;
1306 lpxkey=lpkey->nextsub;
1307 while (iSubkey && lpxkey) {
1309 lpxkey=lpxkey->next;
1311 if (iSubkey || !lpxkey)
1312 return ERROR_NO_MORE_ITEMS;
1313 if (2*strlenW(lpxkey->keyname)+2>*lpcchName)
1314 return ERROR_MORE_DATA;
1315 memcpy(lpszName,lpxkey->keyname,strlenW(lpxkey->keyname)*2+2);
1317 /* what should we write into it? */
1321 return ERROR_SUCCESS;
1325 /* RegEnumKeyW [ADVAPI32.140] */
1335 dprintf_reg(stddeb,"RegEnumKeyW(%lx,%ld,%p,%ld)\n->",
1336 hkey,iSubkey,lpszName,lpcchName
1338 return RegEnumKeyExW(hkey,iSubkey,lpszName,&lpcchName,NULL,NULL,NULL,&ft);
1340 /* RegEnumKeyExA [ADVAPI32.138] */
1347 LPDWORD lpdwReserved,
1352 DWORD ret,lpcchNameW,lpcchClassW;
1353 LPWSTR lpszNameW,lpszClassW;
1356 dprintf_reg(stddeb,"RegEnumKeyExA(%lx,%ld,%p,%ld,%p,%p,%p,%p)\n->",
1357 hkey,iSubkey,lpszName,*lpcchName,lpdwReserved,lpszClass,lpcchClass,ft
1360 lpszNameW = (LPWSTR)xmalloc(*lpcchName*2);
1361 lpcchNameW = *lpcchName*2;
1367 lpszClassW = (LPWSTR)xmalloc(*lpcchClass*2);
1368 lpcchClassW = *lpcchClass*2;
1383 if (ret==ERROR_SUCCESS) {
1384 strcpyWA(lpszName,lpszNameW);
1385 *lpcchName=strlen(lpszName);
1387 strcpyWA(lpszClass,lpszClassW);
1388 *lpcchClass=strlen(lpszClass);
1398 /* RegEnumKeyA [ADVAPI32.137] */
1408 dprintf_reg(stddeb,"RegEnumKeyA(%lx,%ld,%p,%ld)\n->",
1409 hkey,iSubkey,lpszName,lpcchName
1411 return RegEnumKeyExA(
1423 /* RegEnumKey [SHELL.7] [KERNEL.216] */
1431 dprintf_reg(stddeb,"RegEnumKey(%lx,%ld,%p,%ld)\n->",
1432 hkey,iSubkey,lpszName,lpcchName
1434 return RegEnumKeyA(hkey,iSubkey,lpszName,lpcchName);
1438 * Enumerate Registry Values
1441 * RegEnumValue -> RegEnumValueA -> RegEnumValueW
1444 /* RegEnumValueW [ADVAPI32.142] */
1451 LPDWORD lpdReserved,
1459 dprintf_reg(stddeb,"RegEnumValueW(%ld,%ld,%p,%p,%p,%p,%p,%p)\n",
1460 hkey,iValue,lpszValue,lpcchValue,lpdReserved,lpdwType,lpbData,lpcbData
1462 lpkey = lookup_hkey(hkey);
1464 return SHELL_ERROR_BADKEY;
1465 if (lpkey->nrofvalues<iValue)
1466 return ERROR_NO_MORE_ITEMS;
1467 val = lpkey->values+iValue;
1470 if (strlenW(val->name)*2+2>*lpcchValue) {
1471 *lpcchValue = strlenW(val->name)*2+2;
1472 return ERROR_MORE_DATA;
1474 memcpy(lpszValue,val->name,2*strlenW(val->name)+2);
1475 *lpcchValue=strlenW(val->name)*2+2;
1477 /* how to handle NULL value? */
1481 *lpdwType=val->type;
1483 if (val->len>*lpcbData)
1484 return ERROR_MORE_DATA;
1485 memcpy(lpbData,val->data,val->len);
1486 *lpcbData = val->len;
1488 return SHELL_ERROR_SUCCESS;
1491 /* RegEnumValueA [ADVAPI32.141] */
1498 LPDWORD lpdReserved,
1505 DWORD ret,lpcbDataW;
1507 dprintf_reg(stddeb,"RegEnumValueA(%ld,%ld,%p,%p,%p,%p,%p,%p)\n",
1508 hkey,iValue,lpszValue,lpcchValue,lpdReserved,lpdwType,lpbData,lpcbData
1511 lpszValueW = (LPWSTR)xmalloc(*lpcchValue*2);
1513 lpbDataW = (LPBYTE)xmalloc(*lpcbData*2);
1514 lpcbDataW = *lpcbData*2;
1528 if (ret==ERROR_SUCCESS) {
1529 strcpyWA(lpszValue,lpszValueW);
1531 if ((1<<*lpdwType) & UNICONVMASK) {
1532 strcpyWA(lpbData,(LPWSTR)lpbDataW);
1534 if (lpcbDataW > *lpcbData)
1535 ret = ERROR_MORE_DATA;
1537 memcpy(lpbData,lpbDataW,lpcbDataW);
1539 *lpcbData = lpcbDataW;
1549 /* RegEnumValue [KERNEL.223] */
1556 LPDWORD lpdReserved,
1561 dprintf_reg(stddeb,"RegEnumValue(%ld,%ld,%p,%p,%p,%p,%p,%p)\n",
1562 hkey,iValue,lpszValue,lpcchValue,lpdReserved,lpdwType,lpbData,lpcbData
1564 return RegEnumValueA(
1577 * Close registry key
1579 /* RegCloseKey [SHELL.3] [KERNEL.220] [ADVAPI32.126] */
1581 RegCloseKey(HKEY hkey) {
1582 dprintf_reg(stddeb,"RegCloseKey(%ld)\n",hkey);
1583 remove_handle(hkey);
1584 return ERROR_SUCCESS;
1587 * Delete registry key
1590 * RegDeleteKey -> RegDeleteKeyA -> RegDeleteKeyW
1592 /* RegDeleteKeyW [ADVAPI32.134] */
1594 RegDeleteKeyW(HKEY hkey,LPWSTR lpszSubKey) {
1595 LPKEYSTRUCT *lplpPrevKey,lpNextKey,lpxkey;
1599 dprintf_reg(stddeb,"RegDeleteKeyW(%ld,%s)\n",
1600 hkey,W2C(lpszSubKey,0)
1602 lpNextKey = lookup_hkey(hkey);
1604 return SHELL_ERROR_BADKEY;
1605 /* we need to know the previous key in the hier. */
1606 if (!lpszSubKey || !*lpszSubKey)
1607 return SHELL_ERROR_BADKEY;
1608 split_keypath(lpszSubKey,&wps,&wpc);
1612 lpxkey=lpNextKey->nextsub;
1614 if (!strcmpW(wps[i],lpxkey->keyname))
1616 lpxkey=lpxkey->next;
1620 /* not found is success */
1621 return SHELL_ERROR_SUCCESS;
1626 lpxkey = lpNextKey->nextsub;
1627 lplpPrevKey = &(lpNextKey->nextsub);
1629 if (!strcmpW(wps[i],lpxkey->keyname))
1631 lplpPrevKey = &(lpxkey->next);
1632 lpxkey = lpxkey->next;
1635 return SHELL_ERROR_SUCCESS;
1636 if (lpxkey->nextsub)
1637 return SHELL_ERROR_CANTWRITE;
1638 *lplpPrevKey = lpxkey->next;
1639 free(lpxkey->keyname);
1641 free(lpxkey->class);
1643 free(lpxkey->values);
1646 return SHELL_ERROR_SUCCESS;
1649 /* RegDeleteKeyA [ADVAPI32.133] */
1651 RegDeleteKeyA(HKEY hkey,LPCSTR lpszSubKey) {
1655 dprintf_reg(stddeb,"RegDeleteKeyA(%ld,%s)\n",
1658 lpszSubKeyW=strdupA2W(lpszSubKey);
1659 ret=RegDeleteKeyW(hkey,lpszSubKeyW);
1664 /* RegDeleteKey [SHELL.4] [KERNEL.219] */
1666 RegDeleteKey(HKEY hkey,LPCSTR lpszSubKey) {
1667 dprintf_reg(stddeb,"RegDeleteKey(%ld,%s)\n",
1670 return RegDeleteKeyA(hkey,lpszSubKey);
1674 * Delete registry value
1677 * RegDeleteValue -> RegDeleteValueA -> RegDeleteValueW
1679 /* RegDeleteValueW [ADVAPI32.136] */
1681 RegDeleteValueW(HKEY hkey,LPWSTR lpszValue) {
1686 dprintf_reg(stddeb,"RegDeleteValueW(%ld,%s)\n",
1687 hkey,W2C(lpszValue,0)
1689 lpkey=lookup_hkey(hkey);
1691 return SHELL_ERROR_BADKEY;
1693 for (i=0;i<lpkey->nrofvalues;i++)
1694 if (!strcmpW(lpkey->values[i].name,lpszValue))
1697 for (i=0;i<lpkey->nrofvalues;i++)
1698 if (lpkey->values[i].name==NULL)
1701 if (i==lpkey->nrofvalues)
1702 return SHELL_ERROR_BADKEY;/*FIXME: correct errorcode? */
1703 val = lpkey->values+i;
1704 if (val->name) free(val->name);
1705 if (val->data) free(val->data);
1709 sizeof(KEYVALUE)*(lpkey->nrofvalues-i-1)
1711 lpkey->values = (LPKEYVALUE)xrealloc(
1713 (lpkey->nrofvalues-1)*sizeof(KEYVALUE)
1715 lpkey->nrofvalues--;
1716 return SHELL_ERROR_SUCCESS;
1719 /* RegDeleteValueA [ADVAPI32.135] */
1721 RegDeleteValueA(HKEY hkey,LPSTR lpszValue) {
1725 dprintf_reg(stddeb,"RegDeleteValueA(%ld,%s)\n",
1729 lpszValueW=strdupA2W(lpszValue);
1732 ret=RegDeleteValueW(hkey,lpszValueW);
1738 /* RegDeleteValue [KERNEL.222] */
1740 RegDeleteValue(HKEY hkey,LPSTR lpszValue) {
1741 dprintf_reg(stddeb,"RegDeleteValue(%ld,%s)\n",
1744 return RegDeleteValueA(hkey,lpszValue);
1747 /* RegFlushKey [ADVAPI32.143] [KERNEL.227] */
1749 RegFlushKey(HKEY hkey) {
1750 dprintf_reg(stddeb,"RegFlushKey(%ld), STUB.\n",hkey);
1751 return SHELL_ERROR_SUCCESS;
1754 /* FIXME: lpcchXXXX ... is this counting in WCHARS or in BYTEs ?? */
1756 /* RegQueryInfoKeyW [ADVAPI32.153] */
1762 LPDWORD lpdwReserved,
1764 LPDWORD lpcchMaxSubkey,
1765 LPDWORD lpcchMaxClass,
1767 LPDWORD lpcchMaxValueName,
1768 LPDWORD lpccbMaxValueData,
1769 LPDWORD lpcbSecurityDescriptor,
1772 LPKEYSTRUCT lpkey,lpxkey;
1773 int nrofkeys,maxsubkey,maxclass,maxvalues,maxvname,maxvdata;
1776 dprintf_reg(stddeb,"RegQueryInfoKeyW(%lx,......)\n",hkey);
1777 lpkey=lookup_hkey(hkey);
1779 return SHELL_ERROR_BADKEY;
1782 if (strlenW(lpkey->class)*2+2>*lpcchClass) {
1783 *lpcchClass=strlenW(lpkey->class)*2;
1784 return ERROR_MORE_DATA;
1786 *lpcchClass=strlenW(lpkey->class)*2;
1787 memcpy(lpszClass,lpkey->class,strlenW(lpkey->class));
1794 *lpcchClass = strlenW(lpkey->class)*2;
1796 lpxkey=lpkey->nextsub;
1797 nrofkeys=maxsubkey=maxclass=maxvalues=maxvname=maxvdata=0;
1800 if (strlenW(lpxkey->keyname)>maxsubkey)
1801 maxsubkey=strlenW(lpxkey->keyname);
1802 if (lpxkey->class && strlenW(lpxkey->class)>maxclass)
1803 maxclass=strlenW(lpxkey->class);
1804 if (lpxkey->nrofvalues>maxvalues)
1805 maxvalues=lpxkey->nrofvalues;
1806 for (i=0;i<lpxkey->nrofvalues;i++) {
1807 LPKEYVALUE val=lpxkey->values+i;
1809 if (val->name && strlenW(val->name)>maxvname)
1810 maxvname=strlenW(val->name);
1811 if (val->len>maxvdata)
1814 lpxkey=lpxkey->next;
1816 if (!maxclass) maxclass = 1;
1817 if (!maxvname) maxvname = 1;
1819 *lpcSubKeys = nrofkeys;
1821 *lpcchMaxSubkey = maxsubkey*2;
1823 *lpcchMaxClass = maxclass*2;
1825 *lpcValues = maxvalues;
1826 if (lpcchMaxValueName)
1827 *lpcchMaxValueName= maxvname;
1828 if (lpccbMaxValueData)
1829 *lpccbMaxValueData= maxvdata;
1830 return SHELL_ERROR_SUCCESS;
1833 /* RegQueryInfoKeyA [ADVAPI32.152] */
1839 LPDWORD lpdwReserved,
1841 LPDWORD lpcchMaxSubkey,
1842 LPDWORD lpcchMaxClass,
1844 LPDWORD lpcchMaxValueName,
1845 LPDWORD lpccbMaxValueData,
1846 LPDWORD lpcbSecurityDescriptor,
1852 dprintf_reg(stddeb,"RegQueryInfoKeyA(%lx,......)\n",hkey);
1855 lpszClassW = (LPWSTR)xmalloc(*lpcchClass);
1859 ret=RegQueryInfoKeyW(
1870 lpcbSecurityDescriptor,
1873 if (ret==ERROR_SUCCESS)
1874 strcpyWA(lpszClass,lpszClassW);
1881 if (lpcchMaxValueName)
1882 *lpcchMaxValueName/=2;