Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Registry Functions |
| 3 | * |
| 4 | * Copyright 1996 Marcus Meissner |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 5 | * Copyright 1998 Matthew Becker |
Sylvain St.Germain | e533222 | 1999-04-10 16:46:15 +0000 | [diff] [blame] | 6 | * Copyright 1999 Sylvain St-Germain |
Alexandre Julliard | 02e9008 | 1998-01-04 17:49:09 +0000 | [diff] [blame] | 7 | * |
| 8 | * December 21, 1997 - Kevin Cozens |
| 9 | * Fixed bugs in the _w95_loadreg() function. Added extra information |
| 10 | * regarding the format of the Windows '95 registry files. |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 11 | * |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 12 | * NOTES |
| 13 | * When changing this file, please re-run the regtest program to ensure |
| 14 | * the conditions are handled properly. |
| 15 | * |
| 16 | * TODO |
| 17 | * Security access |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 18 | * Option handling |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 19 | * Time for RegEnumKey*, RegQueryInfoKey* |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 20 | */ |
| 21 | |
Marcus Meissner | 31b9dab | 1999-10-24 22:08:33 +0000 | [diff] [blame] | 22 | #include "config.h" |
| 23 | |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 24 | #include <stdlib.h> |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 25 | #include <string.h> |
| 26 | #include <unistd.h> |
| 27 | #include <ctype.h> |
Alexandre Julliard | 8664b89 | 1996-04-05 14:58:24 +0000 | [diff] [blame] | 28 | #include <errno.h> |
Howard Abrams | 1327748 | 1999-07-10 13:16:29 +0000 | [diff] [blame] | 29 | #ifdef HAVE_SYS_ERRNO_H |
Alexandre Julliard | d30dfd2 | 1998-09-27 18:28:36 +0000 | [diff] [blame] | 30 | #include <sys/errno.h> |
Howard Abrams | 1327748 | 1999-07-10 13:16:29 +0000 | [diff] [blame] | 31 | #endif |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 32 | #include <sys/types.h> |
| 33 | #include <sys/fcntl.h> |
| 34 | #include <sys/stat.h> |
Alexandre Julliard | 0623a6f | 1998-01-18 18:01:49 +0000 | [diff] [blame] | 35 | #include <assert.h> |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 36 | #include <time.h> |
Marcus Meissner | 04c3e1d | 1999-02-19 10:37:02 +0000 | [diff] [blame] | 37 | #include "windef.h" |
| 38 | #include "winbase.h" |
| 39 | #include "wine/winbase16.h" |
| 40 | #include "wine/winestring.h" |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 41 | #include "winerror.h" |
Alexandre Julliard | 8cc3a5e | 1996-08-11 15:49:51 +0000 | [diff] [blame] | 42 | #include "file.h" |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 43 | #include "heap.h" |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 44 | #include "debugtools.h" |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 45 | #include "xmalloc.h" |
Marcus Meissner | 6b9dd2e | 1999-03-18 17:39:57 +0000 | [diff] [blame] | 46 | #include "options.h" |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 47 | #include "winreg.h" |
John Richardson | 2bb013b | 1998-11-06 17:36:13 +0000 | [diff] [blame] | 48 | #include "winversion.h" |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 49 | |
Patrik Stridvall | b4b9fae | 1999-04-19 14:56:29 +0000 | [diff] [blame] | 50 | DECLARE_DEBUG_CHANNEL(reg) |
| 51 | DECLARE_DEBUG_CHANNEL(string) |
| 52 | |
Juergen Schmied | ebc2b77 | 1998-11-14 18:59:30 +0000 | [diff] [blame] | 53 | static void REGISTRY_Init(void); |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 54 | /* FIXME: following defines should be configured global ... */ |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 55 | |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 56 | /* NOTE: do not append a /. linux' mkdir() WILL FAIL if you do that */ |
Sylvain St.Germain | e533222 | 1999-04-10 16:46:15 +0000 | [diff] [blame] | 57 | #define WINE_PREFIX "/.wine" |
Marcus Meissner | adf8a0c | 1999-06-12 08:18:38 +0000 | [diff] [blame] | 58 | #define SAVE_USERS_DEFAULT ETCDIR"/wine.userreg" |
| 59 | #define SAVE_LOCAL_MACHINE_DEFAULT ETCDIR"/wine.systemreg" |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 60 | |
| 61 | /* relative in ~user/.wine/ : */ |
Sylvain St.Germain | e533222 | 1999-04-10 16:46:15 +0000 | [diff] [blame] | 62 | #define SAVE_CURRENT_USER "user.reg" |
| 63 | #define SAVE_LOCAL_USERS_DEFAULT "wine.userreg" |
| 64 | #define SAVE_LOCAL_MACHINE "system.reg" |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 65 | |
Sylvain St.Germain | e533222 | 1999-04-10 16:46:15 +0000 | [diff] [blame] | 66 | #define KEY_REGISTRY "Software\\The WINE team\\WINE\\Registry" |
| 67 | #define VAL_SAVEUPDATED "SaveOnlyUpdatedKeys" |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 68 | |
Alexandre Julliard | d90840e | 1996-06-11 16:02:08 +0000 | [diff] [blame] | 69 | /* one value of a key */ |
| 70 | typedef struct tagKEYVALUE |
| 71 | { |
| 72 | LPWSTR name; /* name of value (UNICODE) or NULL for win31 */ |
| 73 | DWORD type; /* type of value */ |
Alexandre Julliard | a69b88b | 1998-03-15 20:29:56 +0000 | [diff] [blame] | 74 | DWORD len; /* length of data in BYTEs */ |
Alexandre Julliard | d90840e | 1996-06-11 16:02:08 +0000 | [diff] [blame] | 75 | DWORD lastmodified; /* time of seconds since 1.1.1970 */ |
| 76 | LPBYTE data; /* content, may be strings, binaries, etc. */ |
| 77 | } KEYVALUE,*LPKEYVALUE; |
| 78 | |
| 79 | /* a registry key */ |
| 80 | typedef struct tagKEYSTRUCT |
| 81 | { |
| 82 | LPWSTR keyname; /* name of THIS key (UNICODE) */ |
| 83 | DWORD flags; /* flags. */ |
| 84 | LPWSTR class; |
| 85 | /* values */ |
| 86 | DWORD nrofvalues; /* nr of values in THIS key */ |
| 87 | LPKEYVALUE values; /* values in THIS key */ |
| 88 | /* key management pointers */ |
| 89 | struct tagKEYSTRUCT *next; /* next key on same hierarchy */ |
| 90 | struct tagKEYSTRUCT *nextsub; /* keys that hang below THIS key */ |
| 91 | } KEYSTRUCT, *LPKEYSTRUCT; |
| 92 | |
| 93 | |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 94 | static KEYSTRUCT *key_classes_root=NULL; /* windows 3.1 global values */ |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 95 | static KEYSTRUCT *key_current_user=NULL; /* user specific values */ |
| 96 | static KEYSTRUCT *key_local_machine=NULL;/* machine specific values */ |
| 97 | static KEYSTRUCT *key_users=NULL; /* all users? */ |
| 98 | |
| 99 | /* dynamic, not saved */ |
| 100 | static KEYSTRUCT *key_performance_data=NULL; |
| 101 | static KEYSTRUCT *key_current_config=NULL; |
| 102 | static KEYSTRUCT *key_dyn_data=NULL; |
| 103 | |
| 104 | /* what valuetypes do we need to convert? */ |
| 105 | #define UNICONVMASK ((1<<REG_SZ)|(1<<REG_MULTI_SZ)|(1<<REG_EXPAND_SZ)) |
| 106 | |
Alexandre Julliard | e658d82 | 1997-11-30 17:45:40 +0000 | [diff] [blame] | 107 | |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 108 | static struct openhandle { |
| 109 | LPKEYSTRUCT lpkey; |
| 110 | HKEY hkey; |
| 111 | REGSAM accessmask; |
| 112 | } *openhandles=NULL; |
| 113 | static int nrofopenhandles=0; |
| 114 | /* Starts after 1 because 0,1 are reserved for Win16 */ |
Alexandre Julliard | 85ed45e | 1998-08-22 19:03:56 +0000 | [diff] [blame] | 115 | /* Note: Should always be even, as Win95 ADVAPI32.DLL reserves odd |
| 116 | HKEYs for remote registry access */ |
| 117 | static int currenthandle=2; |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 118 | |
| 119 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 120 | /* |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 121 | * QUESTION |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 122 | * Are these doing the same as HEAP_strdupAtoW and HEAP_strdupWtoA? |
| 123 | * If so, can we remove them? |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 124 | * ANSWER |
| 125 | * No, the memory handling functions are called very often in here, |
| 126 | * just replacing them by HeapAlloc(SystemHeap,...) makes registry |
| 127 | * loading 100 times slower. -MM |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 128 | */ |
Alexandre Julliard | e658d82 | 1997-11-30 17:45:40 +0000 | [diff] [blame] | 129 | static LPWSTR strdupA2W(LPCSTR src) |
| 130 | { |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 131 | if(src) { |
Alexandre Julliard | e658d82 | 1997-11-30 17:45:40 +0000 | [diff] [blame] | 132 | LPWSTR dest=xmalloc(2*strlen(src)+2); |
| 133 | lstrcpyAtoW(dest,src); |
| 134 | return dest; |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 135 | } |
| 136 | return NULL; |
Alexandre Julliard | e658d82 | 1997-11-30 17:45:40 +0000 | [diff] [blame] | 137 | } |
| 138 | |
| 139 | static LPWSTR strdupW(LPCWSTR a) { |
| 140 | LPWSTR b; |
| 141 | int len; |
| 142 | |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 143 | if(a) { |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 144 | len=sizeof(WCHAR)*(lstrlenW(a)+1); |
Alexandre Julliard | e658d82 | 1997-11-30 17:45:40 +0000 | [diff] [blame] | 145 | b=(LPWSTR)xmalloc(len); |
| 146 | memcpy(b,a,len); |
| 147 | return b; |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 148 | } |
| 149 | return NULL; |
| 150 | } |
| 151 | |
| 152 | LPWSTR strcvtA2W(LPCSTR src, int nchars) |
| 153 | |
| 154 | { |
| 155 | LPWSTR dest = xmalloc (2 * nchars + 2); |
| 156 | |
| 157 | lstrcpynAtoW(dest,src,nchars+1); |
| 158 | dest[nchars] = 0; |
| 159 | return dest; |
Alexandre Julliard | e658d82 | 1997-11-30 17:45:40 +0000 | [diff] [blame] | 160 | } |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 161 | /* |
| 162 | * we need to convert A to W with '\0' in strings (MULTI_SZ) |
| 163 | */ |
| 164 | |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 165 | static LPWSTR lmemcpynAtoW( LPWSTR dst, LPCSTR src, INT n ) |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 166 | { LPWSTR p = dst; |
| 167 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 168 | TRACE_(reg)("\"%s\" %i\n",src, n); |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 169 | |
| 170 | while (n-- > 0) *p++ = (WCHAR)(unsigned char)*src++; |
| 171 | |
| 172 | return dst; |
| 173 | } |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 174 | static LPSTR lmemcpynWtoA( LPSTR dst, LPCWSTR src, INT n ) |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 175 | { LPSTR p = dst; |
| 176 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 177 | TRACE_(string)("L\"%s\" %i\n",debugstr_w(src), n); |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 178 | |
| 179 | while (n-- > 0) *p++ = (CHAR)*src++; |
| 180 | |
| 181 | return dst; |
| 182 | } |
| 183 | |
Sylvain St.Germain | e533222 | 1999-04-10 16:46:15 +0000 | [diff] [blame] | 184 | static void debug_print_value (LPBYTE lpbData, LPKEYVALUE key) |
| 185 | { |
| 186 | if (TRACE_ON(reg) && lpbData) |
| 187 | { |
| 188 | switch(key->type) |
| 189 | { |
Noomen Hamza | c4cd0bf | 1999-05-08 10:50:34 +0000 | [diff] [blame] | 190 | case REG_EXPAND_SZ: |
Sylvain St.Germain | e533222 | 1999-04-10 16:46:15 +0000 | [diff] [blame] | 191 | case REG_SZ: |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 192 | TRACE_(reg)(" Value %s, Data(sz)=%s\n", |
Sylvain St.Germain | e533222 | 1999-04-10 16:46:15 +0000 | [diff] [blame] | 193 | debugstr_w(key->name), |
| 194 | debugstr_w((LPCWSTR)lpbData)); |
| 195 | break; |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 196 | |
Sylvain St.Germain | e533222 | 1999-04-10 16:46:15 +0000 | [diff] [blame] | 197 | case REG_DWORD: |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 198 | TRACE_(reg)(" Value %s, Data(dword)=0x%08lx\n", |
Sylvain St.Germain | e533222 | 1999-04-10 16:46:15 +0000 | [diff] [blame] | 199 | debugstr_w(key->name), |
| 200 | (DWORD)*lpbData); |
| 201 | break; |
| 202 | |
Sylvain St.Germain | e533222 | 1999-04-10 16:46:15 +0000 | [diff] [blame] | 203 | case REG_MULTI_SZ: |
| 204 | { |
| 205 | int i; |
| 206 | LPCWSTR ptr = (LPCWSTR)lpbData; |
| 207 | for (i=0;ptr[0];i++) |
| 208 | { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 209 | TRACE_(reg)(" Value %s, MULTI_SZ(%i=%s)\n", |
Sylvain St.Germain | e533222 | 1999-04-10 16:46:15 +0000 | [diff] [blame] | 210 | debugstr_w(key->name), |
| 211 | i, |
| 212 | debugstr_w(ptr)); |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 213 | |
Sylvain St.Germain | e533222 | 1999-04-10 16:46:15 +0000 | [diff] [blame] | 214 | ptr += lstrlenW(ptr)+1; |
| 215 | } |
| 216 | } |
| 217 | break; |
| 218 | |
Noomen Hamza | c4cd0bf | 1999-05-08 10:50:34 +0000 | [diff] [blame] | 219 | default: |
Sylvain St.Germain | e533222 | 1999-04-10 16:46:15 +0000 | [diff] [blame] | 220 | { |
| 221 | char szTemp[100]; /* 3*32 + 3 + 1 */ |
| 222 | int i; |
| 223 | for ( i = 0; i < key->len ; i++) |
| 224 | { |
| 225 | sprintf (&(szTemp[i*3]),"%02x ", lpbData[i]); |
| 226 | if (i>=31) |
| 227 | { |
| 228 | sprintf (&(szTemp[i*3+3]),"..."); |
| 229 | break; |
| 230 | } |
| 231 | } |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 232 | TRACE_(reg)(" Value %s, Data(raw)=(%s)\n", |
Sylvain St.Germain | e533222 | 1999-04-10 16:46:15 +0000 | [diff] [blame] | 233 | debugstr_w(key->name), |
| 234 | szTemp); |
| 235 | } |
Sylvain St.Germain | e533222 | 1999-04-10 16:46:15 +0000 | [diff] [blame] | 236 | } /* switch */ |
| 237 | } /* if */ |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 238 | } |
| 239 | |
Alexandre Julliard | e658d82 | 1997-11-30 17:45:40 +0000 | [diff] [blame] | 240 | |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 241 | /****************************************************************************** |
| 242 | * is_standard_hkey [Internal] |
| 243 | * Determines if a hkey is a standard key |
| 244 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 245 | static BOOL is_standard_hkey( HKEY hkey ) |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 246 | { |
| 247 | switch(hkey) { |
| 248 | case 0x00000000: |
| 249 | case 0x00000001: |
| 250 | case HKEY_CLASSES_ROOT: |
| 251 | case HKEY_CURRENT_CONFIG: |
| 252 | case HKEY_CURRENT_USER: |
| 253 | case HKEY_LOCAL_MACHINE: |
| 254 | case HKEY_USERS: |
| 255 | case HKEY_PERFORMANCE_DATA: |
| 256 | case HKEY_DYN_DATA: |
| 257 | return TRUE; |
| 258 | default: |
| 259 | return FALSE; |
| 260 | } |
| 261 | } |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 262 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 263 | /****************************************************************************** |
| 264 | * add_handle [Internal] |
| 265 | */ |
| 266 | static void add_handle( HKEY hkey, LPKEYSTRUCT lpkey, REGSAM accessmask ) |
| 267 | { |
| 268 | int i; |
| 269 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 270 | TRACE_(reg)("(0x%x,%p,0x%lx)\n",hkey,lpkey,accessmask); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 271 | /* Check for duplicates */ |
| 272 | for (i=0;i<nrofopenhandles;i++) { |
| 273 | if (openhandles[i].lpkey==lpkey) { |
| 274 | /* This is not really an error - the user is allowed to create |
| 275 | two (or more) handles to the same key */ |
| 276 | /*WARN(reg, "Adding key %p twice\n",lpkey);*/ |
| 277 | } |
| 278 | if (openhandles[i].hkey==hkey) { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 279 | WARN_(reg)("Adding handle %x twice\n",hkey); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 280 | } |
| 281 | } |
| 282 | openhandles=xrealloc( openhandles, |
| 283 | sizeof(struct openhandle)*(nrofopenhandles+1)); |
| 284 | |
| 285 | openhandles[i].lpkey = lpkey; |
| 286 | openhandles[i].hkey = hkey; |
| 287 | openhandles[i].accessmask = accessmask; |
| 288 | nrofopenhandles++; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 289 | } |
| 290 | |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 291 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 292 | /****************************************************************************** |
| 293 | * get_handle [Internal] |
| 294 | * |
| 295 | * RETURNS |
| 296 | * Success: Pointer to key |
| 297 | * Failure: NULL |
| 298 | */ |
| 299 | static LPKEYSTRUCT get_handle( HKEY hkey ) |
| 300 | { |
| 301 | int i; |
| 302 | |
| 303 | for (i=0; i<nrofopenhandles; i++) |
| 304 | if (openhandles[i].hkey == hkey) |
| 305 | return openhandles[i].lpkey; |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 306 | WARN_(reg)("Could not find handle 0x%x\n",hkey); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 307 | return NULL; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 308 | } |
| 309 | |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 310 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 311 | /****************************************************************************** |
| 312 | * remove_handle [Internal] |
| 313 | * |
| 314 | * PARAMS |
| 315 | * hkey [I] Handle of key to remove |
| 316 | * |
| 317 | * RETURNS |
| 318 | * Success: ERROR_SUCCESS |
| 319 | * Failure: ERROR_INVALID_HANDLE |
| 320 | */ |
| 321 | static DWORD remove_handle( HKEY hkey ) |
| 322 | { |
| 323 | int i; |
| 324 | |
| 325 | for (i=0;i<nrofopenhandles;i++) |
| 326 | if (openhandles[i].hkey==hkey) |
| 327 | break; |
| 328 | |
| 329 | if (i == nrofopenhandles) { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 330 | WARN_(reg)("Could not find handle 0x%x\n",hkey); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 331 | return ERROR_INVALID_HANDLE; |
| 332 | } |
| 333 | |
| 334 | memcpy( openhandles+i, |
| 335 | openhandles+i+1, |
| 336 | sizeof(struct openhandle)*(nrofopenhandles-i-1) |
| 337 | ); |
| 338 | openhandles=xrealloc(openhandles,sizeof(struct openhandle)*(nrofopenhandles-1)); |
| 339 | nrofopenhandles--; |
| 340 | return ERROR_SUCCESS; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 341 | } |
| 342 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 343 | /****************************************************************************** |
| 344 | * lookup_hkey [Internal] |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 345 | * |
| 346 | * Just as the name says. Creates the root keys on demand, so we can call the |
| 347 | * Reg* functions at any time. |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 348 | * |
| 349 | * RETURNS |
| 350 | * Success: Pointer to key structure |
| 351 | * Failure: NULL |
| 352 | */ |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 353 | #define ADD_ROOT_KEY(xx) \ |
| 354 | xx = (LPKEYSTRUCT)xmalloc(sizeof(KEYSTRUCT));\ |
| 355 | memset(xx,'\0',sizeof(KEYSTRUCT));\ |
| 356 | xx->keyname= strdupA2W("<should_not_appear_anywhere>"); |
| 357 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 358 | static LPKEYSTRUCT lookup_hkey( HKEY hkey ) |
| 359 | { |
Sylvain St.Germain | e533222 | 1999-04-10 16:46:15 +0000 | [diff] [blame] | 360 | switch (hkey) { |
| 361 | /* 0 and 1 are valid rootkeys in win16 shell.dll and are used by |
| 362 | * some programs. Do not remove those cases. -MM |
| 363 | */ |
| 364 | case 0x00000000: |
| 365 | case 0x00000001: |
| 366 | case HKEY_CLASSES_ROOT: |
| 367 | { |
| 368 | if (!key_classes_root) |
| 369 | { |
| 370 | HKEY cl_r_hkey; |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 371 | |
Sylvain St.Germain | e533222 | 1999-04-10 16:46:15 +0000 | [diff] [blame] | 372 | /* calls lookup_hkey recursively, TWICE */ |
| 373 | if ( RegCreateKey16( |
| 374 | HKEY_LOCAL_MACHINE, |
| 375 | "SOFTWARE\\Classes", |
| 376 | &cl_r_hkey) != ERROR_SUCCESS) |
| 377 | { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 378 | ERR_(reg)("Could not create HKLM\\SOFTWARE\\Classes. This is impossible.\n"); |
Sylvain St.Germain | e533222 | 1999-04-10 16:46:15 +0000 | [diff] [blame] | 379 | exit(1); |
| 380 | } |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 381 | |
Sylvain St.Germain | e533222 | 1999-04-10 16:46:15 +0000 | [diff] [blame] | 382 | key_classes_root = lookup_hkey(cl_r_hkey); |
| 383 | } |
| 384 | return key_classes_root; |
| 385 | } |
| 386 | |
| 387 | case HKEY_CURRENT_USER: |
| 388 | if (!key_current_user) { |
| 389 | ADD_ROOT_KEY(key_current_user); |
| 390 | } |
| 391 | return key_current_user; |
| 392 | |
| 393 | case HKEY_LOCAL_MACHINE: |
| 394 | if (!key_local_machine) { |
| 395 | ADD_ROOT_KEY(key_local_machine); |
| 396 | REGISTRY_Init(); |
| 397 | } |
| 398 | return key_local_machine; |
| 399 | |
| 400 | case HKEY_USERS: |
| 401 | if (!key_users) { |
| 402 | ADD_ROOT_KEY(key_users); |
| 403 | } |
| 404 | return key_users; |
| 405 | |
| 406 | case HKEY_PERFORMANCE_DATA: |
| 407 | if (!key_performance_data) { |
| 408 | ADD_ROOT_KEY(key_performance_data); |
| 409 | } |
| 410 | return key_performance_data; |
| 411 | |
| 412 | case HKEY_DYN_DATA: |
| 413 | if (!key_dyn_data) { |
| 414 | ADD_ROOT_KEY(key_dyn_data); |
| 415 | } |
| 416 | return key_dyn_data; |
| 417 | |
| 418 | case HKEY_CURRENT_CONFIG: |
| 419 | if (!key_current_config) { |
| 420 | ADD_ROOT_KEY(key_current_config); |
| 421 | } |
| 422 | return key_current_config; |
| 423 | |
| 424 | default: |
| 425 | return get_handle(hkey); |
| 426 | |
| 427 | } |
| 428 | /*NOTREACHED*/ |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 429 | } |
Andreas Mohr | d4b13da | 1999-08-07 14:17:10 +0000 | [diff] [blame] | 430 | |
| 431 | |
| 432 | /* |
| 433 | * recursively searches for lpkey_to_find in the root key branch |
| 434 | * given in lpcurrkey. |
| 435 | */ |
| 436 | static int subkey_found(LPKEYSTRUCT lpcurrkey, LPKEYSTRUCT lpkey_to_find) |
| 437 | { |
Andreas Mohr | d4b13da | 1999-08-07 14:17:10 +0000 | [diff] [blame] | 438 | while (lpcurrkey) |
| 439 | { |
Marcus Meissner | 1c40562 | 1999-09-03 12:19:34 +0000 | [diff] [blame] | 440 | if (lpcurrkey == lpkey_to_find) |
| 441 | return 1; |
Andreas Mohr | d4b13da | 1999-08-07 14:17:10 +0000 | [diff] [blame] | 442 | if (subkey_found(lpcurrkey->nextsub, lpkey_to_find)) |
| 443 | return 1; |
| 444 | |
| 445 | lpcurrkey = lpcurrkey->next; |
| 446 | } |
| 447 | |
| 448 | TRACE_(reg)("No key found in this root key branch\n"); |
| 449 | return 0; |
| 450 | } |
| 451 | |
| 452 | |
| 453 | /* |
| 454 | * finds the corresponding root key for a sub key, i.e. e.g. HKEY_CLASSES_ROOT. |
| 455 | */ |
| 456 | static HKEY find_root_key(LPKEYSTRUCT lpkey) |
| 457 | { |
| 458 | typedef struct tagROOT_KEYS { |
Patrik Stridvall | e92331f | 1999-09-20 18:52:06 +0000 | [diff] [blame] | 459 | KEYSTRUCT *lpkey; |
| 460 | HKEY hkey; |
Andreas Mohr | d4b13da | 1999-08-07 14:17:10 +0000 | [diff] [blame] | 461 | } ROOT_KEYS; |
Patrik Stridvall | e92331f | 1999-09-20 18:52:06 +0000 | [diff] [blame] | 462 | ROOT_KEYS root_keys[4]; |
Andreas Mohr | d4b13da | 1999-08-07 14:17:10 +0000 | [diff] [blame] | 463 | int i; |
| 464 | |
Patrik Stridvall | e92331f | 1999-09-20 18:52:06 +0000 | [diff] [blame] | 465 | root_keys[0].lpkey = key_classes_root; |
| 466 | root_keys[0].hkey = HKEY_CLASSES_ROOT; |
| 467 | root_keys[1].lpkey = key_current_user; |
| 468 | root_keys[1].hkey = HKEY_CURRENT_USER; |
| 469 | root_keys[2].lpkey = key_local_machine; |
| 470 | root_keys[2].hkey = HKEY_LOCAL_MACHINE; |
| 471 | root_keys[3].lpkey = key_users; |
| 472 | root_keys[3].hkey = HKEY_USERS; |
| 473 | |
Andreas Mohr | d4b13da | 1999-08-07 14:17:10 +0000 | [diff] [blame] | 474 | for (i=0; i<4;i++) |
| 475 | { |
| 476 | if (subkey_found(root_keys[i].lpkey, lpkey)) |
| 477 | return root_keys[i].hkey; |
| 478 | } |
| 479 | ERR_(reg)("Didn't find corresponding root key entry ! Search strategy broken ??\n"); |
| 480 | return 0; |
| 481 | #undef ROOT_KEYS |
| 482 | } |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 483 | #undef ADD_ROOT_KEY |
| 484 | /* so we don't accidently access them ... */ |
| 485 | #define key_current_config NULL NULL |
| 486 | #define key_current_user NULL NULL |
| 487 | #define key_users NULL NULL |
| 488 | #define key_local_machine NULL NULL |
| 489 | #define key_classes_root NULL NULL |
| 490 | #define key_dyn_data NULL NULL |
| 491 | #define key_performance_data NULL NULL |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 492 | |
| 493 | /****************************************************************************** |
| 494 | * split_keypath [Internal] |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 495 | * splits the unicode string 'wp' into an array of strings. |
| 496 | * the array is allocated by this function. |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 497 | * Free the array using FREE_KEY_PATH |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 498 | * |
| 499 | * PARAMS |
| 500 | * wp [I] String to split up |
| 501 | * wpv [O] Array of pointers to strings |
| 502 | * wpc [O] Number of components |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 503 | */ |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 504 | static void split_keypath( LPCWSTR wp, LPWSTR **wpv, int *wpc) |
| 505 | { |
| 506 | int i,j,len; |
| 507 | LPWSTR ws; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 508 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 509 | TRACE_(reg)("(%s,%p,%p)\n",debugstr_w(wp),wpv,wpc); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 510 | |
| 511 | ws = HEAP_strdupW( SystemHeap, 0, wp ); |
| 512 | |
| 513 | /* We know we have at least one substring */ |
| 514 | *wpc = 1; |
| 515 | |
| 516 | /* Replace each backslash with NULL, and increment the count */ |
| 517 | for (i=0;ws[i];i++) { |
| 518 | if (ws[i]=='\\') { |
| 519 | ws[i]=0; |
| 520 | (*wpc)++; |
| 521 | } |
| 522 | } |
| 523 | |
| 524 | len = i; |
| 525 | |
| 526 | /* Allocate the space for the array of pointers, leaving room for the |
| 527 | NULL at the end */ |
| 528 | *wpv = (LPWSTR*)HeapAlloc( SystemHeap, 0, sizeof(LPWSTR)*(*wpc+2)); |
| 529 | (*wpv)[0]= ws; |
| 530 | |
| 531 | /* Assign each pointer to the appropriate character in the string */ |
| 532 | j = 1; |
| 533 | for (i=1;i<len;i++) |
| 534 | if (ws[i-1]==0) { |
| 535 | (*wpv)[j++]=ws+i; |
Huw D M Davies | f49cb52 | 1999-11-12 00:58:15 +0000 | [diff] [blame] | 536 | /*TRACE_(reg) (" Subitem %d = %s\n",j-1,debugstr_w((*wpv)[j-1]));*/ |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 537 | } |
| 538 | |
| 539 | (*wpv)[j]=NULL; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 540 | } |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 541 | #define FREE_KEY_PATH HeapFree(SystemHeap,0,wps[0]);HeapFree(SystemHeap,0,wps); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 542 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 543 | |
| 544 | |
| 545 | |
| 546 | /****************************************************************************** |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 547 | * REGISTRY_Init [Internal] |
| 548 | * Registry initialisation, allocates some default keys. |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 549 | */ |
Juergen Schmied | ebc2b77 | 1998-11-14 18:59:30 +0000 | [diff] [blame] | 550 | static void REGISTRY_Init(void) { |
Alexandre Julliard | a11d7b1 | 1998-03-01 20:05:02 +0000 | [diff] [blame] | 551 | HKEY hkey; |
| 552 | char buf[200]; |
Alexandre Julliard | 8bbf818 | 1996-09-13 16:50:47 +0000 | [diff] [blame] | 553 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 554 | TRACE_(reg)("(void)\n"); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 555 | |
| 556 | RegCreateKey16(HKEY_DYN_DATA,"PerfStats\\StatData",&hkey); |
Alexandre Julliard | 8bbf818 | 1996-09-13 16:50:47 +0000 | [diff] [blame] | 557 | RegCloseKey(hkey); |
Alexandre Julliard | a11d7b1 | 1998-03-01 20:05:02 +0000 | [diff] [blame] | 558 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 559 | /* This was an Open, but since it is called before the real registries |
| 560 | are loaded, it was changed to a Create - MTB 980507*/ |
| 561 | RegCreateKey16(HKEY_LOCAL_MACHINE,"HARDWARE\\DESCRIPTION\\System",&hkey); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 562 | RegSetValueExA(hkey,"Identifier",0,REG_SZ,"SystemType WINE",strlen("SystemType WINE")); |
Alexandre Julliard | 8bbf818 | 1996-09-13 16:50:47 +0000 | [diff] [blame] | 563 | RegCloseKey(hkey); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 564 | |
Alexandre Julliard | 8bbf818 | 1996-09-13 16:50:47 +0000 | [diff] [blame] | 565 | /* \\SOFTWARE\\Microsoft\\Window NT\\CurrentVersion |
| 566 | * CurrentVersion |
| 567 | * CurrentBuildNumber |
| 568 | * CurrentType |
| 569 | * string RegisteredOwner |
| 570 | * string RegisteredOrganization |
| 571 | * |
| 572 | */ |
| 573 | /* System\\CurrentControlSet\\Services\\SNMP\\Parameters\\RFC1156Agent |
| 574 | * string SysContact |
| 575 | * string SysLocation |
| 576 | * SysServices |
Huw D M Davies | f49cb52 | 1999-11-12 00:58:15 +0000 | [diff] [blame] | 577 | */ |
Alexandre Julliard | 8bbf818 | 1996-09-13 16:50:47 +0000 | [diff] [blame] | 578 | if (-1!=gethostname(buf,200)) { |
Alexandre Julliard | a11d7b1 | 1998-03-01 20:05:02 +0000 | [diff] [blame] | 579 | RegCreateKey16(HKEY_LOCAL_MACHINE,"System\\CurrentControlSet\\Control\\ComputerName\\ComputerName",&hkey); |
| 580 | RegSetValueEx16(hkey,"ComputerName",0,REG_SZ,buf,strlen(buf)+1); |
| 581 | RegCloseKey(hkey); |
Alexandre Julliard | 8bbf818 | 1996-09-13 16:50:47 +0000 | [diff] [blame] | 582 | } |
| 583 | } |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 584 | |
| 585 | |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 586 | /************************ SAVE Registry Function ****************************/ |
| 587 | |
| 588 | #define REGISTRY_SAVE_VERSION 0x00000001 |
| 589 | |
| 590 | /* Registry saveformat: |
| 591 | * If you change it, increase above number by 1, which will flush |
| 592 | * old registry database files. |
| 593 | * |
| 594 | * Global: |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 595 | * "WINE REGISTRY Version %d" |
| 596 | * subkeys.... |
| 597 | * Subkeys: |
| 598 | * keyname |
| 599 | * valuename=lastmodified,type,data |
| 600 | * ... |
| 601 | * subkeys |
| 602 | * ... |
| 603 | * keyname,valuename,stringdata: |
| 604 | * the usual ascii characters from 0x00-0xff (well, not 0x00) |
| 605 | * and \uXXXX as UNICODE value XXXX with XXXX>0xff |
| 606 | * ( "=\\\t" escaped in \uXXXX form.) |
| 607 | * type,lastmodified: |
| 608 | * int |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 609 | * |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 610 | * FIXME: doesn't save 'class' (what does it mean anyway?), nor flags. |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 611 | * |
| 612 | * [HKEY_CURRENT_USER\\Software\\The WINE team\\WINE\\Registry] |
| 613 | * SaveOnlyUpdatedKeys=yes |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 614 | */ |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 615 | |
| 616 | /****************************************************************************** |
| 617 | * _save_check_tainted [Internal] |
| 618 | */ |
| 619 | static int _save_check_tainted( LPKEYSTRUCT lpkey ) |
| 620 | { |
Huw D M Davies | f49cb52 | 1999-11-12 00:58:15 +0000 | [diff] [blame] | 621 | int tainted = 0; |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 622 | |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 623 | while (lpkey) { |
Huw D M Davies | f49cb52 | 1999-11-12 00:58:15 +0000 | [diff] [blame] | 624 | if (_save_check_tainted(lpkey->nextsub)) |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 625 | lpkey->flags |= REG_OPTION_TAINTED; |
Huw D M Davies | f49cb52 | 1999-11-12 00:58:15 +0000 | [diff] [blame] | 626 | if (lpkey->flags & REG_OPTION_TAINTED) |
| 627 | tainted = 1; |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 628 | lpkey = lpkey->next; |
| 629 | } |
| 630 | return tainted; |
| 631 | } |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 632 | |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 633 | /****************************************************************************** |
| 634 | * _save_USTRING [Internal] |
| 635 | */ |
| 636 | static void _save_USTRING( FILE *F, LPWSTR wstr, int escapeeq ) |
| 637 | { |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 638 | LPWSTR s; |
| 639 | int doescape; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 640 | |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 641 | if (wstr==NULL) |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 642 | return; |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 643 | s=wstr; |
| 644 | while (*s) { |
| 645 | doescape=0; |
Marcus Meissner | 229a28f | 1999-10-13 12:15:19 +0000 | [diff] [blame] | 646 | if (*s>0x7f) |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 647 | doescape = 1; |
| 648 | if (*s=='\n') |
| 649 | doescape = 1; |
| 650 | if (escapeeq && *s=='=') |
| 651 | doescape = 1; |
| 652 | if (*s=='\\') |
Alexandre Julliard | 641ee76 | 1997-08-04 16:34:36 +0000 | [diff] [blame] | 653 | fputc(*s,F); /* if \\ then put it twice. */ |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 654 | if (doescape) |
| 655 | fprintf(F,"\\u%04x",*((unsigned short*)s)); |
| 656 | else |
| 657 | fputc(*s,F); |
| 658 | s++; |
| 659 | } |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 660 | } |
| 661 | |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 662 | /****************************************************************************** |
| 663 | * _savesubkey [Internal] |
Juergen Schmied | f74fa4e | 1999-01-31 09:19:46 +0000 | [diff] [blame] | 664 | * |
| 665 | * NOTES |
| 666 | * REG_MULTI_SZ is handled as binary (like in win95) (js) |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 667 | */ |
| 668 | static int _savesubkey( FILE *F, LPKEYSTRUCT lpkey, int level, int all ) |
| 669 | { |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 670 | LPKEYSTRUCT lpxkey; |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 671 | int i,tabs,j; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 672 | |
| 673 | lpxkey = lpkey; |
| 674 | while (lpxkey) { |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 675 | if ( !(lpxkey->flags & REG_OPTION_VOLATILE) && |
| 676 | (all || (lpxkey->flags & REG_OPTION_TAINTED)) |
| 677 | ) { |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 678 | for (tabs=level;tabs--;) |
| 679 | fputc('\t',F); |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 680 | _save_USTRING(F,lpxkey->keyname,1); |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 681 | fputs("\n",F); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 682 | for (i=0;i<lpxkey->nrofvalues;i++) { |
| 683 | LPKEYVALUE val=lpxkey->values+i; |
| 684 | |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 685 | for (tabs=level+1;tabs--;) |
| 686 | fputc('\t',F); |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 687 | _save_USTRING(F,val->name,0); |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 688 | fputc('=',F); |
| 689 | fprintf(F,"%ld,%ld,",val->type,val->lastmodified); |
Juergen Schmied | f74fa4e | 1999-01-31 09:19:46 +0000 | [diff] [blame] | 690 | if ( val->type == REG_SZ || val->type == REG_EXPAND_SZ ) |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 691 | _save_USTRING(F,(LPWSTR)val->data,0); |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 692 | else |
| 693 | for (j=0;j<val->len;j++) |
| 694 | fprintf(F,"%02x",*((unsigned char*)val->data+j)); |
| 695 | fputs("\n",F); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 696 | } |
| 697 | /* descend recursively */ |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 698 | if (!_savesubkey(F,lpxkey->nextsub,level+1,all)) |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 699 | return 0; |
| 700 | } |
| 701 | lpxkey=lpxkey->next; |
| 702 | } |
| 703 | return 1; |
| 704 | } |
| 705 | |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 706 | |
| 707 | /****************************************************************************** |
| 708 | * _savesubreg [Internal] |
| 709 | */ |
| 710 | static int _savesubreg( FILE *F, LPKEYSTRUCT lpkey, int all ) |
| 711 | { |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 712 | fprintf(F,"WINE REGISTRY Version %d\n",REGISTRY_SAVE_VERSION); |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 713 | _save_check_tainted(lpkey->nextsub); |
| 714 | return _savesubkey(F,lpkey->nextsub,0,all); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 715 | } |
| 716 | |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 717 | |
| 718 | /****************************************************************************** |
| 719 | * _savereg [Internal] |
| 720 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 721 | static BOOL _savereg( LPKEYSTRUCT lpkey, char *fn, int all ) |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 722 | { |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 723 | FILE *F; |
| 724 | |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 725 | F=fopen(fn,"w"); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 726 | if (F==NULL) { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 727 | WARN_(reg)("Couldn't open %s for writing: %s\n", |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 728 | fn,strerror(errno) |
| 729 | ); |
Alexandre Julliard | da0cfb3 | 1996-12-01 17:17:47 +0000 | [diff] [blame] | 730 | return FALSE; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 731 | } |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 732 | if (!_savesubreg(F,lpkey,all)) { |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 733 | fclose(F); |
| 734 | unlink(fn); |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 735 | WARN_(reg)("Failed to save keys, perhaps no more diskspace for %s?\n",fn); |
Alexandre Julliard | da0cfb3 | 1996-12-01 17:17:47 +0000 | [diff] [blame] | 736 | return FALSE; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 737 | } |
| 738 | fclose(F); |
Alexandre Julliard | da0cfb3 | 1996-12-01 17:17:47 +0000 | [diff] [blame] | 739 | return TRUE; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 740 | } |
| 741 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 742 | |
| 743 | /****************************************************************************** |
Andreas Mohr | d4b13da | 1999-08-07 14:17:10 +0000 | [diff] [blame] | 744 | * SHELL_SaveRegistryBranch [Internal] |
| 745 | * |
| 746 | * Saves main registry branch specified by hkey. |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 747 | */ |
Andreas Mohr | d4b13da | 1999-08-07 14:17:10 +0000 | [diff] [blame] | 748 | static void SHELL_SaveRegistryBranch(HKEY hkey, int all) |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 749 | { |
Alexandre Julliard | 154c99b | 1999-04-25 12:41:36 +0000 | [diff] [blame] | 750 | char *fn, *home, *tmp; |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 751 | |
Nathaniel | 7bf36ad | 1999-10-24 19:35:47 +0000 | [diff] [blame] | 752 | /* Find out what to save to, get from config file */ |
| 753 | BOOL writeToHome = PROFILE_GetWineIniBool("registry","WritetoHomeRegistries",1); |
| 754 | BOOL writeToAlt = PROFILE_GetWineIniBool("registry","WritetoAltRegistries",1); |
| 755 | |
Andreas Mohr | d4b13da | 1999-08-07 14:17:10 +0000 | [diff] [blame] | 756 | /* FIXME: does this check apply to all keys written below ? */ |
Alexandre Julliard | 154c99b | 1999-04-25 12:41:36 +0000 | [diff] [blame] | 757 | if (!(home = getenv( "HOME" ))) |
Andreas Mohr | d4b13da | 1999-08-07 14:17:10 +0000 | [diff] [blame] | 758 | ERR_(reg)("Failed to get homedirectory of UID %ld.\n",(long) getuid()); |
Andreas Mohr | d4b13da | 1999-08-07 14:17:10 +0000 | [diff] [blame] | 759 | |
Nathaniel | 7bf36ad | 1999-10-24 19:35:47 +0000 | [diff] [blame] | 760 | /* HKEY_LOCAL_MACHINE contains the HKEY_CLASSES_ROOT branch */ |
| 761 | if (hkey == HKEY_CLASSES_ROOT) hkey = HKEY_LOCAL_MACHINE; |
Andreas Mohr | d4b13da | 1999-08-07 14:17:10 +0000 | [diff] [blame] | 762 | |
Nathaniel | 7bf36ad | 1999-10-24 19:35:47 +0000 | [diff] [blame] | 763 | switch (hkey) |
Andreas Mohr | d4b13da | 1999-08-07 14:17:10 +0000 | [diff] [blame] | 764 | { |
Nathaniel | 7bf36ad | 1999-10-24 19:35:47 +0000 | [diff] [blame] | 765 | case HKEY_CURRENT_USER: |
| 766 | fn = xmalloc( MAX_PATHNAME_LEN ); |
| 767 | if (writeToAlt && PROFILE_GetWineIniString( "registry", "AltCurrentUserFile", "", |
| 768 | fn, MAX_PATHNAME_LEN - 1)) |
| 769 | _savereg(lookup_hkey(HKEY_CURRENT_USER),fn,all); |
| 770 | free (fn); |
Andreas Mohr | d4b13da | 1999-08-07 14:17:10 +0000 | [diff] [blame] | 771 | |
Nathaniel | 7bf36ad | 1999-10-24 19:35:47 +0000 | [diff] [blame] | 772 | if (home && writeToHome) |
| 773 | { |
| 774 | fn=(char*)xmalloc( strlen(home) + strlen(WINE_PREFIX) + |
| 775 | strlen(SAVE_CURRENT_USER) + 2 ); |
| 776 | strcpy(fn,home); |
| 777 | strcat(fn,WINE_PREFIX); |
Alexandre Julliard | 154c99b | 1999-04-25 12:41:36 +0000 | [diff] [blame] | 778 | |
Nathaniel | 7bf36ad | 1999-10-24 19:35:47 +0000 | [diff] [blame] | 779 | /* create the directory. don't care about errorcodes. */ |
| 780 | mkdir(fn,0755); /* drwxr-xr-x */ |
| 781 | strcat(fn,"/"SAVE_CURRENT_USER); |
Nathan Zorich | bd3771c | 1999-03-14 15:12:48 +0000 | [diff] [blame] | 782 | |
Nathaniel | 7bf36ad | 1999-10-24 19:35:47 +0000 | [diff] [blame] | 783 | tmp = (char*)xmalloc(strlen(fn)+strlen(".tmp")+1); |
| 784 | strcpy(tmp,fn); |
| 785 | strcat(tmp,".tmp"); |
Sylvain St.Germain | e533222 | 1999-04-10 16:46:15 +0000 | [diff] [blame] | 786 | |
Nathaniel | 7bf36ad | 1999-10-24 19:35:47 +0000 | [diff] [blame] | 787 | if (_savereg(lookup_hkey(HKEY_CURRENT_USER),tmp,all)) { |
| 788 | if (-1==rename(tmp,fn)) { |
| 789 | perror("rename tmp registry"); |
| 790 | unlink(tmp); |
| 791 | } |
Alexandre Julliard | 154c99b | 1999-04-25 12:41:36 +0000 | [diff] [blame] | 792 | } |
Nathaniel | 7bf36ad | 1999-10-24 19:35:47 +0000 | [diff] [blame] | 793 | free(tmp); |
| 794 | free(fn); |
Alexandre Julliard | 154c99b | 1999-04-25 12:41:36 +0000 | [diff] [blame] | 795 | } |
Nathaniel | 7bf36ad | 1999-10-24 19:35:47 +0000 | [diff] [blame] | 796 | break; |
| 797 | case HKEY_LOCAL_MACHINE: |
| 798 | /* Try first saving according to the defined location in .winerc */ |
| 799 | fn = xmalloc ( MAX_PATHNAME_LEN); |
| 800 | if (writeToAlt && PROFILE_GetWineIniString( "Registry", "AltLocalMachineFile", "", |
| 801 | fn, MAX_PATHNAME_LEN - 1)) |
| 802 | _savereg(lookup_hkey(HKEY_LOCAL_MACHINE), fn, all); |
| 803 | free (fn); |
Nathan Zorich | bd3771c | 1999-03-14 15:12:48 +0000 | [diff] [blame] | 804 | |
Nathaniel | 7bf36ad | 1999-10-24 19:35:47 +0000 | [diff] [blame] | 805 | if (home && writeToHome) |
| 806 | { |
| 807 | fn=(char*)xmalloc( strlen(home) + strlen(WINE_PREFIX) + |
| 808 | strlen(SAVE_LOCAL_MACHINE) + 2); |
| 809 | strcpy(fn,home); |
| 810 | strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_MACHINE); |
Alexandre Julliard | 154c99b | 1999-04-25 12:41:36 +0000 | [diff] [blame] | 811 | |
Nathaniel | 7bf36ad | 1999-10-24 19:35:47 +0000 | [diff] [blame] | 812 | tmp = (char*)xmalloc(strlen(fn)+strlen(".tmp")+1); |
| 813 | strcpy(tmp,fn); |
| 814 | strcat(tmp,".tmp"); |
Alexandre Julliard | 154c99b | 1999-04-25 12:41:36 +0000 | [diff] [blame] | 815 | |
Nathaniel | 7bf36ad | 1999-10-24 19:35:47 +0000 | [diff] [blame] | 816 | if (_savereg(lookup_hkey(HKEY_LOCAL_MACHINE),tmp,all)) { |
| 817 | if (-1==rename(tmp,fn)) { |
| 818 | perror("rename tmp registry"); |
| 819 | unlink(tmp); |
| 820 | } |
Alexandre Julliard | 154c99b | 1999-04-25 12:41:36 +0000 | [diff] [blame] | 821 | } |
Nathaniel | 7bf36ad | 1999-10-24 19:35:47 +0000 | [diff] [blame] | 822 | free(tmp); |
| 823 | free(fn); |
Alexandre Julliard | 154c99b | 1999-04-25 12:41:36 +0000 | [diff] [blame] | 824 | } |
Nathaniel | 7bf36ad | 1999-10-24 19:35:47 +0000 | [diff] [blame] | 825 | break; |
| 826 | case HKEY_USERS: |
| 827 | fn = xmalloc( MAX_PATHNAME_LEN ); |
| 828 | if (writeToAlt && PROFILE_GetWineIniString( "Registry", "AltUserFile", "", |
| 829 | fn, MAX_PATHNAME_LEN - 1)) |
| 830 | _savereg(lookup_hkey(HKEY_LOCAL_MACHINE), fn, all); |
| 831 | free (fn); |
Nathan Zorich | bd3771c | 1999-03-14 15:12:48 +0000 | [diff] [blame] | 832 | |
Nathaniel | 7bf36ad | 1999-10-24 19:35:47 +0000 | [diff] [blame] | 833 | if (home && writeToHome) |
| 834 | { |
| 835 | fn=(char*)xmalloc( strlen(home) + strlen(WINE_PREFIX) + |
| 836 | strlen(SAVE_LOCAL_USERS_DEFAULT) + 2); |
| 837 | strcpy(fn,home); |
| 838 | strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_USERS_DEFAULT); |
Sylvain St.Germain | e533222 | 1999-04-10 16:46:15 +0000 | [diff] [blame] | 839 | |
Nathaniel | 7bf36ad | 1999-10-24 19:35:47 +0000 | [diff] [blame] | 840 | tmp = (char*)xmalloc(strlen(fn)+strlen(".tmp")+1); |
| 841 | strcpy(tmp,fn); |
| 842 | strcat(tmp,".tmp"); |
| 843 | if ( _savereg(lookup_hkey(HKEY_USERS),tmp,FALSE)) { |
| 844 | if (-1==rename(tmp,fn)) { |
| 845 | perror("rename tmp registry"); |
| 846 | unlink(tmp); |
| 847 | } |
| 848 | } |
| 849 | free(tmp); |
| 850 | free(fn); |
Alexandre Julliard | 154c99b | 1999-04-25 12:41:36 +0000 | [diff] [blame] | 851 | } |
Nathaniel | 7bf36ad | 1999-10-24 19:35:47 +0000 | [diff] [blame] | 852 | break; |
| 853 | default: |
| 854 | ERR_(reg)("unknown/invalid key handle !\n"); |
| 855 | break; |
Sylvain St.Germain | e533222 | 1999-04-10 16:46:15 +0000 | [diff] [blame] | 856 | } |
Andreas Mohr | d4b13da | 1999-08-07 14:17:10 +0000 | [diff] [blame] | 857 | } |
| 858 | |
| 859 | |
| 860 | /****************************************************************************** |
| 861 | * SHELL_SaveRegistry [Internal] |
| 862 | */ |
| 863 | void SHELL_SaveRegistry( void ) |
| 864 | { |
| 865 | char buf[4]; |
| 866 | HKEY hkey; |
| 867 | int all; |
| 868 | |
| 869 | TRACE_(reg)("(void)\n"); |
| 870 | |
| 871 | all=0; |
| 872 | if (RegOpenKey16(HKEY_CURRENT_USER,KEY_REGISTRY,&hkey)!=ERROR_SUCCESS) |
| 873 | { |
| 874 | strcpy(buf,"yes"); |
| 875 | } |
| 876 | else |
| 877 | { |
| 878 | DWORD len,junk,type; |
| 879 | |
| 880 | len=4; |
| 881 | if ((ERROR_SUCCESS!=RegQueryValueExA( hkey, |
| 882 | VAL_SAVEUPDATED, |
| 883 | &junk, |
| 884 | &type, |
| 885 | buf, |
| 886 | &len)) || (type!=REG_SZ)) |
| 887 | { |
| 888 | strcpy(buf,"yes"); |
| 889 | } |
| 890 | RegCloseKey(hkey); |
| 891 | } |
| 892 | |
| 893 | if (lstrcmpiA(buf,"yes")) |
| 894 | all = 1; |
| 895 | |
| 896 | SHELL_SaveRegistryBranch(HKEY_CURRENT_USER, all); |
| 897 | SHELL_SaveRegistryBranch(HKEY_LOCAL_MACHINE, all); |
| 898 | SHELL_SaveRegistryBranch(HKEY_USERS, all); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 899 | } |
| 900 | |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 901 | |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 902 | /************************ LOAD Registry Function ****************************/ |
| 903 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 904 | |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 905 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 906 | /****************************************************************************** |
| 907 | * _find_or_add_key [Internal] |
| 908 | */ |
| 909 | static LPKEYSTRUCT _find_or_add_key( LPKEYSTRUCT lpkey, LPWSTR keyname ) |
| 910 | { |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 911 | LPKEYSTRUCT lpxkey,*lplpkey; |
| 912 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 913 | if ((!keyname) || (keyname[0]==0)) { |
Alexandre Julliard | a11d7b1 | 1998-03-01 20:05:02 +0000 | [diff] [blame] | 914 | free(keyname); |
| 915 | return lpkey; |
| 916 | } |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 917 | lplpkey= &(lpkey->nextsub); |
| 918 | lpxkey = *lplpkey; |
| 919 | while (lpxkey) { |
Marcus Meissner | f2ef145 | 1999-06-26 11:41:33 +0000 | [diff] [blame] | 920 | if ( tolower(lpxkey->keyname[0])==tolower(keyname[0]) && |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 921 | !lstrcmpiW(lpxkey->keyname,keyname) |
Alexandre Julliard | a0d7731 | 1998-09-13 16:32:00 +0000 | [diff] [blame] | 922 | ) |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 923 | break; |
| 924 | lplpkey = &(lpxkey->next); |
| 925 | lpxkey = *lplpkey; |
| 926 | } |
| 927 | if (lpxkey==NULL) { |
| 928 | *lplpkey = (LPKEYSTRUCT)xmalloc(sizeof(KEYSTRUCT)); |
| 929 | lpxkey = *lplpkey; |
| 930 | memset(lpxkey,'\0',sizeof(KEYSTRUCT)); |
| 931 | lpxkey->keyname = keyname; |
| 932 | } else |
| 933 | free(keyname); |
| 934 | return lpxkey; |
| 935 | } |
| 936 | |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 937 | /****************************************************************************** |
| 938 | * _find_or_add_value [Internal] |
| 939 | */ |
| 940 | static void _find_or_add_value( LPKEYSTRUCT lpkey, LPWSTR name, DWORD type, |
| 941 | LPBYTE data, DWORD len, DWORD lastmodified ) |
| 942 | { |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 943 | LPKEYVALUE val=NULL; |
| 944 | int i; |
| 945 | |
Alexandre Julliard | 0623a6f | 1998-01-18 18:01:49 +0000 | [diff] [blame] | 946 | if (name && !*name) {/* empty string equals default (NULL) value */ |
| 947 | free(name); |
| 948 | name = NULL; |
| 949 | } |
| 950 | |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 951 | for (i=0;i<lpkey->nrofvalues;i++) { |
| 952 | val=lpkey->values+i; |
| 953 | if (name==NULL) { |
| 954 | if (val->name==NULL) |
| 955 | break; |
| 956 | } else { |
Marcus Meissner | f2ef145 | 1999-06-26 11:41:33 +0000 | [diff] [blame] | 957 | if ( val->name!=NULL && |
| 958 | tolower(val->name[0])==tolower(name[0]) && |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 959 | !lstrcmpiW(val->name,name) |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 960 | ) |
| 961 | break; |
| 962 | } |
| 963 | } |
| 964 | if (i==lpkey->nrofvalues) { |
| 965 | lpkey->values = xrealloc( |
| 966 | lpkey->values, |
| 967 | (++lpkey->nrofvalues)*sizeof(KEYVALUE) |
| 968 | ); |
| 969 | val=lpkey->values+i; |
| 970 | memset(val,'\0',sizeof(KEYVALUE)); |
| 971 | val->name = name; |
| 972 | } else { |
| 973 | if (name) |
| 974 | free(name); |
| 975 | } |
| 976 | if (val->lastmodified<lastmodified) { |
| 977 | val->lastmodified=lastmodified; |
| 978 | val->type = type; |
Noomen Hamza | 9adef53 | 1999-04-24 11:49:26 +0000 | [diff] [blame] | 979 | |
| 980 | if ((type == REG_SZ || type == REG_EXPAND_SZ) && !data){ |
| 981 | |
| 982 | data=xmalloc(sizeof(WCHAR)); |
| 983 | memset(data,0,sizeof(WCHAR)); |
| 984 | len =sizeof(WCHAR); |
| 985 | } |
| 986 | |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 987 | val->len = len; |
| 988 | if (val->data) |
| 989 | free(val->data); |
| 990 | val->data = data; |
| 991 | } else |
| 992 | free(data); |
| 993 | } |
| 994 | |
| 995 | |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 996 | /****************************************************************************** |
| 997 | * _wine_read_line [Internal] |
| 998 | * |
| 999 | * reads a line including dynamically enlarging the readbuffer and throwing |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 1000 | * away comments |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 1001 | */ |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 1002 | static int _wine_read_line( FILE *F, char **buf, int *len ) |
| 1003 | { |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 1004 | char *s,*curread; |
| 1005 | int mylen,curoff; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 1006 | |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 1007 | curread = *buf; |
| 1008 | mylen = *len; |
| 1009 | **buf = '\0'; |
| 1010 | while (1) { |
| 1011 | while (1) { |
| 1012 | s=fgets(curread,mylen,F); |
| 1013 | if (s==NULL) |
| 1014 | return 0; /* EOF */ |
| 1015 | if (NULL==(s=strchr(curread,'\n'))) { |
| 1016 | /* buffer wasn't large enough */ |
| 1017 | curoff = strlen(*buf); |
| 1018 | *buf = xrealloc(*buf,*len*2); |
| 1019 | curread = *buf + curoff; |
| 1020 | mylen = *len; /* we filled up the buffer and |
| 1021 | * got new '*len' bytes to fill |
| 1022 | */ |
| 1023 | *len = *len * 2; |
| 1024 | } else { |
| 1025 | *s='\0'; |
| 1026 | break; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 1027 | } |
| 1028 | } |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 1029 | /* throw away comments */ |
| 1030 | if (**buf=='#' || **buf==';') { |
| 1031 | curread = *buf; |
| 1032 | mylen = *len; |
| 1033 | continue; |
| 1034 | } |
| 1035 | if (s) /* got end of line */ |
| 1036 | break; |
| 1037 | } |
| 1038 | return 1; |
| 1039 | } |
| 1040 | |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 1041 | |
| 1042 | /****************************************************************************** |
| 1043 | * _wine_read_USTRING [Internal] |
| 1044 | * |
| 1045 | * converts a char* into a UNICODE string (up to a special char) |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 1046 | * and returns the position exactly after that string |
| 1047 | */ |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 1048 | static char* _wine_read_USTRING( char *buf, LPWSTR *str ) |
| 1049 | { |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 1050 | char *s; |
| 1051 | LPWSTR ws; |
| 1052 | |
| 1053 | /* read up to "=" or "\0" or "\n" */ |
| 1054 | s = buf; |
| 1055 | if (*s == '=') { |
| 1056 | /* empty string is the win3.1 default value(NULL)*/ |
| 1057 | *str = NULL; |
| 1058 | return s; |
| 1059 | } |
| 1060 | *str = (LPWSTR)xmalloc(2*strlen(buf)+2); |
| 1061 | ws = *str; |
| 1062 | while (*s && (*s!='\n') && (*s!='=')) { |
| 1063 | if (*s!='\\') |
| 1064 | *ws++=*((unsigned char*)s++); |
| 1065 | else { |
| 1066 | s++; |
Alexandre Julliard | 638f169 | 1999-01-17 16:32:32 +0000 | [diff] [blame] | 1067 | if (!*s) { |
| 1068 | /* Dangling \ ... may only happen if a registry |
| 1069 | * write was short. FIXME: What do to? |
| 1070 | */ |
| 1071 | break; |
| 1072 | } |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 1073 | if (*s=='\\') { |
Alexandre Julliard | 84c70f5 | 1997-05-09 08:40:27 +0000 | [diff] [blame] | 1074 | *ws++='\\'; |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 1075 | s++; |
| 1076 | continue; |
| 1077 | } |
| 1078 | if (*s!='u') { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 1079 | WARN_(reg)("Non unicode escape sequence \\%c found in |%s|\n",*s,buf); |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 1080 | *ws++='\\'; |
| 1081 | *ws++=*s++; |
| 1082 | } else { |
| 1083 | char xbuf[5]; |
| 1084 | int wc; |
| 1085 | |
| 1086 | s++; |
| 1087 | memcpy(xbuf,s,4);xbuf[4]='\0'; |
| 1088 | if (!sscanf(xbuf,"%x",&wc)) |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 1089 | WARN_(reg)("Strange escape sequence %s found in |%s|\n",xbuf,buf); |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 1090 | s+=4; |
| 1091 | *ws++ =(unsigned short)wc; |
| 1092 | } |
| 1093 | } |
| 1094 | } |
| 1095 | *ws = 0; |
| 1096 | ws = *str; |
Alexandre Julliard | 0623a6f | 1998-01-18 18:01:49 +0000 | [diff] [blame] | 1097 | if (*ws) |
| 1098 | *str = strdupW(*str); |
| 1099 | else |
| 1100 | *str = NULL; |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 1101 | free(ws); |
| 1102 | return s; |
| 1103 | } |
| 1104 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 1105 | |
| 1106 | /****************************************************************************** |
| 1107 | * _wine_loadsubkey [Internal] |
| 1108 | * |
| 1109 | * NOTES |
| 1110 | * It seems like this is returning a boolean. Should it? |
| 1111 | * |
| 1112 | * RETURNS |
| 1113 | * Success: 1 |
| 1114 | * Failure: 0 |
| 1115 | */ |
| 1116 | static int _wine_loadsubkey( FILE *F, LPKEYSTRUCT lpkey, int level, char **buf, |
| 1117 | int *buflen, DWORD optflag ) |
| 1118 | { |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1119 | LPKEYSTRUCT lpxkey; |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 1120 | int i; |
| 1121 | char *s; |
| 1122 | LPWSTR name; |
| 1123 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 1124 | TRACE_(reg)("(%p,%p,%d,%s,%d,%lx)\n", F, lpkey, level, debugstr_a(*buf), |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 1125 | *buflen, optflag); |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1126 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 1127 | lpkey->flags |= optflag; |
| 1128 | |
| 1129 | /* Good. We already got a line here ... so parse it */ |
| 1130 | lpxkey = NULL; |
| 1131 | while (1) { |
| 1132 | i=0;s=*buf; |
| 1133 | while (*s=='\t') { |
| 1134 | s++; |
| 1135 | i++; |
| 1136 | } |
| 1137 | if (i>level) { |
| 1138 | if (lpxkey==NULL) { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 1139 | WARN_(reg)("Got a subhierarchy without resp. key?\n"); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 1140 | return 0; |
| 1141 | } |
Eric Pouech | c0bcf26 | 1999-11-04 01:38:11 +0000 | [diff] [blame] | 1142 | if (!_wine_loadsubkey(F,lpxkey,level+1,buf,buflen,optflag)) |
| 1143 | if (!_wine_read_line(F,buf,buflen)) |
| 1144 | return 1; |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 1145 | continue; |
| 1146 | } |
| 1147 | |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 1148 | /* let the caller handle this line */ |
| 1149 | if (i<level || **buf=='\0') |
| 1150 | return 1; |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1151 | |
| 1152 | /* it can be: a value or a keyname. Parse the name first */ |
| 1153 | s=_wine_read_USTRING(s,&name); |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 1154 | |
| 1155 | /* switch() default: hack to avoid gotos */ |
| 1156 | switch (0) { |
| 1157 | default: |
| 1158 | if (*s=='\0') { |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1159 | lpxkey=_find_or_add_key(lpkey,name); |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 1160 | } else { |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 1161 | LPBYTE data; |
| 1162 | int len,lastmodified,type; |
| 1163 | |
| 1164 | if (*s!='=') { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 1165 | WARN_(reg)("Unexpected character: %c\n",*s); |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 1166 | break; |
| 1167 | } |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 1168 | s++; |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 1169 | if (2!=sscanf(s,"%d,%d,",&type,&lastmodified)) { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 1170 | WARN_(reg)("Haven't understood possible value in |%s|, skipping.\n",*buf); |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 1171 | break; |
| 1172 | } |
| 1173 | /* skip the 2 , */ |
| 1174 | s=strchr(s,',');s++; |
Eric Pouech | c0bcf26 | 1999-11-04 01:38:11 +0000 | [diff] [blame] | 1175 | s=strchr(s,','); |
| 1176 | if (!s++) { |
| 1177 | WARN_(reg)("Haven't understood possible value in |%s|, skipping.\n",*buf); |
| 1178 | break; |
| 1179 | } |
Juergen Schmied | f74fa4e | 1999-01-31 09:19:46 +0000 | [diff] [blame] | 1180 | if (type == REG_SZ || type == REG_EXPAND_SZ) { |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1181 | s=_wine_read_USTRING(s,(LPWSTR*)&data); |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 1182 | if (data) |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1183 | len = lstrlenW((LPWSTR)data)*2+2; |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 1184 | else |
| 1185 | len = 0; |
| 1186 | } else { |
| 1187 | len=strlen(s)/2; |
| 1188 | data = (LPBYTE)xmalloc(len+1); |
| 1189 | for (i=0;i<len;i++) { |
| 1190 | data[i]=0; |
| 1191 | if (*s>='0' && *s<='9') |
| 1192 | data[i]=(*s-'0')<<4; |
| 1193 | if (*s>='a' && *s<='f') |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 1194 | data[i]=(*s-'a'+'\xa')<<4; |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 1195 | if (*s>='A' && *s<='F') |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 1196 | data[i]=(*s-'A'+'\xa')<<4; |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 1197 | s++; |
| 1198 | if (*s>='0' && *s<='9') |
| 1199 | data[i]|=*s-'0'; |
| 1200 | if (*s>='a' && *s<='f') |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 1201 | data[i]|=*s-'a'+'\xa'; |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 1202 | if (*s>='A' && *s<='F') |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 1203 | data[i]|=*s-'A'+'\xa'; |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 1204 | s++; |
| 1205 | } |
| 1206 | } |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1207 | _find_or_add_value(lpkey,name,type,data,len,lastmodified); |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 1208 | } |
| 1209 | } |
| 1210 | /* read the next line */ |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1211 | if (!_wine_read_line(F,buf,buflen)) |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 1212 | return 1; |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 1213 | } |
| 1214 | return 1; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 1215 | } |
| 1216 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 1217 | |
| 1218 | /****************************************************************************** |
| 1219 | * _wine_loadsubreg [Internal] |
| 1220 | */ |
| 1221 | static int _wine_loadsubreg( FILE *F, LPKEYSTRUCT lpkey, DWORD optflag ) |
| 1222 | { |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 1223 | int ver; |
| 1224 | char *buf; |
| 1225 | int buflen; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 1226 | |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 1227 | buf=xmalloc(10);buflen=10; |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1228 | if (!_wine_read_line(F,&buf,&buflen)) { |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 1229 | free(buf); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 1230 | return 0; |
| 1231 | } |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 1232 | if (!sscanf(buf,"WINE REGISTRY Version %d",&ver)) { |
| 1233 | free(buf); |
| 1234 | return 0; |
| 1235 | } |
| 1236 | if (ver!=REGISTRY_SAVE_VERSION) { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 1237 | TRACE_(reg)("Old format (%d) registry found, ignoring it. (buf was %s).\n",ver,buf); |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 1238 | free(buf); |
| 1239 | return 0; |
| 1240 | } |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1241 | if (!_wine_read_line(F,&buf,&buflen)) { |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 1242 | free(buf); |
| 1243 | return 0; |
| 1244 | } |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1245 | if (!_wine_loadsubkey(F,lpkey,0,&buf,&buflen,optflag)) { |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 1246 | free(buf); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 1247 | return 0; |
| 1248 | } |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 1249 | free(buf); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 1250 | return 1; |
| 1251 | } |
| 1252 | |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 1253 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 1254 | /****************************************************************************** |
| 1255 | * _wine_loadreg [Internal] |
| 1256 | */ |
| 1257 | static void _wine_loadreg( LPKEYSTRUCT lpkey, char *fn, DWORD optflag ) |
| 1258 | { |
| 1259 | FILE *F; |
| 1260 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 1261 | TRACE_(reg)("(%p,%s,%lx)\n",lpkey,debugstr_a(fn),optflag); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 1262 | |
| 1263 | F = fopen(fn,"rb"); |
| 1264 | if (F==NULL) { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 1265 | WARN_(reg)("Couldn't open %s for reading: %s\n",fn,strerror(errno) ); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 1266 | return; |
| 1267 | } |
| 1268 | if (!_wine_loadsubreg(F,lpkey,optflag)) { |
| 1269 | fclose(F); |
| 1270 | unlink(fn); |
| 1271 | return; |
| 1272 | } |
| 1273 | fclose(F); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 1274 | } |
| 1275 | |
Sylvain St.Germain | e533222 | 1999-04-10 16:46:15 +0000 | [diff] [blame] | 1276 | /****************************************************************************** |
| 1277 | * _flush_registry [Internal] |
| 1278 | * |
| 1279 | * This function allow to flush section of the internal registry. It is mainly |
| 1280 | * implements to fix a problem with the global HKU and the local HKU. |
| 1281 | * Those two files are read to build the HKU\.Default branch to finaly copy |
| 1282 | * this branch onto HKCU hive, once this is done, if we keep the HKU hive as is, |
| 1283 | * all the global HKU are saved onto the user's personal version of HKU hive. |
| 1284 | * which is bad... |
| 1285 | */ |
| 1286 | |
| 1287 | /* Forward declaration of recusive agent */ |
| 1288 | static void _flush_reg(LPKEYSTRUCT from); |
| 1289 | |
| 1290 | static void _flush_registry( LPKEYSTRUCT from ) |
| 1291 | { |
| 1292 | /* make sure we have something... */ |
| 1293 | if (from == NULL) |
| 1294 | return; |
| 1295 | |
| 1296 | /* Launch the recusive agent on sub branches */ |
| 1297 | _flush_reg( from->nextsub ); |
| 1298 | _flush_reg( from->next ); |
| 1299 | |
| 1300 | /* Initialize pointers */ |
| 1301 | from->nextsub = NULL; |
| 1302 | from->next = NULL; |
| 1303 | } |
| 1304 | static void _flush_reg( LPKEYSTRUCT from ) |
| 1305 | { |
| 1306 | int j; |
| 1307 | |
| 1308 | /* make sure we have something... */ |
| 1309 | if (from == NULL) |
| 1310 | return; |
| 1311 | |
| 1312 | /* |
| 1313 | * do the same for the child keys |
| 1314 | */ |
| 1315 | if (from->nextsub != NULL) |
| 1316 | _flush_reg(from->nextsub); |
| 1317 | |
| 1318 | /* |
| 1319 | * do the same for the sibling keys |
| 1320 | */ |
| 1321 | if (from->next != NULL) |
| 1322 | _flush_reg(from->next); |
| 1323 | |
| 1324 | /* |
| 1325 | * iterate through this key's values and delete them |
| 1326 | */ |
| 1327 | for (j=0;j<from->nrofvalues;j++) |
| 1328 | { |
| 1329 | free( (from->values+j)->name); |
| 1330 | free( (from->values+j)->data); |
| 1331 | } |
| 1332 | |
| 1333 | /* |
| 1334 | * free the structure |
| 1335 | */ |
| 1336 | if ( from != NULL ) |
| 1337 | free(from); |
| 1338 | } |
| 1339 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 1340 | |
| 1341 | /****************************************************************************** |
| 1342 | * _copy_registry [Internal] |
| 1343 | */ |
| 1344 | static void _copy_registry( LPKEYSTRUCT from, LPKEYSTRUCT to ) |
| 1345 | { |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1346 | LPKEYSTRUCT lpxkey; |
| 1347 | int j; |
| 1348 | LPKEYVALUE valfrom; |
| 1349 | |
| 1350 | from=from->nextsub; |
| 1351 | while (from) { |
| 1352 | lpxkey = _find_or_add_key(to,strdupW(from->keyname)); |
| 1353 | |
| 1354 | for (j=0;j<from->nrofvalues;j++) { |
| 1355 | LPWSTR name; |
| 1356 | LPBYTE data; |
| 1357 | |
| 1358 | valfrom = from->values+j; |
| 1359 | name=valfrom->name; |
| 1360 | if (name) name=strdupW(name); |
Alexandre Julliard | a11d7b1 | 1998-03-01 20:05:02 +0000 | [diff] [blame] | 1361 | data=(LPBYTE)xmalloc(valfrom->len); |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1362 | memcpy(data,valfrom->data,valfrom->len); |
| 1363 | |
| 1364 | _find_or_add_value( |
| 1365 | lpxkey, |
| 1366 | name, |
| 1367 | valfrom->type, |
| 1368 | data, |
| 1369 | valfrom->len, |
| 1370 | valfrom->lastmodified |
| 1371 | ); |
| 1372 | } |
| 1373 | _copy_registry(from,lpxkey); |
| 1374 | from = from->next; |
| 1375 | } |
| 1376 | } |
| 1377 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 1378 | |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1379 | /* WINDOWS 95 REGISTRY LOADER */ |
| 1380 | /* |
| 1381 | * Structure of a win95 registry database. |
| 1382 | * main header: |
| 1383 | * 0 : "CREG" - magic |
| 1384 | * 4 : DWORD version |
| 1385 | * 8 : DWORD offset_of_RGDB_part |
Alexandre Julliard | 02e9008 | 1998-01-04 17:49:09 +0000 | [diff] [blame] | 1386 | * 0C..0F: ? (someone fill in please) |
| 1387 | * 10: WORD number of RGDB blocks |
| 1388 | * 12: WORD ? |
| 1389 | * 14: WORD always 0000? |
| 1390 | * 16: WORD always 0001? |
| 1391 | * 18..1F: ? (someone fill in please) |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1392 | * |
| 1393 | * 20: RGKN_section: |
| 1394 | * header: |
| 1395 | * 0 : "RGKN" - magic |
Alexandre Julliard | 02e9008 | 1998-01-04 17:49:09 +0000 | [diff] [blame] | 1396 | * 4 : DWORD offset to first RGDB section |
Alexandre Julliard | a0d7731 | 1998-09-13 16:32:00 +0000 | [diff] [blame] | 1397 | * 8 : DWORD offset to the root record |
Alexandre Julliard | 02e9008 | 1998-01-04 17:49:09 +0000 | [diff] [blame] | 1398 | * C..0x1B: ? (fill in) |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1399 | * 0x20 ... offset_of_RGDB_part: Disk Key Entry structures |
| 1400 | * |
| 1401 | * Disk Key Entry Structure: |
Alexandre Julliard | 60ce85c | 1998-02-01 18:33:27 +0000 | [diff] [blame] | 1402 | * 00: DWORD - Free entry indicator(?) |
| 1403 | * 04: DWORD - Hash = sum of bytes of keyname |
| 1404 | * 08: DWORD - Root key indicator? unknown, but usually 0xFFFFFFFF on win95 systems |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1405 | * 0C: DWORD - disk address of PreviousLevel Key. |
| 1406 | * 10: DWORD - disk address of Next Sublevel Key. |
| 1407 | * 14: DWORD - disk address of Next Key (on same level). |
| 1408 | * DKEP>18: WORD - Nr, Low Significant part. |
| 1409 | * 1A: WORD - Nr, High Significant part. |
| 1410 | * |
| 1411 | * The disk address always points to the nr part of the previous key entry |
| 1412 | * of the referenced key. Don't ask me why, or even if I got this correct |
| 1413 | * from staring at 1kg of hexdumps. (DKEP) |
| 1414 | * |
Alexandre Julliard | 60ce85c | 1998-02-01 18:33:27 +0000 | [diff] [blame] | 1415 | * The High significant part of the structure seems to equal the number |
| 1416 | * of the RGDB section. The low significant part is a unique ID within |
| 1417 | * that RGDB section |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1418 | * |
| 1419 | * There are two minor corrections to the position of that structure. |
| 1420 | * 1. If the address is xxx014 or xxx018 it will be aligned to xxx01c AND |
| 1421 | * the DKE reread from there. |
| 1422 | * 2. If the address is xxxFFx it will be aligned to (xxx+1)000. |
Alexandre Julliard | 60ce85c | 1998-02-01 18:33:27 +0000 | [diff] [blame] | 1423 | * CPS - I have not experienced the above phenomenon in my registry files |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1424 | * |
| 1425 | * RGDB_section: |
| 1426 | * 00: "RGDB" - magic |
Alexandre Julliard | 02e9008 | 1998-01-04 17:49:09 +0000 | [diff] [blame] | 1427 | * 04: DWORD offset to next RGDB section |
| 1428 | * 08: DWORD ? |
| 1429 | * 0C: WORD always 000d? |
| 1430 | * 0E: WORD RGDB block number |
| 1431 | * 10: DWORD ? (equals value at offset 4 - value at offset 8) |
| 1432 | * 14..1F: ? |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1433 | * 20.....: disk keys |
| 1434 | * |
| 1435 | * disk key: |
| 1436 | * 00: DWORD nextkeyoffset - offset to the next disk key structure |
| 1437 | * 08: WORD nrLS - low significant part of NR |
| 1438 | * 0A: WORD nrHS - high significant part of NR |
| 1439 | * 0C: DWORD bytesused - bytes used in this structure. |
| 1440 | * 10: WORD name_len - length of name in bytes. without \0 |
| 1441 | * 12: WORD nr_of_values - number of values. |
| 1442 | * 14: char name[name_len] - name string. No \0. |
| 1443 | * 14+name_len: disk values |
| 1444 | * nextkeyoffset: ... next disk key |
| 1445 | * |
| 1446 | * disk value: |
| 1447 | * 00: DWORD type - value type (hmm, could be WORD too) |
| 1448 | * 04: DWORD - unknown, usually 0 |
| 1449 | * 08: WORD namelen - length of Name. 0 means name=NULL |
| 1450 | * 0C: WORD datalen - length of Data. |
| 1451 | * 10: char name[namelen] - name, no \0 |
| 1452 | * 10+namelen: BYTE data[datalen] - data, without \0 if string |
| 1453 | * 10+namelen+datalen: next values or disk key |
| 1454 | * |
| 1455 | * Disk keys are layed out flat ... But, sometimes, nrLS and nrHS are both |
| 1456 | * 0xFFFF, which means skipping over nextkeyoffset bytes (including this |
| 1457 | * structure) and reading another RGDB_section. |
| 1458 | * repeat until end of file. |
| 1459 | * |
Alexandre Julliard | 02e9008 | 1998-01-04 17:49:09 +0000 | [diff] [blame] | 1460 | * An interesting relationship exists in RGDB_section. The value at offset |
| 1461 | * 10 equals the value at offset 4 minus the value at offset 8. I have no |
| 1462 | * idea at the moment what this means. (Kevin Cozens) |
| 1463 | * |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1464 | * FIXME: this description needs some serious help, yes. |
| 1465 | */ |
| 1466 | |
| 1467 | struct _w95keyvalue { |
| 1468 | unsigned long type; |
| 1469 | unsigned short datalen; |
| 1470 | char *name; |
| 1471 | unsigned char *data; |
| 1472 | unsigned long x1; |
| 1473 | int lastmodified; |
| 1474 | }; |
| 1475 | |
| 1476 | struct _w95key { |
| 1477 | char *name; |
| 1478 | int nrofvals; |
| 1479 | struct _w95keyvalue *values; |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1480 | struct _w95key *prevlvl; |
| 1481 | struct _w95key *nextsub; |
| 1482 | struct _w95key *next; |
| 1483 | }; |
| 1484 | |
Alexandre Julliard | 60ce85c | 1998-02-01 18:33:27 +0000 | [diff] [blame] | 1485 | |
| 1486 | struct _w95_info { |
| 1487 | char *rgknbuffer; |
| 1488 | int rgknsize; |
| 1489 | char *rgdbbuffer; |
| 1490 | int rgdbsize; |
| 1491 | int depth; |
| 1492 | int lastmodified; |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1493 | }; |
| 1494 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 1495 | |
| 1496 | /****************************************************************************** |
| 1497 | * _w95_processKey [Internal] |
| 1498 | */ |
Alexandre Julliard | 60ce85c | 1998-02-01 18:33:27 +0000 | [diff] [blame] | 1499 | static LPKEYSTRUCT _w95_processKey ( LPKEYSTRUCT lpkey, |
| 1500 | int nrLS, int nrMS, struct _w95_info *info ) |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1501 | |
Alexandre Julliard | 60ce85c | 1998-02-01 18:33:27 +0000 | [diff] [blame] | 1502 | { |
| 1503 | /* Disk Key Header structure (RGDB part) */ |
Alexandre Julliard | a11d7b1 | 1998-03-01 20:05:02 +0000 | [diff] [blame] | 1504 | struct dkh { |
Alexandre Julliard | 60ce85c | 1998-02-01 18:33:27 +0000 | [diff] [blame] | 1505 | unsigned long nextkeyoff; |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1506 | unsigned short nrLS; |
| 1507 | unsigned short nrMS; |
| 1508 | unsigned long bytesused; |
| 1509 | unsigned short keynamelen; |
| 1510 | unsigned short values; |
| 1511 | unsigned long xx1; |
| 1512 | /* keyname */ |
| 1513 | /* disk key values or nothing */ |
| 1514 | }; |
| 1515 | /* Disk Key Value structure */ |
| 1516 | struct dkv { |
| 1517 | unsigned long type; |
| 1518 | unsigned long x1; |
| 1519 | unsigned short valnamelen; |
| 1520 | unsigned short valdatalen; |
| 1521 | /* valname, valdata */ |
| 1522 | }; |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1523 | |
Alexandre Julliard | 60ce85c | 1998-02-01 18:33:27 +0000 | [diff] [blame] | 1524 | |
| 1525 | struct dkh dkh; |
| 1526 | int bytesread = 0; |
| 1527 | char *rgdbdata = info->rgdbbuffer; |
| 1528 | int nbytes = info->rgdbsize; |
| 1529 | char *curdata = rgdbdata; |
| 1530 | char *end = rgdbdata + nbytes; |
| 1531 | int off_next_rgdb; |
| 1532 | char *next = rgdbdata; |
| 1533 | int nrgdb, i; |
| 1534 | LPKEYSTRUCT lpxkey; |
| 1535 | |
| 1536 | do { |
| 1537 | curdata = next; |
| 1538 | if (strncmp(curdata, "RGDB", 4)) return (NULL); |
| 1539 | |
| 1540 | memcpy(&off_next_rgdb,curdata+4,4); |
| 1541 | next = curdata + off_next_rgdb; |
| 1542 | nrgdb = (int) *((short *)curdata + 7); |
| 1543 | |
| 1544 | } while (nrgdb != nrMS && (next < end)); |
| 1545 | |
| 1546 | /* curdata now points to the start of the right RGDB section */ |
| 1547 | curdata += 0x20; |
| 1548 | |
| 1549 | #define XREAD(whereto,len) \ |
David Gay | 6f0056d | 1999-04-11 12:00:15 +0000 | [diff] [blame] | 1550 | if ((curdata + len) <= end) {\ |
Alexandre Julliard | 60ce85c | 1998-02-01 18:33:27 +0000 | [diff] [blame] | 1551 | memcpy(whereto,curdata,len);\ |
| 1552 | curdata+=len;\ |
| 1553 | bytesread+=len;\ |
| 1554 | } |
| 1555 | |
Alexandre Julliard | a0d7731 | 1998-09-13 16:32:00 +0000 | [diff] [blame] | 1556 | while (curdata < next) { |
Marcus Meissner | f4f1719 | 1998-10-17 12:10:19 +0000 | [diff] [blame] | 1557 | struct dkh *xdkh = (struct dkh*)curdata; |
Alexandre Julliard | 60ce85c | 1998-02-01 18:33:27 +0000 | [diff] [blame] | 1558 | |
Alexandre Julliard | a0d7731 | 1998-09-13 16:32:00 +0000 | [diff] [blame] | 1559 | bytesread += sizeof(dkh); /* FIXME... nextkeyoff? */ |
| 1560 | if (xdkh->nrLS == nrLS) { |
| 1561 | memcpy(&dkh,xdkh,sizeof(dkh)); |
| 1562 | curdata += sizeof(dkh); |
| 1563 | break; |
| 1564 | } |
| 1565 | curdata += xdkh->nextkeyoff; |
| 1566 | }; |
Alexandre Julliard | 60ce85c | 1998-02-01 18:33:27 +0000 | [diff] [blame] | 1567 | |
| 1568 | if (dkh.nrLS != nrLS) return (NULL); |
| 1569 | |
Alexandre Julliard | a0d7731 | 1998-09-13 16:32:00 +0000 | [diff] [blame] | 1570 | if (nrgdb != dkh.nrMS) |
Alexandre Julliard | 60ce85c | 1998-02-01 18:33:27 +0000 | [diff] [blame] | 1571 | return (NULL); |
Alexandre Julliard | 60ce85c | 1998-02-01 18:33:27 +0000 | [diff] [blame] | 1572 | |
Alexandre Julliard | a11d7b1 | 1998-03-01 20:05:02 +0000 | [diff] [blame] | 1573 | assert((dkh.keynamelen<2) || curdata[0]); |
Alexandre Julliard | 60ce85c | 1998-02-01 18:33:27 +0000 | [diff] [blame] | 1574 | lpxkey=_find_or_add_key(lpkey,strcvtA2W(curdata, dkh.keynamelen)); |
| 1575 | curdata += dkh.keynamelen; |
| 1576 | |
| 1577 | for (i=0;i< dkh.values; i++) { |
| 1578 | struct dkv dkv; |
| 1579 | LPBYTE data; |
| 1580 | int len; |
| 1581 | LPWSTR name; |
| 1582 | |
| 1583 | XREAD(&dkv,sizeof(dkv)); |
| 1584 | |
| 1585 | name = strcvtA2W(curdata, dkv.valnamelen); |
| 1586 | curdata += dkv.valnamelen; |
| 1587 | |
| 1588 | if ((1 << dkv.type) & UNICONVMASK) { |
| 1589 | data = (LPBYTE) strcvtA2W(curdata, dkv.valdatalen); |
Alexandre Julliard | a69b88b | 1998-03-15 20:29:56 +0000 | [diff] [blame] | 1590 | len = 2*(dkv.valdatalen + 1); |
Alexandre Julliard | 60ce85c | 1998-02-01 18:33:27 +0000 | [diff] [blame] | 1591 | } else { |
| 1592 | /* I don't think we want to NULL terminate all data */ |
| 1593 | data = xmalloc(dkv.valdatalen); |
| 1594 | memcpy (data, curdata, dkv.valdatalen); |
| 1595 | len = dkv.valdatalen; |
| 1596 | } |
| 1597 | |
| 1598 | curdata += dkv.valdatalen; |
| 1599 | |
| 1600 | _find_or_add_value( |
| 1601 | lpxkey, |
| 1602 | name, |
| 1603 | dkv.type, |
| 1604 | data, |
| 1605 | len, |
| 1606 | info->lastmodified |
| 1607 | ); |
Alexandre Julliard | 60ce85c | 1998-02-01 18:33:27 +0000 | [diff] [blame] | 1608 | } |
Alexandre Julliard | 60ce85c | 1998-02-01 18:33:27 +0000 | [diff] [blame] | 1609 | return (lpxkey); |
| 1610 | } |
| 1611 | |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 1612 | /****************************************************************************** |
| 1613 | * _w95_walkrgkn [Internal] |
| 1614 | */ |
| 1615 | static void _w95_walkrgkn( LPKEYSTRUCT prevkey, char *off, |
| 1616 | struct _w95_info *info ) |
Alexandre Julliard | 60ce85c | 1998-02-01 18:33:27 +0000 | [diff] [blame] | 1617 | |
| 1618 | { |
| 1619 | /* Disk Key Entry structure (RGKN part) */ |
| 1620 | struct dke { |
| 1621 | unsigned long x1; |
| 1622 | unsigned long x2; |
| 1623 | unsigned long x3;/*usually 0xFFFFFFFF */ |
| 1624 | unsigned long prevlvl; |
| 1625 | unsigned long nextsub; |
| 1626 | unsigned long next; |
| 1627 | unsigned short nrLS; |
| 1628 | unsigned short nrMS; |
| 1629 | } *dke = (struct dke *)off; |
| 1630 | LPKEYSTRUCT lpxkey; |
| 1631 | |
| 1632 | if (dke == NULL) { |
| 1633 | dke = (struct dke *) ((char *)info->rgknbuffer); |
| 1634 | } |
| 1635 | |
| 1636 | lpxkey = _w95_processKey(prevkey, dke->nrLS, dke->nrMS, info); |
| 1637 | /* XXX <-- This is a hack*/ |
| 1638 | if (!lpxkey) { |
| 1639 | lpxkey = prevkey; |
| 1640 | } |
| 1641 | |
| 1642 | if (dke->nextsub != -1 && |
| 1643 | ((dke->nextsub - 0x20) < info->rgknsize) |
| 1644 | && (dke->nextsub > 0x20)) { |
| 1645 | |
| 1646 | _w95_walkrgkn(lpxkey, |
| 1647 | info->rgknbuffer + dke->nextsub - 0x20, |
| 1648 | info); |
| 1649 | } |
| 1650 | |
| 1651 | if (dke->next != -1 && |
| 1652 | ((dke->next - 0x20) < info->rgknsize) && |
| 1653 | (dke->next > 0x20)) { |
| 1654 | _w95_walkrgkn(prevkey, |
| 1655 | info->rgknbuffer + dke->next - 0x20, |
| 1656 | info); |
| 1657 | } |
| 1658 | |
| 1659 | return; |
| 1660 | } |
| 1661 | |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 1662 | |
| 1663 | /****************************************************************************** |
| 1664 | * _w95_loadreg [Internal] |
| 1665 | */ |
| 1666 | static void _w95_loadreg( char* fn, LPKEYSTRUCT lpkey ) |
| 1667 | { |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1668 | HFILE hfd; |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1669 | char magic[5]; |
Alexandre Julliard | 60ce85c | 1998-02-01 18:33:27 +0000 | [diff] [blame] | 1670 | unsigned long where,version,rgdbsection,end; |
| 1671 | struct _w95_info info; |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1672 | OFSTRUCT ofs; |
Alexandre Julliard | 8bbf818 | 1996-09-13 16:50:47 +0000 | [diff] [blame] | 1673 | BY_HANDLE_FILE_INFORMATION hfdinfo; |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1674 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 1675 | TRACE_(reg)("Loading Win95 registry database '%s'\n",fn); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1676 | hfd=OpenFile(fn,&ofs,OF_READ); |
| 1677 | if (hfd==HFILE_ERROR) |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1678 | return; |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1679 | magic[4]=0; |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1680 | if (4!=_lread(hfd,magic,4)) |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1681 | return; |
| 1682 | if (strcmp(magic,"CREG")) { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 1683 | WARN_(reg)("%s is not a w95 registry.\n",fn); |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1684 | return; |
| 1685 | } |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1686 | if (4!=_lread(hfd,&version,4)) |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1687 | return; |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1688 | if (4!=_lread(hfd,&rgdbsection,4)) |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1689 | return; |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1690 | if (-1==_llseek(hfd,0x20,SEEK_SET)) |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1691 | return; |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1692 | if (4!=_lread(hfd,magic,4)) |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1693 | return; |
| 1694 | if (strcmp(magic,"RGKN")) { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 1695 | WARN_(reg)("second IFF header not RGKN, but %s\n", magic); |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1696 | return; |
| 1697 | } |
| 1698 | |
| 1699 | /* STEP 1: Keylink structures */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1700 | if (-1==_llseek(hfd,0x40,SEEK_SET)) |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1701 | return; |
| 1702 | where = 0x40; |
| 1703 | end = rgdbsection; |
| 1704 | |
Alexandre Julliard | 60ce85c | 1998-02-01 18:33:27 +0000 | [diff] [blame] | 1705 | info.rgknsize = end - where; |
| 1706 | info.rgknbuffer = (char*)xmalloc(info.rgknsize); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1707 | if (info.rgknsize != _lread(hfd,info.rgknbuffer,info.rgknsize)) |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1708 | return; |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1709 | |
Alexandre Julliard | 8bbf818 | 1996-09-13 16:50:47 +0000 | [diff] [blame] | 1710 | if (!GetFileInformationByHandle(hfd,&hfdinfo)) |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1711 | return; |
Alexandre Julliard | 60ce85c | 1998-02-01 18:33:27 +0000 | [diff] [blame] | 1712 | |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 1713 | end = hfdinfo.nFileSizeLow; |
Alexandre Julliard | 60ce85c | 1998-02-01 18:33:27 +0000 | [diff] [blame] | 1714 | info.lastmodified = DOSFS_FileTimeToUnixTime(&hfdinfo.ftLastWriteTime,NULL); |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1715 | |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1716 | if (-1==_llseek(hfd,rgdbsection,SEEK_SET)) |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1717 | return; |
Alexandre Julliard | 60ce85c | 1998-02-01 18:33:27 +0000 | [diff] [blame] | 1718 | |
| 1719 | info.rgdbbuffer = (char*)xmalloc(end-rgdbsection); |
| 1720 | info.rgdbsize = end - rgdbsection; |
| 1721 | |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1722 | if (info.rgdbsize !=_lread(hfd,info.rgdbbuffer,info.rgdbsize)) |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1723 | return; |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1724 | _lclose(hfd); |
Alexandre Julliard | 02e9008 | 1998-01-04 17:49:09 +0000 | [diff] [blame] | 1725 | |
Alexandre Julliard | 60ce85c | 1998-02-01 18:33:27 +0000 | [diff] [blame] | 1726 | _w95_walkrgkn(lpkey, NULL, &info); |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1727 | |
Alexandre Julliard | 60ce85c | 1998-02-01 18:33:27 +0000 | [diff] [blame] | 1728 | free (info.rgdbbuffer); |
| 1729 | free (info.rgknbuffer); |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1730 | } |
| 1731 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 1732 | |
Alexandre Julliard | da0cfb3 | 1996-12-01 17:17:47 +0000 | [diff] [blame] | 1733 | /* WINDOWS 31 REGISTRY LOADER, supplied by Tor Sjøwall, tor@sn.no */ |
| 1734 | |
| 1735 | /* |
| 1736 | reghack - windows 3.11 registry data format demo program. |
| 1737 | |
| 1738 | The reg.dat file has 3 parts, a header, a table of 8-byte entries that is |
| 1739 | a combined hash table and tree description, and finally a text table. |
| 1740 | |
| 1741 | The header is obvious from the struct header. The taboff1 and taboff2 |
| 1742 | fields are always 0x20, and their usage is unknown. |
| 1743 | |
| 1744 | The 8-byte entry table has various entry types. |
| 1745 | |
| 1746 | tabent[0] is a root index. The second word has the index of the root of |
| 1747 | the directory. |
| 1748 | tabent[1..hashsize] is a hash table. The first word in the hash entry is |
| 1749 | the index of the key/value that has that hash. Data with the same |
| 1750 | hash value are on a circular list. The other three words in the |
| 1751 | hash entry are always zero. |
| 1752 | tabent[hashsize..tabcnt] is the tree structure. There are two kinds of |
| 1753 | entry: dirent and keyent/valent. They are identified by context. |
| 1754 | tabent[freeidx] is the first free entry. The first word in a free entry |
| 1755 | is the index of the next free entry. The last has 0 as a link. |
| 1756 | The other three words in the free list are probably irrelevant. |
| 1757 | |
| 1758 | Entries in text table are preceeded by a word at offset-2. This word |
| 1759 | has the value (2*index)+1, where index is the referring keyent/valent |
| 1760 | entry in the table. I have no suggestion for the 2* and the +1. |
| 1761 | Following the word, there are N bytes of data, as per the keyent/valent |
| 1762 | entry length. The offset of the keyent/valent entry is from the start |
| 1763 | of the text table to the first data byte. |
| 1764 | |
| 1765 | This information is not available from Microsoft. The data format is |
| 1766 | deduced from the reg.dat file by me. Mistakes may |
| 1767 | have been made. I claim no rights and give no guarantees for this program. |
| 1768 | |
| 1769 | Tor Sjøwall, tor@sn.no |
| 1770 | */ |
| 1771 | |
| 1772 | /* reg.dat header format */ |
| 1773 | struct _w31_header { |
| 1774 | char cookie[8]; /* 'SHCC3.10' */ |
| 1775 | unsigned long taboff1; /* offset of hash table (??) = 0x20 */ |
| 1776 | unsigned long taboff2; /* offset of index table (??) = 0x20 */ |
| 1777 | unsigned long tabcnt; /* number of entries in index table */ |
| 1778 | unsigned long textoff; /* offset of text part */ |
| 1779 | unsigned long textsize; /* byte size of text part */ |
| 1780 | unsigned short hashsize; /* hash size */ |
| 1781 | unsigned short freeidx; /* free index */ |
| 1782 | }; |
| 1783 | |
| 1784 | /* generic format of table entries */ |
| 1785 | struct _w31_tabent { |
| 1786 | unsigned short w0, w1, w2, w3; |
| 1787 | }; |
| 1788 | |
| 1789 | /* directory tabent: */ |
| 1790 | struct _w31_dirent { |
| 1791 | unsigned short sibling_idx; /* table index of sibling dirent */ |
| 1792 | unsigned short child_idx; /* table index of child dirent */ |
| 1793 | unsigned short key_idx; /* table index of key keyent */ |
| 1794 | unsigned short value_idx; /* table index of value valent */ |
| 1795 | }; |
| 1796 | |
| 1797 | /* key tabent: */ |
| 1798 | struct _w31_keyent { |
| 1799 | unsigned short hash_idx; /* hash chain index for string */ |
| 1800 | unsigned short refcnt; /* reference count */ |
| 1801 | unsigned short length; /* length of string */ |
| 1802 | unsigned short string_off; /* offset of string in text table */ |
| 1803 | }; |
| 1804 | |
| 1805 | /* value tabent: */ |
| 1806 | struct _w31_valent { |
| 1807 | unsigned short hash_idx; /* hash chain index for string */ |
| 1808 | unsigned short refcnt; /* reference count */ |
| 1809 | unsigned short length; /* length of string */ |
| 1810 | unsigned short string_off; /* offset of string in text table */ |
| 1811 | }; |
| 1812 | |
| 1813 | /* recursive helper function to display a directory tree */ |
| 1814 | void |
| 1815 | __w31_dumptree( unsigned short idx, |
| 1816 | unsigned char *txt, |
| 1817 | struct _w31_tabent *tab, |
| 1818 | struct _w31_header *head, |
| 1819 | LPKEYSTRUCT lpkey, |
| 1820 | time_t lastmodified, |
| 1821 | int level |
| 1822 | ) { |
| 1823 | struct _w31_dirent *dir; |
| 1824 | struct _w31_keyent *key; |
| 1825 | struct _w31_valent *val; |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 1826 | LPKEYSTRUCT xlpkey = NULL; |
Alexandre Julliard | da0cfb3 | 1996-12-01 17:17:47 +0000 | [diff] [blame] | 1827 | LPWSTR name,value; |
| 1828 | static char tail[400]; |
| 1829 | |
| 1830 | while (idx!=0) { |
| 1831 | dir=(struct _w31_dirent*)&tab[idx]; |
| 1832 | |
| 1833 | if (dir->key_idx) { |
| 1834 | key = (struct _w31_keyent*)&tab[dir->key_idx]; |
| 1835 | |
| 1836 | memcpy(tail,&txt[key->string_off],key->length); |
| 1837 | tail[key->length]='\0'; |
| 1838 | /* all toplevel entries AND the entries in the |
| 1839 | * toplevel subdirectory belong to \SOFTWARE\Classes |
| 1840 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1841 | if (!level && !lstrcmpA(tail,".classes")) { |
Alexandre Julliard | da0cfb3 | 1996-12-01 17:17:47 +0000 | [diff] [blame] | 1842 | __w31_dumptree(dir->child_idx,txt,tab,head,lpkey,lastmodified,level+1); |
| 1843 | idx=dir->sibling_idx; |
| 1844 | continue; |
| 1845 | } |
Alexandre Julliard | e658d82 | 1997-11-30 17:45:40 +0000 | [diff] [blame] | 1846 | name=strdupA2W(tail); |
Alexandre Julliard | da0cfb3 | 1996-12-01 17:17:47 +0000 | [diff] [blame] | 1847 | |
| 1848 | xlpkey=_find_or_add_key(lpkey,name); |
| 1849 | |
| 1850 | /* only add if leaf node or valued node */ |
| 1851 | if (dir->value_idx!=0||dir->child_idx==0) { |
| 1852 | if (dir->value_idx) { |
| 1853 | val=(struct _w31_valent*)&tab[dir->value_idx]; |
| 1854 | memcpy(tail,&txt[val->string_off],val->length); |
| 1855 | tail[val->length]='\0'; |
Alexandre Julliard | e658d82 | 1997-11-30 17:45:40 +0000 | [diff] [blame] | 1856 | value=strdupA2W(tail); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1857 | _find_or_add_value(xlpkey,NULL,REG_SZ,(LPBYTE)value,lstrlenW(value)*2+2,lastmodified); |
Alexandre Julliard | da0cfb3 | 1996-12-01 17:17:47 +0000 | [diff] [blame] | 1858 | } |
| 1859 | } |
| 1860 | } else { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 1861 | TRACE_(reg)("strange: no directory key name, idx=%04x\n", idx); |
Alexandre Julliard | da0cfb3 | 1996-12-01 17:17:47 +0000 | [diff] [blame] | 1862 | } |
| 1863 | __w31_dumptree(dir->child_idx,txt,tab,head,xlpkey,lastmodified,level+1); |
| 1864 | idx=dir->sibling_idx; |
| 1865 | } |
| 1866 | } |
| 1867 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 1868 | |
| 1869 | /****************************************************************************** |
| 1870 | * _w31_loadreg [Internal] |
| 1871 | */ |
Juergen Schmied | ebc2b77 | 1998-11-14 18:59:30 +0000 | [diff] [blame] | 1872 | void _w31_loadreg(void) { |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1873 | HFILE hf; |
Alexandre Julliard | da0cfb3 | 1996-12-01 17:17:47 +0000 | [diff] [blame] | 1874 | struct _w31_header head; |
| 1875 | struct _w31_tabent *tab; |
| 1876 | unsigned char *txt; |
| 1877 | int len; |
| 1878 | OFSTRUCT ofs; |
| 1879 | BY_HANDLE_FILE_INFORMATION hfinfo; |
| 1880 | time_t lastmodified; |
Alexandre Julliard | da0cfb3 | 1996-12-01 17:17:47 +0000 | [diff] [blame] | 1881 | LPKEYSTRUCT lpkey; |
| 1882 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 1883 | TRACE_(reg)("(void)\n"); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 1884 | |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1885 | hf = OpenFile("reg.dat",&ofs,OF_READ); |
| 1886 | if (hf==HFILE_ERROR) |
Alexandre Julliard | da0cfb3 | 1996-12-01 17:17:47 +0000 | [diff] [blame] | 1887 | return; |
| 1888 | |
| 1889 | /* read & dump header */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1890 | if (sizeof(head)!=_lread(hf,&head,sizeof(head))) { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 1891 | ERR_(reg)("reg.dat is too short.\n"); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1892 | _lclose(hf); |
Alexandre Julliard | da0cfb3 | 1996-12-01 17:17:47 +0000 | [diff] [blame] | 1893 | return; |
| 1894 | } |
| 1895 | if (memcmp(head.cookie, "SHCC3.10", sizeof(head.cookie))!=0) { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 1896 | ERR_(reg)("reg.dat has bad signature.\n"); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1897 | _lclose(hf); |
Alexandre Julliard | da0cfb3 | 1996-12-01 17:17:47 +0000 | [diff] [blame] | 1898 | return; |
| 1899 | } |
| 1900 | |
| 1901 | len = head.tabcnt * sizeof(struct _w31_tabent); |
| 1902 | /* read and dump index table */ |
| 1903 | tab = xmalloc(len); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1904 | if (len!=_lread(hf,tab,len)) { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 1905 | ERR_(reg)("couldn't read %d bytes.\n",len); |
Alexandre Julliard | da0cfb3 | 1996-12-01 17:17:47 +0000 | [diff] [blame] | 1906 | free(tab); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1907 | _lclose(hf); |
Alexandre Julliard | da0cfb3 | 1996-12-01 17:17:47 +0000 | [diff] [blame] | 1908 | return; |
| 1909 | } |
| 1910 | |
| 1911 | /* read text */ |
| 1912 | txt = xmalloc(head.textsize); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1913 | if (-1==_llseek(hf,head.textoff,SEEK_SET)) { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 1914 | ERR_(reg)("couldn't seek to textblock.\n"); |
Alexandre Julliard | da0cfb3 | 1996-12-01 17:17:47 +0000 | [diff] [blame] | 1915 | free(tab); |
| 1916 | free(txt); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1917 | _lclose(hf); |
Alexandre Julliard | da0cfb3 | 1996-12-01 17:17:47 +0000 | [diff] [blame] | 1918 | return; |
| 1919 | } |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1920 | if (head.textsize!=_lread(hf,txt,head.textsize)) { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 1921 | ERR_(reg)("textblock too short (%d instead of %ld).\n",len,head.textsize); |
Alexandre Julliard | da0cfb3 | 1996-12-01 17:17:47 +0000 | [diff] [blame] | 1922 | free(tab); |
| 1923 | free(txt); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1924 | _lclose(hf); |
Alexandre Julliard | da0cfb3 | 1996-12-01 17:17:47 +0000 | [diff] [blame] | 1925 | return; |
| 1926 | } |
| 1927 | |
| 1928 | if (!GetFileInformationByHandle(hf,&hfinfo)) { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 1929 | ERR_(reg)("GetFileInformationByHandle failed?.\n"); |
Alexandre Julliard | da0cfb3 | 1996-12-01 17:17:47 +0000 | [diff] [blame] | 1930 | free(tab); |
| 1931 | free(txt); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1932 | _lclose(hf); |
Alexandre Julliard | da0cfb3 | 1996-12-01 17:17:47 +0000 | [diff] [blame] | 1933 | return; |
| 1934 | } |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 1935 | lastmodified = DOSFS_FileTimeToUnixTime(&hfinfo.ftLastWriteTime,NULL); |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 1936 | lpkey = lookup_hkey(HKEY_CLASSES_ROOT); |
Alexandre Julliard | da0cfb3 | 1996-12-01 17:17:47 +0000 | [diff] [blame] | 1937 | __w31_dumptree(tab[0].w1,txt,tab,&head,lpkey,lastmodified,0); |
| 1938 | free(tab); |
| 1939 | free(txt); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1940 | _lclose(hf); |
Alexandre Julliard | da0cfb3 | 1996-12-01 17:17:47 +0000 | [diff] [blame] | 1941 | return; |
| 1942 | } |
| 1943 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 1944 | |
| 1945 | /********************************************************************************** |
| 1946 | * SHELL_LoadRegistry [Internal] |
| 1947 | */ |
| 1948 | void SHELL_LoadRegistry( void ) |
| 1949 | { |
Alexandre Julliard | 154c99b | 1999-04-25 12:41:36 +0000 | [diff] [blame] | 1950 | char *fn, *home; |
Sylvain St.Germain | e533222 | 1999-04-10 16:46:15 +0000 | [diff] [blame] | 1951 | LPKEYSTRUCT lpkey, HKCU, HKU, HKLM; |
| 1952 | HKEY hkey; |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1953 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 1954 | TRACE_(reg)("(void)\n"); |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 1955 | |
Sylvain St.Germain | e533222 | 1999-04-10 16:46:15 +0000 | [diff] [blame] | 1956 | HKCU = lookup_hkey(HKEY_CURRENT_USER); |
| 1957 | HKU = lookup_hkey(HKEY_USERS); |
| 1958 | HKLM = lookup_hkey(HKEY_LOCAL_MACHINE); |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1959 | |
Nathaniel | 7bf36ad | 1999-10-24 19:35:47 +0000 | [diff] [blame] | 1960 | if (PROFILE_GetWineIniBool ("registry", "LoadWindowsRegistryFiles", 1)) |
| 1961 | { |
| 1962 | /* Load windows 3.1 entries */ |
| 1963 | _w31_loadreg(); |
| 1964 | /* Load windows 95 entries */ |
| 1965 | _w95_loadreg("C:\\system.1st", HKLM); |
| 1966 | _w95_loadreg("system.dat", HKLM); |
| 1967 | _w95_loadreg("user.dat", HKU); |
| 1968 | } |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1969 | |
Nathaniel | 7bf36ad | 1999-10-24 19:35:47 +0000 | [diff] [blame] | 1970 | if (PROFILE_GetWineIniBool ("registry","LoadGlobalRegistryFiles", 1)) |
| 1971 | { |
| 1972 | /* |
| 1973 | * Load the global HKU hive directly from sysconfdir |
| 1974 | */ |
| 1975 | _wine_loadreg( HKU, SAVE_USERS_DEFAULT, 0); |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1976 | |
Nathaniel | 7bf36ad | 1999-10-24 19:35:47 +0000 | [diff] [blame] | 1977 | /* |
| 1978 | * Load the global machine defaults directly form sysconfdir |
| 1979 | */ |
| 1980 | _wine_loadreg( HKLM, SAVE_LOCAL_MACHINE_DEFAULT, 0); |
| 1981 | } |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 1982 | |
Sylvain St.Germain | e533222 | 1999-04-10 16:46:15 +0000 | [diff] [blame] | 1983 | /* |
| 1984 | * Load the user saved registries |
| 1985 | */ |
Nathaniel | 7bf36ad | 1999-10-24 19:35:47 +0000 | [diff] [blame] | 1986 | if (!(home = getenv( "HOME" ))) |
| 1987 | WARN_(reg)("Failed to get homedirectory of UID %ld.\n",(long) getuid()); |
Marcus Meissner | 31b9dab | 1999-10-24 22:08:33 +0000 | [diff] [blame] | 1988 | else if (PROFILE_GetWineIniBool("registry", "LoadHomeRegistryFiles", 1)) |
Sylvain St.Germain | e533222 | 1999-04-10 16:46:15 +0000 | [diff] [blame] | 1989 | { |
Nathaniel | 7bf36ad | 1999-10-24 19:35:47 +0000 | [diff] [blame] | 1990 | /* |
| 1991 | * Load user's personal versions of global HKU/.Default keys |
| 1992 | */ |
| 1993 | fn=(char*)xmalloc( strlen(home)+ strlen(WINE_PREFIX) + |
| 1994 | strlen(SAVE_LOCAL_USERS_DEFAULT)+2); |
| 1995 | strcpy(fn, home); |
| 1996 | strcat(fn, WINE_PREFIX"/"SAVE_LOCAL_USERS_DEFAULT); |
| 1997 | _wine_loadreg(HKU, fn, REG_OPTION_TAINTED); |
| 1998 | free(fn); |
Nathan Zorich | bd3771c | 1999-03-14 15:12:48 +0000 | [diff] [blame] | 1999 | |
Nathaniel | 7bf36ad | 1999-10-24 19:35:47 +0000 | [diff] [blame] | 2000 | fn=(char*)xmalloc( strlen(home) + strlen(WINE_PREFIX) + strlen(SAVE_CURRENT_USER)+2); |
| 2001 | strcpy(fn, home); |
| 2002 | strcat(fn, WINE_PREFIX"/"SAVE_CURRENT_USER); |
| 2003 | _wine_loadreg(HKCU, fn, REG_OPTION_TAINTED); |
| 2004 | free(fn); |
Nathan Zorich | bd3771c | 1999-03-14 15:12:48 +0000 | [diff] [blame] | 2005 | |
Nathaniel | 7bf36ad | 1999-10-24 19:35:47 +0000 | [diff] [blame] | 2006 | /* |
| 2007 | * Load HKLM, attempt to get the registry location from the config |
| 2008 | * file first, if exist, load and keep going. |
| 2009 | */ |
| 2010 | fn=(char*)xmalloc( strlen(home)+ strlen(WINE_PREFIX)+ strlen(SAVE_LOCAL_MACHINE)+2); |
| 2011 | strcpy(fn,home); |
| 2012 | strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_MACHINE); |
| 2013 | _wine_loadreg(HKLM, fn, REG_OPTION_TAINTED); |
| 2014 | free(fn); |
Sylvain St.Germain | e533222 | 1999-04-10 16:46:15 +0000 | [diff] [blame] | 2015 | } |
Nathaniel | 7bf36ad | 1999-10-24 19:35:47 +0000 | [diff] [blame] | 2016 | |
| 2017 | /* |
| 2018 | * Load HKCU, get the registry location from the config |
| 2019 | * file, if exist, load and keep going. |
| 2020 | */ |
| 2021 | if (PROFILE_GetWineIniBool ( "registry", "LoadAltRegistryFiles", 1)) |
Sylvain St.Germain | e533222 | 1999-04-10 16:46:15 +0000 | [diff] [blame] | 2022 | { |
Nathaniel | 7bf36ad | 1999-10-24 19:35:47 +0000 | [diff] [blame] | 2023 | fn = xmalloc( MAX_PATHNAME_LEN ); |
| 2024 | if ( PROFILE_GetWineIniString( "registry", "AltCurrentUserFile", "", |
| 2025 | fn, MAX_PATHNAME_LEN - 1)) |
| 2026 | { |
| 2027 | _wine_loadreg(HKCU,fn,REG_OPTION_TAINTED); |
| 2028 | } |
| 2029 | free (fn); |
| 2030 | /* |
| 2031 | * Load HKU, get the registry location from the config |
| 2032 | * file, if exist, load and keep going. |
| 2033 | */ |
| 2034 | fn = xmalloc ( MAX_PATHNAME_LEN ); |
| 2035 | if ( PROFILE_GetWineIniString ( "registry", "AltUserFile", "", |
| 2036 | fn, MAX_PATHNAME_LEN - 1)) |
| 2037 | { |
| 2038 | _wine_loadreg(HKU,fn,REG_OPTION_TAINTED); |
| 2039 | } |
| 2040 | free (fn); |
| 2041 | /* |
| 2042 | * Load HKLM, get the registry location from the config |
| 2043 | * file, if exist, load and keep going. |
| 2044 | */ |
| 2045 | fn = xmalloc ( MAX_PATHNAME_LEN ); |
| 2046 | if (PROFILE_GetWineIniString ( "registry", "AltLocalMachineFile", "", |
| 2047 | fn, MAX_PATHNAME_LEN - 1)) |
| 2048 | { |
| 2049 | _wine_loadreg(HKLM,fn,REG_OPTION_TAINTED); |
| 2050 | } |
| 2051 | free (fn); |
| 2052 | } |
| 2053 | |
Sylvain St.Germain | e533222 | 1999-04-10 16:46:15 +0000 | [diff] [blame] | 2054 | /* |
| 2055 | * Obtain the handle of the HKU\.Default key. |
| 2056 | * in order to copy HKU\.Default\* onto HKEY_CURRENT_USER |
| 2057 | */ |
| 2058 | RegCreateKey16(HKEY_USERS,".Default",&hkey); |
| 2059 | lpkey = lookup_hkey(hkey); |
Nathaniel | 7bf36ad | 1999-10-24 19:35:47 +0000 | [diff] [blame] | 2060 | if(!lpkey){ |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2061 | WARN_(reg)("Could not create global user default key\n"); |
Nathaniel | 7bf36ad | 1999-10-24 19:35:47 +0000 | [diff] [blame] | 2062 | } else { |
Sylvain St.Germain | e533222 | 1999-04-10 16:46:15 +0000 | [diff] [blame] | 2063 | _copy_registry(lpkey, HKCU ); |
Nathaniel | 7bf36ad | 1999-10-24 19:35:47 +0000 | [diff] [blame] | 2064 | } |
Sylvain St.Germain | e533222 | 1999-04-10 16:46:15 +0000 | [diff] [blame] | 2065 | |
| 2066 | RegCloseKey(hkey); |
| 2067 | |
| 2068 | /* |
| 2069 | * Since HKU is built from the global HKU and the local user HKU file we must |
| 2070 | * flush the HKU tree we have built at this point otherwise the part brought |
| 2071 | * in from the global HKU is saved into the local HKU. To avoid this |
| 2072 | * useless dupplication of HKU keys we reread the local HKU key. |
| 2073 | */ |
| 2074 | |
| 2075 | /* Allways flush the HKU hive and reload it only with user's personal HKU */ |
| 2076 | _flush_registry(HKU); |
| 2077 | |
| 2078 | /* Reload user's local HKU hive */ |
Nathaniel | 7bf36ad | 1999-10-24 19:35:47 +0000 | [diff] [blame] | 2079 | if (home && PROFILE_GetWineIniBool ("registry","LoadHomeRegistryFiles",1)) |
Alexandre Julliard | 154c99b | 1999-04-25 12:41:36 +0000 | [diff] [blame] | 2080 | { |
| 2081 | fn=(char*)xmalloc( strlen(home) + strlen(WINE_PREFIX) |
| 2082 | + strlen(SAVE_LOCAL_USERS_DEFAULT) + 2); |
| 2083 | |
| 2084 | strcpy(fn,home); |
| 2085 | strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_USERS_DEFAULT); |
Sylvain St.Germain | e533222 | 1999-04-10 16:46:15 +0000 | [diff] [blame] | 2086 | |
Alexandre Julliard | 154c99b | 1999-04-25 12:41:36 +0000 | [diff] [blame] | 2087 | _wine_loadreg( HKU, fn, REG_OPTION_TAINTED); |
Sylvain St.Germain | e533222 | 1999-04-10 16:46:15 +0000 | [diff] [blame] | 2088 | |
Alexandre Julliard | 154c99b | 1999-04-25 12:41:36 +0000 | [diff] [blame] | 2089 | free(fn); |
| 2090 | } |
Sylvain St.Germain | e533222 | 1999-04-10 16:46:15 +0000 | [diff] [blame] | 2091 | |
| 2092 | /* |
| 2093 | * Make sure the update mode is there |
| 2094 | */ |
| 2095 | if (ERROR_SUCCESS==RegCreateKey16(HKEY_CURRENT_USER,KEY_REGISTRY,&hkey)) |
| 2096 | { |
| 2097 | DWORD junk,type,len; |
| 2098 | char data[5]; |
| 2099 | |
| 2100 | len=4; |
| 2101 | if (( RegQueryValueExA( |
| 2102 | hkey, |
| 2103 | VAL_SAVEUPDATED, |
| 2104 | &junk, |
| 2105 | &type, |
| 2106 | data, |
| 2107 | &len) != ERROR_SUCCESS) || (type != REG_SZ)) |
| 2108 | { |
| 2109 | RegSetValueExA(hkey,VAL_SAVEUPDATED,0,REG_SZ,"yes",4); |
| 2110 | } |
| 2111 | |
| 2112 | RegCloseKey(hkey); |
| 2113 | } |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2114 | } |
| 2115 | |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2116 | |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 2117 | /********************* API FUNCTIONS ***************************************/ |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2118 | /* |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 2119 | * Open Keys. |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2120 | * |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 2121 | * All functions are stubs to RegOpenKeyEx32W where all the |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2122 | * magic happens. |
| 2123 | * |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2124 | * Callpath: |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 2125 | * RegOpenKey16 -> RegOpenKey32A -> RegOpenKeyEx32A \ |
| 2126 | * RegOpenKey32W -> RegOpenKeyEx32W |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2127 | */ |
| 2128 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2129 | |
| 2130 | /****************************************************************************** |
| 2131 | * RegOpenKeyEx32W [ADVAPI32.150] |
| 2132 | * Opens the specified key |
| 2133 | * |
| 2134 | * Unlike RegCreateKeyEx, this does not create the key if it does not exist. |
| 2135 | * |
| 2136 | * PARAMS |
| 2137 | * hkey [I] Handle of open key |
| 2138 | * lpszSubKey [I] Name of subkey to open |
| 2139 | * dwReserved [I] Reserved - must be zero |
| 2140 | * samDesired [I] Security access mask |
| 2141 | * retkey [O] Address of handle of open key |
| 2142 | * |
| 2143 | * RETURNS |
| 2144 | * Success: ERROR_SUCCESS |
| 2145 | * Failure: Error code |
| 2146 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2147 | DWORD WINAPI RegOpenKeyExW( HKEY hkey, LPCWSTR lpszSubKey, DWORD dwReserved, |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2148 | REGSAM samDesired, LPHKEY retkey ) |
| 2149 | { |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2150 | LPKEYSTRUCT lpNextKey,lpxkey; |
| 2151 | LPWSTR *wps; |
| 2152 | int wpc,i; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2153 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2154 | TRACE_(reg)("(0x%x,%s,%ld,%lx,%p)\n", hkey,debugstr_w(lpszSubKey),dwReserved, |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2155 | samDesired,retkey); |
| 2156 | |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 2157 | lpNextKey = lookup_hkey( hkey ); |
| 2158 | if (!lpNextKey) |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2159 | return ERROR_INVALID_HANDLE; |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2160 | |
| 2161 | if (!lpszSubKey || !*lpszSubKey) { |
| 2162 | /* Either NULL or pointer to empty string, so return a new handle |
| 2163 | to the original hkey */ |
Alexandre Julliard | 85ed45e | 1998-08-22 19:03:56 +0000 | [diff] [blame] | 2164 | currenthandle += 2; |
| 2165 | add_handle(currenthandle,lpNextKey,samDesired); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2166 | *retkey=currenthandle; |
| 2167 | return ERROR_SUCCESS; |
| 2168 | } |
| 2169 | |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 2170 | if (lpszSubKey[0] == '\\') { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2171 | WARN_(reg)("Subkey %s must not begin with backslash.\n",debugstr_w(lpszSubKey)); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 2172 | return ERROR_BAD_PATHNAME; |
| 2173 | } |
| 2174 | |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2175 | split_keypath(lpszSubKey,&wps,&wpc); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2176 | i = 0; |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 2177 | while ((i<wpc) && (wps[i][0]=='\0')) i++; |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2178 | lpxkey = lpNextKey; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2179 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2180 | while (wps[i]) { |
| 2181 | lpxkey=lpNextKey->nextsub; |
| 2182 | while (lpxkey) { |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2183 | if (!lstrcmpiW(wps[i],lpxkey->keyname)) { |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2184 | break; |
| 2185 | } |
| 2186 | lpxkey=lpxkey->next; |
| 2187 | } |
| 2188 | |
| 2189 | if (!lpxkey) { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2190 | TRACE_(reg)("Could not find subkey %s\n",debugstr_w(wps[i])); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2191 | FREE_KEY_PATH; |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 2192 | return ERROR_FILE_NOT_FOUND; |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2193 | } |
| 2194 | i++; |
| 2195 | lpNextKey = lpxkey; |
| 2196 | } |
| 2197 | |
Alexandre Julliard | 85ed45e | 1998-08-22 19:03:56 +0000 | [diff] [blame] | 2198 | currenthandle += 2; |
| 2199 | add_handle(currenthandle,lpxkey,samDesired); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2200 | *retkey = currenthandle; |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2201 | TRACE_(reg)(" Returning %x\n", currenthandle); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2202 | FREE_KEY_PATH; |
| 2203 | return ERROR_SUCCESS; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2204 | } |
| 2205 | |
| 2206 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2207 | /****************************************************************************** |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2208 | * RegOpenKeyEx32A [ADVAPI32.149] |
| 2209 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2210 | DWORD WINAPI RegOpenKeyExA( HKEY hkey, LPCSTR lpszSubKey, DWORD dwReserved, |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2211 | REGSAM samDesired, LPHKEY retkey ) |
| 2212 | { |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 2213 | LPWSTR lpszSubKeyW = strdupA2W(lpszSubKey); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2214 | DWORD ret; |
| 2215 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2216 | TRACE_(reg)("(%x,%s,%ld,%lx,%p)\n",hkey,debugstr_a(lpszSubKey),dwReserved, |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2217 | samDesired,retkey); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2218 | ret = RegOpenKeyExW( hkey, lpszSubKeyW, dwReserved, samDesired, retkey ); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 2219 | free(lpszSubKeyW); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2220 | return ret; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2221 | } |
| 2222 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2223 | |
| 2224 | /****************************************************************************** |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 2225 | * RegOpenKey32W [ADVAPI32.151] |
| 2226 | * |
| 2227 | * PARAMS |
| 2228 | * hkey [I] Handle of open key |
| 2229 | * lpszSubKey [I] Address of name of subkey to open |
| 2230 | * retkey [O] Address of handle of open key |
| 2231 | * |
| 2232 | * RETURNS |
| 2233 | * Success: ERROR_SUCCESS |
| 2234 | * Failure: Error code |
| 2235 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2236 | DWORD WINAPI RegOpenKeyW( HKEY hkey, LPCWSTR lpszSubKey, LPHKEY retkey ) |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 2237 | { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2238 | TRACE_(reg)("(%x,%s,%p)\n",hkey,debugstr_w(lpszSubKey),retkey); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2239 | return RegOpenKeyExW( hkey, lpszSubKey, 0, KEY_ALL_ACCESS, retkey ); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 2240 | } |
| 2241 | |
| 2242 | |
| 2243 | /****************************************************************************** |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2244 | * RegOpenKey32A [ADVAPI32.148] |
| 2245 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2246 | DWORD WINAPI RegOpenKeyA( HKEY hkey, LPCSTR lpszSubKey, LPHKEY retkey ) |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2247 | { |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 2248 | DWORD ret; |
| 2249 | LPWSTR lpszSubKeyW = strdupA2W(lpszSubKey); |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2250 | TRACE_(reg)("(%x,%s,%p)\n",hkey,debugstr_a(lpszSubKey),retkey); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2251 | ret = RegOpenKeyW( hkey, lpszSubKeyW, retkey ); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 2252 | free(lpszSubKeyW); |
| 2253 | return ret; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2254 | } |
| 2255 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2256 | |
| 2257 | /****************************************************************************** |
| 2258 | * RegOpenKey16 [SHELL.1] [KERNEL.217] |
| 2259 | */ |
| 2260 | DWORD WINAPI RegOpenKey16( HKEY hkey, LPCSTR lpszSubKey, LPHKEY retkey ) |
| 2261 | { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2262 | TRACE_(reg)("(%x,%s,%p)\n",hkey,debugstr_a(lpszSubKey),retkey); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2263 | return RegOpenKeyA( hkey, lpszSubKey, retkey ); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2264 | } |
| 2265 | |
| 2266 | |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2267 | /* |
| 2268 | * Create keys |
| 2269 | * |
| 2270 | * All those functions convert their respective |
| 2271 | * arguments and call RegCreateKeyExW at the end. |
| 2272 | * |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 2273 | * We stay away from the Ex functions as long as possible because there are |
| 2274 | * differences in the return values |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2275 | * |
| 2276 | * Callpath: |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 2277 | * RegCreateKeyEx32A \ |
| 2278 | * RegCreateKey16 -> RegCreateKey32A -> RegCreateKey32W -> RegCreateKeyEx32W |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2279 | */ |
| 2280 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2281 | |
| 2282 | /****************************************************************************** |
| 2283 | * RegCreateKeyEx32W [ADVAPI32.131] |
| 2284 | * |
| 2285 | * PARAMS |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 2286 | * hkey [I] Handle of an open key |
| 2287 | * lpszSubKey [I] Address of subkey name |
| 2288 | * dwReserved [I] Reserved - must be 0 |
| 2289 | * lpszClass [I] Address of class string |
| 2290 | * fdwOptions [I] Special options flag |
| 2291 | * samDesired [I] Desired security access |
| 2292 | * lpSecAttribs [I] Address of key security structure |
| 2293 | * retkey [O] Address of buffer for opened handle |
| 2294 | * lpDispos [O] Receives REG_CREATED_NEW_KEY or REG_OPENED_EXISTING_KEY |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2295 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2296 | DWORD WINAPI RegCreateKeyExW( HKEY hkey, LPCWSTR lpszSubKey, |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2297 | DWORD dwReserved, LPWSTR lpszClass, |
| 2298 | DWORD fdwOptions, REGSAM samDesired, |
| 2299 | LPSECURITY_ATTRIBUTES lpSecAttribs, |
| 2300 | LPHKEY retkey, LPDWORD lpDispos ) |
| 2301 | { |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2302 | LPKEYSTRUCT *lplpPrevKey,lpNextKey,lpxkey; |
| 2303 | LPWSTR *wps; |
| 2304 | int wpc,i; |
| 2305 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2306 | TRACE_(reg)("(%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n", hkey, |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2307 | debugstr_w(lpszSubKey), dwReserved, debugstr_w(lpszClass), |
| 2308 | fdwOptions, samDesired, lpSecAttribs, retkey, lpDispos); |
| 2309 | |
| 2310 | lpNextKey = lookup_hkey(hkey); |
| 2311 | if (!lpNextKey) |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 2312 | return ERROR_INVALID_HANDLE; |
| 2313 | |
| 2314 | /* Check for valid options */ |
| 2315 | switch(fdwOptions) { |
| 2316 | case REG_OPTION_NON_VOLATILE: |
| 2317 | case REG_OPTION_VOLATILE: |
| 2318 | case REG_OPTION_BACKUP_RESTORE: |
| 2319 | break; |
| 2320 | default: |
| 2321 | return ERROR_INVALID_PARAMETER; |
| 2322 | } |
| 2323 | |
| 2324 | /* Sam has to be a combination of the following */ |
| 2325 | if (!(samDesired & |
| 2326 | (KEY_ALL_ACCESS | KEY_CREATE_LINK | KEY_CREATE_SUB_KEY | |
| 2327 | KEY_ENUMERATE_SUB_KEYS | KEY_EXECUTE | KEY_NOTIFY | |
| 2328 | KEY_QUERY_VALUE | KEY_READ | KEY_SET_VALUE | KEY_WRITE))) |
| 2329 | return ERROR_INVALID_PARAMETER; |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2330 | |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2331 | if (!lpszSubKey || !*lpszSubKey) { |
Alexandre Julliard | 85ed45e | 1998-08-22 19:03:56 +0000 | [diff] [blame] | 2332 | currenthandle += 2; |
| 2333 | add_handle(currenthandle,lpNextKey,samDesired); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2334 | *retkey=currenthandle; |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2335 | TRACE_(reg)("Returning %x\n", currenthandle); |
Alexandre Julliard | 2c69f6d | 1996-09-28 18:11:01 +0000 | [diff] [blame] | 2336 | lpNextKey->flags|=REG_OPTION_TAINTED; |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2337 | return ERROR_SUCCESS; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2338 | } |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2339 | |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 2340 | if (lpszSubKey[0] == '\\') { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2341 | WARN_(reg)("Subkey %s must not begin with backslash.\n",debugstr_w(lpszSubKey)); |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 2342 | return ERROR_BAD_PATHNAME; |
| 2343 | } |
| 2344 | |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2345 | split_keypath(lpszSubKey,&wps,&wpc); |
| 2346 | i = 0; |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 2347 | while ((i<wpc) && (wps[i][0]=='\0')) i++; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2348 | lpxkey = lpNextKey; |
Alexandre Julliard | 2c69f6d | 1996-09-28 18:11:01 +0000 | [diff] [blame] | 2349 | while (wps[i]) { |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2350 | lpxkey=lpNextKey->nextsub; |
| 2351 | while (lpxkey) { |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2352 | if (!lstrcmpiW(wps[i],lpxkey->keyname)) |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2353 | break; |
| 2354 | lpxkey=lpxkey->next; |
| 2355 | } |
| 2356 | if (!lpxkey) |
| 2357 | break; |
| 2358 | i++; |
| 2359 | lpNextKey = lpxkey; |
| 2360 | } |
| 2361 | if (lpxkey) { |
Alexandre Julliard | 85ed45e | 1998-08-22 19:03:56 +0000 | [diff] [blame] | 2362 | currenthandle += 2; |
| 2363 | add_handle(currenthandle,lpxkey,samDesired); |
Alexandre Julliard | 2c69f6d | 1996-09-28 18:11:01 +0000 | [diff] [blame] | 2364 | lpxkey->flags |= REG_OPTION_TAINTED; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2365 | *retkey = currenthandle; |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2366 | TRACE_(reg)("Returning %x\n", currenthandle); |
Alexandre Julliard | 2c69f6d | 1996-09-28 18:11:01 +0000 | [diff] [blame] | 2367 | if (lpDispos) |
| 2368 | *lpDispos = REG_OPENED_EXISTING_KEY; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2369 | FREE_KEY_PATH; |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2370 | return ERROR_SUCCESS; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2371 | } |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2372 | |
| 2373 | /* Good. Now the hard part */ |
Alexandre Julliard | 2c69f6d | 1996-09-28 18:11:01 +0000 | [diff] [blame] | 2374 | while (wps[i]) { |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2375 | lplpPrevKey = &(lpNextKey->nextsub); |
| 2376 | lpxkey = *lplpPrevKey; |
| 2377 | while (lpxkey) { |
| 2378 | lplpPrevKey = &(lpxkey->next); |
| 2379 | lpxkey = *lplpPrevKey; |
| 2380 | } |
| 2381 | *lplpPrevKey=malloc(sizeof(KEYSTRUCT)); |
| 2382 | if (!*lplpPrevKey) { |
| 2383 | FREE_KEY_PATH; |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2384 | TRACE_(reg)("Returning OUTOFMEMORY\n"); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2385 | return ERROR_OUTOFMEMORY; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2386 | } |
| 2387 | memset(*lplpPrevKey,'\0',sizeof(KEYSTRUCT)); |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2388 | TRACE_(reg)("Adding %s\n", debugstr_w(wps[i])); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2389 | (*lplpPrevKey)->keyname = strdupW(wps[i]); |
| 2390 | (*lplpPrevKey)->next = NULL; |
| 2391 | (*lplpPrevKey)->nextsub = NULL; |
| 2392 | (*lplpPrevKey)->values = NULL; |
| 2393 | (*lplpPrevKey)->nrofvalues = 0; |
Alexandre Julliard | 2c69f6d | 1996-09-28 18:11:01 +0000 | [diff] [blame] | 2394 | (*lplpPrevKey)->flags = REG_OPTION_TAINTED; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2395 | if (lpszClass) |
| 2396 | (*lplpPrevKey)->class = strdupW(lpszClass); |
| 2397 | else |
| 2398 | (*lplpPrevKey)->class = NULL; |
| 2399 | lpNextKey = *lplpPrevKey; |
| 2400 | i++; |
| 2401 | } |
Alexandre Julliard | 85ed45e | 1998-08-22 19:03:56 +0000 | [diff] [blame] | 2402 | currenthandle += 2; |
| 2403 | add_handle(currenthandle,lpNextKey,samDesired); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2404 | |
| 2405 | /*FIXME: flag handling correct? */ |
Alexandre Julliard | 2c69f6d | 1996-09-28 18:11:01 +0000 | [diff] [blame] | 2406 | lpNextKey->flags= fdwOptions |REG_OPTION_TAINTED; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2407 | if (lpszClass) |
| 2408 | lpNextKey->class = strdupW(lpszClass); |
| 2409 | else |
| 2410 | lpNextKey->class = NULL; |
| 2411 | *retkey = currenthandle; |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2412 | TRACE_(reg)("Returning %x\n", currenthandle); |
Alexandre Julliard | 2c69f6d | 1996-09-28 18:11:01 +0000 | [diff] [blame] | 2413 | if (lpDispos) |
| 2414 | *lpDispos = REG_CREATED_NEW_KEY; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2415 | FREE_KEY_PATH; |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2416 | return ERROR_SUCCESS; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2417 | } |
| 2418 | |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2419 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2420 | /****************************************************************************** |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2421 | * RegCreateKeyEx32A [ADVAPI32.130] |
| 2422 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2423 | DWORD WINAPI RegCreateKeyExA( HKEY hkey, LPCSTR lpszSubKey, DWORD dwReserved, |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2424 | LPSTR lpszClass, DWORD fdwOptions, |
| 2425 | REGSAM samDesired, |
| 2426 | LPSECURITY_ATTRIBUTES lpSecAttribs, |
| 2427 | LPHKEY retkey, LPDWORD lpDispos ) |
| 2428 | { |
| 2429 | LPWSTR lpszSubKeyW, lpszClassW; |
| 2430 | DWORD ret; |
| 2431 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2432 | TRACE_(reg)("(%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n",hkey,debugstr_a(lpszSubKey), |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2433 | dwReserved,debugstr_a(lpszClass),fdwOptions,samDesired,lpSecAttribs, |
| 2434 | retkey,lpDispos); |
| 2435 | |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 2436 | lpszSubKeyW = lpszSubKey?strdupA2W(lpszSubKey):NULL; |
| 2437 | lpszClassW = lpszClass?strdupA2W(lpszClass):NULL; |
| 2438 | |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2439 | ret = RegCreateKeyExW( hkey, lpszSubKeyW, dwReserved, lpszClassW, |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2440 | fdwOptions, samDesired, lpSecAttribs, retkey, |
| 2441 | lpDispos ); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 2442 | |
| 2443 | if(lpszSubKeyW) free(lpszSubKeyW); |
| 2444 | if(lpszClassW) free(lpszClassW); |
| 2445 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2446 | return ret; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2447 | } |
| 2448 | |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2449 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2450 | /****************************************************************************** |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 2451 | * RegCreateKey32W [ADVAPI32.132] |
| 2452 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2453 | DWORD WINAPI RegCreateKeyW( HKEY hkey, LPCWSTR lpszSubKey, LPHKEY retkey ) |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 2454 | { |
| 2455 | DWORD junk; |
| 2456 | LPKEYSTRUCT lpNextKey; |
| 2457 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2458 | TRACE_(reg)("(%x,%s,%p)\n", hkey,debugstr_w(lpszSubKey),retkey); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 2459 | |
| 2460 | /* This check is here because the return value is different than the |
| 2461 | one from the Ex functions */ |
| 2462 | lpNextKey = lookup_hkey(hkey); |
| 2463 | if (!lpNextKey) |
| 2464 | return ERROR_BADKEY; |
| 2465 | |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2466 | return RegCreateKeyExW( hkey, lpszSubKey, 0, NULL, |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 2467 | REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, |
| 2468 | retkey, &junk); |
| 2469 | } |
| 2470 | |
| 2471 | |
| 2472 | /****************************************************************************** |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2473 | * RegCreateKey32A [ADVAPI32.129] |
| 2474 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2475 | DWORD WINAPI RegCreateKeyA( HKEY hkey, LPCSTR lpszSubKey, LPHKEY retkey ) |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2476 | { |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 2477 | DWORD ret; |
| 2478 | LPWSTR lpszSubKeyW; |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2479 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2480 | TRACE_(reg)("(%x,%s,%p)\n",hkey,debugstr_a(lpszSubKey),retkey); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 2481 | lpszSubKeyW = lpszSubKey?strdupA2W(lpszSubKey):NULL; |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2482 | ret = RegCreateKeyW( hkey, lpszSubKeyW, retkey ); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 2483 | if(lpszSubKeyW) free(lpszSubKeyW); |
| 2484 | return ret; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2485 | } |
| 2486 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2487 | |
| 2488 | /****************************************************************************** |
| 2489 | * RegCreateKey16 [SHELL.2] [KERNEL.218] |
| 2490 | */ |
| 2491 | DWORD WINAPI RegCreateKey16( HKEY hkey, LPCSTR lpszSubKey, LPHKEY retkey ) |
| 2492 | { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2493 | TRACE_(reg)("(%x,%s,%p)\n",hkey,debugstr_a(lpszSubKey),retkey); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2494 | return RegCreateKeyA( hkey, lpszSubKey, retkey ); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2495 | } |
| 2496 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2497 | |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2498 | /* |
| 2499 | * Query Value Functions |
| 2500 | * Win32 differs between keynames and valuenames. |
| 2501 | * multiple values may belong to one key, the special value |
| 2502 | * with name NULL is the default value used by the win31 |
| 2503 | * compat functions. |
| 2504 | * |
| 2505 | * Callpath: |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 2506 | * RegQueryValue16 -> RegQueryValue32A -> RegQueryValueEx32A \ |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 2507 | * RegQueryValue32W -> RegQueryValueEx32W |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2508 | */ |
| 2509 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2510 | |
| 2511 | /****************************************************************************** |
| 2512 | * RegQueryValueEx32W [ADVAPI32.158] |
| 2513 | * Retrieves type and data for a specified name associated with an open key |
| 2514 | * |
| 2515 | * PARAMS |
| 2516 | * hkey [I] Handle of key to query |
| 2517 | * lpValueName [I] Name of value to query |
| 2518 | * lpdwReserved [I] Reserved - must be NULL |
| 2519 | * lpdwType [O] Address of buffer for value type. If NULL, the type |
| 2520 | * is not required. |
| 2521 | * lpbData [O] Address of data buffer. If NULL, the actual data is |
| 2522 | * not required. |
| 2523 | * lpcbData [I/O] Address of data buffer size |
| 2524 | * |
| 2525 | * RETURNS |
| 2526 | * ERROR_SUCCESS: Success |
Juergen Schmied | f74fa4e | 1999-01-31 09:19:46 +0000 | [diff] [blame] | 2527 | * ERROR_MORE_DATA: !!! if the specified buffer is not big enough to hold the data |
| 2528 | * buffer is left untouched. The MS-documentation is wrong (js) !!! |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2529 | */ |
Huw D M Davies | df088c6 | 1999-07-10 11:41:24 +0000 | [diff] [blame] | 2530 | DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR lpValueName, |
| 2531 | LPDWORD lpdwReserved, LPDWORD lpdwType, |
| 2532 | LPBYTE lpbData, LPDWORD lpcbData ) |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2533 | { |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2534 | LPKEYSTRUCT lpkey; |
| 2535 | int i; |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 2536 | DWORD ret; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2537 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2538 | TRACE_(reg)("(0x%x,%s,%p,%p,%p,%p=%ld)\n", hkey, debugstr_w(lpValueName), |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 2539 | lpdwReserved, lpdwType, lpbData, lpcbData, lpcbData?*lpcbData:0); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2540 | |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 2541 | lpkey = lookup_hkey(hkey); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 2542 | |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 2543 | if (!lpkey) |
| 2544 | return ERROR_INVALID_HANDLE; |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2545 | |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 2546 | if ((lpbData && ! lpcbData) || lpdwReserved) |
| 2547 | return ERROR_INVALID_PARAMETER; |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2548 | |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 2549 | /* An empty name string is equivalent to NULL */ |
| 2550 | if (lpValueName && !*lpValueName) |
| 2551 | lpValueName = NULL; |
| 2552 | |
| 2553 | if (lpValueName==NULL) |
| 2554 | { /* Use key's unnamed or default value, if any */ |
| 2555 | for (i=0;i<lpkey->nrofvalues;i++) |
| 2556 | if (lpkey->values[i].name==NULL) |
| 2557 | break; |
| 2558 | } |
| 2559 | else |
| 2560 | { /* Search for the key name */ |
| 2561 | for (i=0;i<lpkey->nrofvalues;i++) |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2562 | if ( lpkey->values[i].name && !lstrcmpiW(lpValueName,lpkey->values[i].name)) |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 2563 | break; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2564 | } |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2565 | |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 2566 | if (i==lpkey->nrofvalues) |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2567 | { TRACE_(reg)(" Key not found\n"); |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 2568 | if (lpValueName==NULL) |
| 2569 | { /* Empty keyname not found */ |
| 2570 | if (lpbData) |
| 2571 | { *(WCHAR*)lpbData = 0; |
| 2572 | *lpcbData = 2; |
| 2573 | } |
| 2574 | if (lpdwType) |
| 2575 | *lpdwType = REG_SZ; |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2576 | TRACE_(reg)(" Returning an empty string\n"); |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 2577 | return ERROR_SUCCESS; |
| 2578 | } |
| 2579 | return ERROR_FILE_NOT_FOUND; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2580 | } |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2581 | |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 2582 | ret = ERROR_SUCCESS; |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2583 | |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 2584 | if (lpdwType) /* type required ?*/ |
| 2585 | *lpdwType = lpkey->values[i].type; |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2586 | |
Juergen Schmied | f74fa4e | 1999-01-31 09:19:46 +0000 | [diff] [blame] | 2587 | if (lpbData) /* data required ?*/ |
| 2588 | { if (*lpcbData >= lpkey->values[i].len) /* buffer large enought ?*/ |
| 2589 | memcpy(lpbData,lpkey->values[i].data,lpkey->values[i].len); |
Marcus Meissner | fe9bdf9 | 1999-07-15 14:33:17 +0000 | [diff] [blame] | 2590 | else { |
| 2591 | *lpcbData = lpkey->values[i].len; |
Juergen Schmied | f74fa4e | 1999-01-31 09:19:46 +0000 | [diff] [blame] | 2592 | ret = ERROR_MORE_DATA; |
Marcus Meissner | fe9bdf9 | 1999-07-15 14:33:17 +0000 | [diff] [blame] | 2593 | } |
Juergen Schmied | f74fa4e | 1999-01-31 09:19:46 +0000 | [diff] [blame] | 2594 | } |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2595 | |
Juergen Schmied | f74fa4e | 1999-01-31 09:19:46 +0000 | [diff] [blame] | 2596 | if (lpcbData) /* size required ?*/ |
| 2597 | { *lpcbData = lpkey->values[i].len; |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 2598 | } |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2599 | |
Sylvain St.Germain | e533222 | 1999-04-10 16:46:15 +0000 | [diff] [blame] | 2600 | debug_print_value ( lpbData, &lpkey->values[i]); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2601 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2602 | TRACE_(reg)(" (ret=%lx, type=%lx, len=%ld)\n", ret, lpdwType?*lpdwType:0,lpcbData?*lpcbData:0); |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 2603 | |
| 2604 | return ret; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2605 | } |
| 2606 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2607 | |
| 2608 | /****************************************************************************** |
| 2609 | * RegQueryValue32W [ADVAPI32.159] |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2610 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2611 | DWORD WINAPI RegQueryValueW( HKEY hkey, LPCWSTR lpszSubKey, LPWSTR lpszData, |
Alexandre Julliard | b24fc08 | 1999-02-25 16:36:07 +0000 | [diff] [blame] | 2612 | LPLONG lpcbData ) |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2613 | { |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2614 | HKEY xhkey; |
| 2615 | DWORD ret,lpdwType; |
| 2616 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2617 | TRACE_(reg)("(%x,%s,%p,%ld)\n",hkey,debugstr_w(lpszSubKey),lpszData, |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2618 | lpcbData?*lpcbData:0); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2619 | |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 2620 | /* Only open subkey, if we really do descend */ |
| 2621 | if (lpszSubKey && *lpszSubKey) { |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2622 | ret = RegOpenKeyW( hkey, lpszSubKey, &xhkey ); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 2623 | if (ret != ERROR_SUCCESS) { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2624 | WARN_(reg)("Could not open %s\n", debugstr_w(lpszSubKey)); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 2625 | return ret; |
| 2626 | } |
| 2627 | } else |
| 2628 | xhkey = hkey; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2629 | |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 2630 | lpdwType = REG_SZ; |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2631 | ret = RegQueryValueExW( xhkey, NULL, NULL, &lpdwType, (LPBYTE)lpszData, |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 2632 | lpcbData ); |
| 2633 | if (xhkey != hkey) |
| 2634 | RegCloseKey(xhkey); |
| 2635 | return ret; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2636 | } |
| 2637 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2638 | |
| 2639 | /****************************************************************************** |
| 2640 | * RegQueryValueEx32A [ADVAPI32.157] |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 2641 | * |
| 2642 | * NOTES: |
| 2643 | * the documantation is wrong: if the buffer is to small it remains untouched |
| 2644 | * |
| 2645 | * FIXME: check returnvalue (len) for an empty key |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2646 | */ |
Huw D M Davies | df088c6 | 1999-07-10 11:41:24 +0000 | [diff] [blame] | 2647 | DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR lpszValueName, |
| 2648 | LPDWORD lpdwReserved, LPDWORD lpdwType, |
| 2649 | LPBYTE lpbData, LPDWORD lpcbData ) |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2650 | { |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2651 | LPWSTR lpszValueNameW; |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 2652 | LPBYTE mybuf = NULL; |
| 2653 | DWORD ret, mytype, mylen = 0; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2654 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2655 | TRACE_(reg)("(%x,%s,%p,%p,%p,%p=%ld)\n", hkey,debugstr_a(lpszValueName), |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 2656 | lpdwReserved,lpdwType,lpbData,lpcbData,lpcbData?*lpcbData:0); |
Alexandre Julliard | a69b88b | 1998-03-15 20:29:56 +0000 | [diff] [blame] | 2657 | |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 2658 | if (!lpcbData && lpbData) /* buffer without size is illegal */ |
| 2659 | { return ERROR_INVALID_PARAMETER; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2660 | } |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 2661 | |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 2662 | lpszValueNameW = lpszValueName ? strdupA2W(lpszValueName) : NULL; |
| 2663 | |
| 2664 | /* get just the type first */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2665 | ret = RegQueryValueExW( hkey, lpszValueNameW, lpdwReserved, &mytype, NULL, NULL ); |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 2666 | |
| 2667 | if ( ret != ERROR_SUCCESS ) /* failed ?? */ |
| 2668 | { if(lpszValueNameW) free(lpszValueNameW); |
| 2669 | return ret; |
| 2670 | } |
| 2671 | |
| 2672 | if (lpcbData) /* at least length requested? */ |
| 2673 | { if (UNICONVMASK & (1<<(mytype))) /* string requested? */ |
Juergen Schmied | f74fa4e | 1999-01-31 09:19:46 +0000 | [diff] [blame] | 2674 | { if (lpbData ) /* value requested? */ |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 2675 | { mylen = 2*( *lpcbData ); |
| 2676 | mybuf = (LPBYTE)xmalloc( mylen ); |
| 2677 | } |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2678 | |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2679 | ret = RegQueryValueExW( hkey, lpszValueNameW, lpdwReserved, lpdwType, mybuf, &mylen ); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2680 | |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 2681 | if (ret == ERROR_SUCCESS ) |
| 2682 | { if ( lpbData ) |
| 2683 | { lmemcpynWtoA(lpbData, (LPWSTR)mybuf, mylen/2); |
| 2684 | } |
| 2685 | } |
| 2686 | |
| 2687 | *lpcbData = mylen/2; /* size is in byte! */ |
| 2688 | } |
| 2689 | else /* no strings, call it straight */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2690 | { ret = RegQueryValueExW( hkey, lpszValueNameW, lpdwReserved, lpdwType, lpbData, lpcbData ); |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 2691 | } |
| 2692 | } |
| 2693 | |
| 2694 | if (lpdwType) /* type when requested */ |
| 2695 | { *lpdwType = mytype; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2696 | } |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2697 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2698 | TRACE_(reg)(" (ret=%lx,type=%lx, len=%ld)\n", ret,mytype,lpcbData?*lpcbData:0); |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 2699 | |
| 2700 | if(mybuf) free(mybuf); |
| 2701 | if(lpszValueNameW) free(lpszValueNameW); |
| 2702 | return ret; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2703 | } |
| 2704 | |
Alexandre Julliard | a69b88b | 1998-03-15 20:29:56 +0000 | [diff] [blame] | 2705 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2706 | /****************************************************************************** |
| 2707 | * RegQueryValueEx16 [KERNEL.225] |
| 2708 | */ |
| 2709 | DWORD WINAPI RegQueryValueEx16( HKEY hkey, LPSTR lpszValueName, |
| 2710 | LPDWORD lpdwReserved, LPDWORD lpdwType, |
| 2711 | LPBYTE lpbData, LPDWORD lpcbData ) |
| 2712 | { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2713 | TRACE_(reg)("(%x,%s,%p,%p,%p,%ld)\n",hkey,debugstr_a(lpszValueName), |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2714 | lpdwReserved,lpdwType,lpbData,lpcbData?*lpcbData:0); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2715 | return RegQueryValueExA( hkey, lpszValueName, lpdwReserved, lpdwType, |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2716 | lpbData, lpcbData ); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2717 | } |
| 2718 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2719 | |
| 2720 | /****************************************************************************** |
| 2721 | * RegQueryValue32A [ADVAPI32.156] |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2722 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2723 | DWORD WINAPI RegQueryValueA( HKEY hkey, LPCSTR lpszSubKey, LPSTR lpszData, |
Alexandre Julliard | b24fc08 | 1999-02-25 16:36:07 +0000 | [diff] [blame] | 2724 | LPLONG lpcbData ) |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 2725 | { |
| 2726 | HKEY xhkey; |
| 2727 | DWORD ret, dwType; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2728 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2729 | TRACE_(reg)("(%x,%s,%p,%ld)\n",hkey,debugstr_a(lpszSubKey),lpszData, |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2730 | lpcbData?*lpcbData:0); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2731 | |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 2732 | if (lpszSubKey && *lpszSubKey) { |
| 2733 | ret = RegOpenKey16( hkey, lpszSubKey, &xhkey ); |
| 2734 | if( ret != ERROR_SUCCESS ) |
| 2735 | return ret; |
| 2736 | } else |
| 2737 | xhkey = hkey; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2738 | |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 2739 | dwType = REG_SZ; |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2740 | ret = RegQueryValueExA( xhkey, NULL,NULL, &dwType, (LPBYTE)lpszData, |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 2741 | lpcbData ); |
| 2742 | if( xhkey != hkey ) |
| 2743 | RegCloseKey( xhkey ); |
| 2744 | return ret; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2745 | } |
| 2746 | |
Alexandre Julliard | a69b88b | 1998-03-15 20:29:56 +0000 | [diff] [blame] | 2747 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2748 | /****************************************************************************** |
| 2749 | * RegQueryValue16 [SHELL.6] [KERNEL.224] |
| 2750 | * |
| 2751 | * NOTES |
| 2752 | * Is this HACK still applicable? |
| 2753 | * |
| 2754 | * HACK |
| 2755 | * The 16bit RegQueryValue doesn't handle selectorblocks anyway, so we just |
| 2756 | * mask out the high 16 bit. This (not so much incidently) hopefully fixes |
| 2757 | * Aldus FH4) |
| 2758 | */ |
| 2759 | DWORD WINAPI RegQueryValue16( HKEY hkey, LPSTR lpszSubKey, LPSTR lpszData, |
| 2760 | LPDWORD lpcbData ) |
| 2761 | { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2762 | TRACE_(reg)("(%x,%s,%p,%ld)\n",hkey,debugstr_a(lpszSubKey),lpszData, |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2763 | lpcbData?*lpcbData:0); |
| 2764 | |
| 2765 | if (lpcbData) |
| 2766 | *lpcbData &= 0xFFFF; |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2767 | return RegQueryValueA(hkey,lpszSubKey,lpszData,lpcbData); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2768 | } |
| 2769 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2770 | |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2771 | /* |
| 2772 | * Setting values of Registry keys |
| 2773 | * |
| 2774 | * Callpath: |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 2775 | * RegSetValue16 -> RegSetValue32A -> RegSetValueEx32A \ |
| 2776 | * RegSetValue32W -> RegSetValueEx32W |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2777 | */ |
| 2778 | |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2779 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2780 | /****************************************************************************** |
| 2781 | * RegSetValueEx32W [ADVAPI32.170] |
| 2782 | * Sets the data and type of a value under a register key |
| 2783 | * |
| 2784 | * PARAMS |
| 2785 | * hkey [I] Handle of key to set value for |
| 2786 | * lpszValueName [I] Name of value to set |
| 2787 | * dwReserved [I] Reserved - must be zero |
| 2788 | * dwType [I] Flag for value type |
| 2789 | * lpbData [I] Address of value data |
| 2790 | * cbData [I] Size of value data |
| 2791 | * |
| 2792 | * RETURNS |
| 2793 | * Success: ERROR_SUCCESS |
| 2794 | * Failure: Error code |
Juergen Schmied | f74fa4e | 1999-01-31 09:19:46 +0000 | [diff] [blame] | 2795 | * |
| 2796 | * NOTES |
| 2797 | * win95 does not care about cbData for REG_SZ and finds out the len by itself (js) |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2798 | */ |
Huw D M Davies | df088c6 | 1999-07-10 11:41:24 +0000 | [diff] [blame] | 2799 | DWORD WINAPI RegSetValueExW( HKEY hkey, LPCWSTR lpszValueName, |
| 2800 | DWORD dwReserved, DWORD dwType, |
| 2801 | CONST BYTE *lpbData, DWORD cbData) |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2802 | { |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 2803 | LPKEYSTRUCT lpkey; |
| 2804 | int i; |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2805 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2806 | TRACE_(reg)("(%x,%s,%ld,%ld,%p,%ld)\n", hkey, debugstr_w(lpszValueName), |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2807 | dwReserved, dwType, lpbData, cbData); |
| 2808 | |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 2809 | lpkey = lookup_hkey( hkey ); |
| 2810 | |
| 2811 | if (!lpkey) |
| 2812 | return ERROR_INVALID_HANDLE; |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 2813 | |
| 2814 | lpkey->flags |= REG_OPTION_TAINTED; |
| 2815 | |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2816 | if (lpszValueName==NULL) { |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2817 | /* Sets type and name for key's unnamed or default value */ |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2818 | for (i=0;i<lpkey->nrofvalues;i++) |
| 2819 | if (lpkey->values[i].name==NULL) |
| 2820 | break; |
| 2821 | } else { |
| 2822 | for (i=0;i<lpkey->nrofvalues;i++) |
Alexandre Julliard | 0e270f4 | 1996-08-24 18:26:35 +0000 | [diff] [blame] | 2823 | if ( lpkey->values[i].name && |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2824 | !lstrcmpiW(lpszValueName,lpkey->values[i].name) |
Alexandre Julliard | 0e270f4 | 1996-08-24 18:26:35 +0000 | [diff] [blame] | 2825 | ) |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2826 | break; |
| 2827 | } |
| 2828 | if (i==lpkey->nrofvalues) { |
| 2829 | lpkey->values = (LPKEYVALUE)xrealloc( |
| 2830 | lpkey->values, |
| 2831 | (lpkey->nrofvalues+1)*sizeof(KEYVALUE) |
| 2832 | ); |
| 2833 | lpkey->nrofvalues++; |
| 2834 | memset(lpkey->values+i,'\0',sizeof(KEYVALUE)); |
| 2835 | } |
Marcus Meissner | f4f1719 | 1998-10-17 12:10:19 +0000 | [diff] [blame] | 2836 | if (lpkey->values[i].name==NULL) { |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2837 | if (lpszValueName) |
| 2838 | lpkey->values[i].name = strdupW(lpszValueName); |
| 2839 | else |
| 2840 | lpkey->values[i].name = NULL; |
Marcus Meissner | f4f1719 | 1998-10-17 12:10:19 +0000 | [diff] [blame] | 2841 | } |
Juergen Schmied | f74fa4e | 1999-01-31 09:19:46 +0000 | [diff] [blame] | 2842 | |
| 2843 | if (dwType == REG_SZ) |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2844 | cbData = 2 * (lstrlenW ((LPCWSTR)lpbData) + 1); |
Juergen Schmied | f74fa4e | 1999-01-31 09:19:46 +0000 | [diff] [blame] | 2845 | |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2846 | lpkey->values[i].len = cbData; |
| 2847 | lpkey->values[i].type = dwType; |
| 2848 | if (lpkey->values[i].data !=NULL) |
| 2849 | free(lpkey->values[i].data); |
| 2850 | lpkey->values[i].data = (LPBYTE)xmalloc(cbData); |
Alexandre Julliard | cdcdede | 1996-04-21 14:57:41 +0000 | [diff] [blame] | 2851 | lpkey->values[i].lastmodified = time(NULL); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2852 | memcpy(lpkey->values[i].data,lpbData,cbData); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2853 | return ERROR_SUCCESS; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2854 | } |
| 2855 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2856 | |
| 2857 | /****************************************************************************** |
| 2858 | * RegSetValueEx32A [ADVAPI32.169] |
| 2859 | * |
Juergen Schmied | f74fa4e | 1999-01-31 09:19:46 +0000 | [diff] [blame] | 2860 | * NOTES |
| 2861 | * win95 does not care about cbData for REG_SZ and finds out the len by itself (js) |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2862 | */ |
Huw D M Davies | df088c6 | 1999-07-10 11:41:24 +0000 | [diff] [blame] | 2863 | DWORD WINAPI RegSetValueExA( HKEY hkey, LPCSTR lpszValueName, |
| 2864 | DWORD dwReserved, DWORD dwType, |
| 2865 | CONST BYTE *lpbData, DWORD cbData ) |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2866 | { |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2867 | LPBYTE buf; |
| 2868 | LPWSTR lpszValueNameW; |
| 2869 | DWORD ret; |
| 2870 | |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 2871 | if (!lpbData) |
| 2872 | return (ERROR_INVALID_PARAMETER); |
| 2873 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2874 | TRACE_(reg)("(%x,%s,%ld,%ld,%p,%ld)\n",hkey,debugstr_a(lpszValueName), |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2875 | dwReserved,dwType,lpbData,cbData); |
| 2876 | |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 2877 | if ((1<<dwType) & UNICONVMASK) |
Juergen Schmied | f74fa4e | 1999-01-31 09:19:46 +0000 | [diff] [blame] | 2878 | { if (dwType == REG_SZ) |
| 2879 | cbData = strlen ((LPCSTR)lpbData)+1; |
| 2880 | |
| 2881 | buf = (LPBYTE)xmalloc( cbData *2 ); |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 2882 | lmemcpynAtoW ((LPVOID)buf, lpbData, cbData ); |
| 2883 | cbData=2*cbData; |
| 2884 | } |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2885 | else |
Huw D M Davies | df088c6 | 1999-07-10 11:41:24 +0000 | [diff] [blame] | 2886 | buf=(LPBYTE)lpbData; |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 2887 | |
| 2888 | if (lpszValueName) |
| 2889 | lpszValueNameW = strdupA2W(lpszValueName); |
| 2890 | else |
| 2891 | lpszValueNameW = NULL; |
| 2892 | |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2893 | ret=RegSetValueExW(hkey,lpszValueNameW,dwReserved,dwType,buf,cbData); |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 2894 | |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2895 | if (lpszValueNameW) |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 2896 | free(lpszValueNameW); |
| 2897 | |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2898 | if (buf!=lpbData) |
Juergen Schmied | 26cae9d | 1999-01-23 12:11:09 +0000 | [diff] [blame] | 2899 | free(buf); |
| 2900 | |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2901 | return ret; |
| 2902 | } |
| 2903 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2904 | |
| 2905 | /****************************************************************************** |
| 2906 | * RegSetValueEx16 [KERNEL.226] |
| 2907 | */ |
| 2908 | DWORD WINAPI RegSetValueEx16( HKEY hkey, LPSTR lpszValueName, DWORD dwReserved, |
| 2909 | DWORD dwType, LPBYTE lpbData, DWORD cbData ) |
| 2910 | { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2911 | TRACE_(reg)("(%x,%s,%ld,%ld,%p,%ld)\n",hkey,debugstr_a(lpszValueName), |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2912 | dwReserved,dwType,lpbData,cbData); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2913 | return RegSetValueExA( hkey, lpszValueName, dwReserved, dwType, lpbData, |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2914 | cbData ); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2915 | } |
| 2916 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2917 | |
| 2918 | /****************************************************************************** |
| 2919 | * RegSetValue32W [ADVAPI32.171] |
| 2920 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2921 | DWORD WINAPI RegSetValueW( HKEY hkey, LPCWSTR lpszSubKey, DWORD dwType, |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 2922 | LPCWSTR lpszData, DWORD cbData ) |
| 2923 | { |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2924 | HKEY xhkey; |
| 2925 | DWORD ret; |
| 2926 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2927 | TRACE_(reg)("(%x,%s,%ld,%s,%ld)\n", |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 2928 | hkey,debugstr_w(lpszSubKey),dwType,debugstr_w(lpszData),cbData |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2929 | ); |
| 2930 | if (lpszSubKey && *lpszSubKey) { |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2931 | ret=RegCreateKeyW(hkey,lpszSubKey,&xhkey); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2932 | if (ret!=ERROR_SUCCESS) |
| 2933 | return ret; |
| 2934 | } else |
| 2935 | xhkey=hkey; |
| 2936 | if (dwType!=REG_SZ) { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2937 | TRACE_(reg)("dwType=%ld - Changing to REG_SZ\n",dwType); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2938 | dwType=REG_SZ; |
| 2939 | } |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2940 | if (cbData!=2*lstrlenW(lpszData)+2) { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2941 | TRACE_(reg)("Len=%ld != strlen(%s)+1=%d!\n", |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2942 | cbData,debugstr_w(lpszData),2*lstrlenW(lpszData)+2 |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2943 | ); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2944 | cbData=2*lstrlenW(lpszData)+2; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2945 | } |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2946 | ret=RegSetValueExW(xhkey,NULL,0,dwType,(LPBYTE)lpszData,cbData); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2947 | if (hkey!=xhkey) |
| 2948 | RegCloseKey(xhkey); |
| 2949 | return ret; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2950 | } |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2951 | |
| 2952 | |
| 2953 | /****************************************************************************** |
| 2954 | * RegSetValue32A [ADVAPI32.168] |
| 2955 | * |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2956 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2957 | DWORD WINAPI RegSetValueA( HKEY hkey, LPCSTR lpszSubKey, DWORD dwType, |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 2958 | LPCSTR lpszData, DWORD cbData ) |
| 2959 | { |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2960 | DWORD ret; |
| 2961 | HKEY xhkey; |
| 2962 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2963 | TRACE_(reg)("(%x,%s,%ld,%s,%ld)\n",hkey,lpszSubKey,dwType,lpszData,cbData); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2964 | if (lpszSubKey && *lpszSubKey) { |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 2965 | ret=RegCreateKey16(hkey,lpszSubKey,&xhkey); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2966 | if (ret!=ERROR_SUCCESS) |
| 2967 | return ret; |
| 2968 | } else |
| 2969 | xhkey=hkey; |
| 2970 | |
| 2971 | if (dwType!=REG_SZ) { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2972 | TRACE_(reg)("dwType=%ld!\n",dwType); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2973 | dwType=REG_SZ; |
| 2974 | } |
| 2975 | if (cbData!=strlen(lpszData)+1) |
| 2976 | cbData=strlen(lpszData)+1; |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2977 | ret=RegSetValueExA(xhkey,NULL,0,dwType,(LPBYTE)lpszData,cbData); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2978 | if (xhkey!=hkey) |
| 2979 | RegCloseKey(xhkey); |
| 2980 | return ret; |
| 2981 | } |
| 2982 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2983 | |
| 2984 | /****************************************************************************** |
| 2985 | * RegSetValue16 [KERNEL.221] [SHELL.5] |
| 2986 | */ |
| 2987 | DWORD WINAPI RegSetValue16( HKEY hkey, LPCSTR lpszSubKey, DWORD dwType, |
| 2988 | LPCSTR lpszData, DWORD cbData ) |
| 2989 | { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 2990 | TRACE_(reg)("(%x,%s,%ld,%s,%ld)\n",hkey,debugstr_a(lpszSubKey),dwType, |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2991 | debugstr_a(lpszData),cbData); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 2992 | return RegSetValueA(hkey,lpszSubKey,dwType,lpszData,cbData); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2993 | } |
| 2994 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 2995 | |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 2996 | /* |
| 2997 | * Key Enumeration |
| 2998 | * |
| 2999 | * Callpath: |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 3000 | * RegEnumKey16 -> RegEnumKey32A -> RegEnumKeyEx32A \ |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 3001 | * RegEnumKey32W -> RegEnumKeyEx32W |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3002 | */ |
| 3003 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3004 | |
| 3005 | /****************************************************************************** |
| 3006 | * RegEnumKeyEx32W [ADVAPI32.139] |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 3007 | * |
| 3008 | * PARAMS |
| 3009 | * hkey [I] Handle to key to enumerate |
| 3010 | * iSubKey [I] Index of subkey to enumerate |
| 3011 | * lpszName [O] Buffer for subkey name |
| 3012 | * lpcchName [O] Size of subkey buffer |
| 3013 | * lpdwReserved [I] Reserved |
| 3014 | * lpszClass [O] Buffer for class string |
| 3015 | * lpcchClass [O] Size of class buffer |
| 3016 | * ft [O] Time key last written to |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3017 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3018 | DWORD WINAPI RegEnumKeyExW( HKEY hkey, DWORD iSubkey, LPWSTR lpszName, |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3019 | LPDWORD lpcchName, LPDWORD lpdwReserved, |
| 3020 | LPWSTR lpszClass, LPDWORD lpcchClass, |
| 3021 | FILETIME *ft ) |
| 3022 | { |
Huw D M Davies | 13d00c8 | 1999-10-31 17:40:21 +0000 | [diff] [blame] | 3023 | LPKEYSTRUCT lpkey,lpxkey; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3024 | |
Huw D M Davies | 13d00c8 | 1999-10-31 17:40:21 +0000 | [diff] [blame] | 3025 | TRACE_(reg)("(%x,%ld,%p,%p(%ld),%p,%p,%p,%p)\n",hkey,iSubkey,lpszName, |
| 3026 | lpcchName,lpcchName? *lpcchName : -1,lpdwReserved,lpszClass, |
| 3027 | lpcchClass,ft); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3028 | |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3029 | lpkey = lookup_hkey( hkey ); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3030 | if (!lpkey) |
| 3031 | return ERROR_INVALID_HANDLE; |
| 3032 | |
Huw D M Davies | 13d00c8 | 1999-10-31 17:40:21 +0000 | [diff] [blame] | 3033 | if (!lpcchName) |
| 3034 | return ERROR_INVALID_PARAMETER; |
| 3035 | |
| 3036 | if (!lpkey->nextsub) |
| 3037 | return ERROR_NO_MORE_ITEMS; |
| 3038 | lpxkey=lpkey->nextsub; |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 3039 | |
| 3040 | /* Traverse the subkeys */ |
Huw D M Davies | 13d00c8 | 1999-10-31 17:40:21 +0000 | [diff] [blame] | 3041 | while (iSubkey && lpxkey) { |
| 3042 | iSubkey--; |
| 3043 | lpxkey=lpxkey->next; |
| 3044 | } |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 3045 | |
Huw D M Davies | 13d00c8 | 1999-10-31 17:40:21 +0000 | [diff] [blame] | 3046 | if (iSubkey || !lpxkey) |
| 3047 | return ERROR_NO_MORE_ITEMS; |
| 3048 | if (lstrlenW(lpxkey->keyname)+1>*lpcchName) { |
| 3049 | *lpcchName = lstrlenW(lpxkey->keyname); |
| 3050 | return ERROR_MORE_DATA; |
| 3051 | } |
| 3052 | memcpy(lpszName,lpxkey->keyname,lstrlenW(lpxkey->keyname)*2+2); |
| 3053 | *lpcchName = lstrlenW(lpszName); |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 3054 | |
Huw D M Davies | 13d00c8 | 1999-10-31 17:40:21 +0000 | [diff] [blame] | 3055 | if (lpszClass) { |
| 3056 | /* FIXME: what should we write into it? */ |
| 3057 | *lpszClass = 0; |
| 3058 | *lpcchClass = 2; |
| 3059 | } |
| 3060 | return ERROR_SUCCESS; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3061 | } |
| 3062 | |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3063 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3064 | /****************************************************************************** |
Huw D M Davies | 13d00c8 | 1999-10-31 17:40:21 +0000 | [diff] [blame] | 3065 | * RegEnumKeyW [ADVAPI32.140] |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3066 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3067 | DWORD WINAPI RegEnumKeyW( HKEY hkey, DWORD iSubkey, LPWSTR lpszName, |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3068 | DWORD lpcchName ) |
| 3069 | { |
Huw D M Davies | 13d00c8 | 1999-10-31 17:40:21 +0000 | [diff] [blame] | 3070 | DWORD ret; |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 3071 | TRACE_(reg)("(%x,%ld,%p,%ld)\n",hkey,iSubkey,lpszName,lpcchName); |
Huw D M Davies | 13d00c8 | 1999-10-31 17:40:21 +0000 | [diff] [blame] | 3072 | ret = RegEnumKeyExW(hkey,iSubkey,lpszName,&lpcchName,NULL,NULL,NULL,NULL); |
| 3073 | |
| 3074 | /* If lpszName is NULL then we have a slightly different behaviour than |
| 3075 | RegEnumKeyExW */ |
| 3076 | if(lpszName == NULL && ret == ERROR_MORE_DATA) |
| 3077 | ret = ERROR_SUCCESS; |
| 3078 | |
| 3079 | return ret; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3080 | } |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3081 | |
| 3082 | |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3083 | /****************************************************************************** |
| 3084 | * RegEnumKeyEx32A [ADVAPI32.138] |
| 3085 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3086 | DWORD WINAPI RegEnumKeyExA( HKEY hkey, DWORD iSubkey, LPSTR lpszName, |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3087 | LPDWORD lpcchName, LPDWORD lpdwReserved, |
| 3088 | LPSTR lpszClass, LPDWORD lpcchClass, |
| 3089 | FILETIME *ft ) |
| 3090 | { |
Huw D M Davies | 13d00c8 | 1999-10-31 17:40:21 +0000 | [diff] [blame] | 3091 | DWORD ret; |
| 3092 | LPWSTR lpszNameW, lpszClassW; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3093 | |
Huw D M Davies | 13d00c8 | 1999-10-31 17:40:21 +0000 | [diff] [blame] | 3094 | TRACE_(reg)("(%x,%ld,%p,%p(%ld),%p,%p,%p,%p)\n", |
| 3095 | hkey,iSubkey,lpszName,lpcchName,lpcchName? *lpcchName : -1, |
| 3096 | lpdwReserved,lpszClass,lpcchClass,ft); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3097 | |
Huw D M Davies | 13d00c8 | 1999-10-31 17:40:21 +0000 | [diff] [blame] | 3098 | lpszNameW = lpszName ? (LPWSTR)xmalloc(*lpcchName * 2) : NULL; |
| 3099 | lpszClassW = lpszClass ? (LPWSTR)xmalloc(*lpcchClass * 2) : NULL; |
| 3100 | |
| 3101 | ret = RegEnumKeyExW(hkey, iSubkey, lpszNameW, lpcchName, lpdwReserved, |
| 3102 | lpszClassW, lpcchClass, ft); |
| 3103 | |
| 3104 | if (ret == ERROR_SUCCESS) { |
| 3105 | lstrcpyWtoA(lpszName,lpszNameW); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3106 | if (lpszClassW) |
Huw D M Davies | 13d00c8 | 1999-10-31 17:40:21 +0000 | [diff] [blame] | 3107 | lstrcpyWtoA(lpszClass,lpszClassW); |
| 3108 | } |
| 3109 | if (lpszNameW) |
| 3110 | free(lpszNameW); |
| 3111 | if (lpszClassW) |
| 3112 | free(lpszClassW); |
| 3113 | return ret; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3114 | } |
| 3115 | |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3116 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3117 | /****************************************************************************** |
Huw D M Davies | 13d00c8 | 1999-10-31 17:40:21 +0000 | [diff] [blame] | 3118 | * RegEnumKeyA [ADVAPI32.137] |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3119 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3120 | DWORD WINAPI RegEnumKeyA( HKEY hkey, DWORD iSubkey, LPSTR lpszName, |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3121 | DWORD lpcchName ) |
| 3122 | { |
Huw D M Davies | 13d00c8 | 1999-10-31 17:40:21 +0000 | [diff] [blame] | 3123 | DWORD ret; |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 3124 | TRACE_(reg)("(%x,%ld,%p,%ld)\n",hkey,iSubkey,lpszName,lpcchName); |
Huw D M Davies | 13d00c8 | 1999-10-31 17:40:21 +0000 | [diff] [blame] | 3125 | ret = RegEnumKeyExA( hkey, iSubkey, lpszName, &lpcchName, NULL, NULL, |
| 3126 | NULL, NULL ); |
| 3127 | |
| 3128 | /* If lpszName is NULL then we have a slightly different behaviour than |
| 3129 | RegEnumKeyExA */ |
| 3130 | if(lpszName == NULL && ret == ERROR_MORE_DATA) |
| 3131 | ret = ERROR_SUCCESS; |
| 3132 | |
| 3133 | return ret; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3134 | } |
| 3135 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3136 | |
| 3137 | /****************************************************************************** |
| 3138 | * RegEnumKey16 [SHELL.7] [KERNEL.216] |
| 3139 | */ |
| 3140 | DWORD WINAPI RegEnumKey16( HKEY hkey, DWORD iSubkey, LPSTR lpszName, |
| 3141 | DWORD lpcchName ) |
| 3142 | { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 3143 | TRACE_(reg)("(%x,%ld,%p,%ld)\n",hkey,iSubkey,lpszName,lpcchName); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3144 | return RegEnumKeyA( hkey, iSubkey, lpszName, lpcchName); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3145 | } |
| 3146 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3147 | |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3148 | /* |
| 3149 | * Enumerate Registry Values |
| 3150 | * |
| 3151 | * Callpath: |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 3152 | * RegEnumValue16 -> RegEnumValue32A -> RegEnumValue32W |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3153 | */ |
| 3154 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3155 | |
| 3156 | /****************************************************************************** |
| 3157 | * RegEnumValue32W [ADVAPI32.142] |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3158 | * |
| 3159 | * PARAMS |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 3160 | * hkey [I] Handle to key to query |
| 3161 | * iValue [I] Index of value to query |
| 3162 | * lpszValue [O] Value string |
Juergen Schmied | f74fa4e | 1999-01-31 09:19:46 +0000 | [diff] [blame] | 3163 | * lpcchValue [I/O] Size of value buffer (in wchars) |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 3164 | * lpdReserved [I] Reserved |
| 3165 | * lpdwType [O] Type code |
| 3166 | * lpbData [O] Value data |
Juergen Schmied | f74fa4e | 1999-01-31 09:19:46 +0000 | [diff] [blame] | 3167 | * lpcbData [I/O] Size of data buffer (in bytes) |
John Richardson | 2bb013b | 1998-11-06 17:36:13 +0000 | [diff] [blame] | 3168 | * |
| 3169 | * Note: wide character functions that take and/or return "character counts" |
| 3170 | * use TCHAR (that is unsigned short or char) not byte counts. |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3171 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3172 | DWORD WINAPI RegEnumValueW( HKEY hkey, DWORD iValue, LPWSTR lpszValue, |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3173 | LPDWORD lpcchValue, LPDWORD lpdReserved, |
| 3174 | LPDWORD lpdwType, LPBYTE lpbData, |
| 3175 | LPDWORD lpcbData ) |
| 3176 | { |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3177 | LPKEYSTRUCT lpkey; |
| 3178 | LPKEYVALUE val; |
| 3179 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 3180 | TRACE_(reg)("(%x,%ld,%p,%p,%p,%p,%p,%p)\n",hkey,iValue,debugstr_w(lpszValue), |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3181 | lpcchValue,lpdReserved,lpdwType,lpbData,lpcbData); |
| 3182 | |
Juergen Schmied | f74fa4e | 1999-01-31 09:19:46 +0000 | [diff] [blame] | 3183 | lpkey = lookup_hkey( hkey ); |
| 3184 | |
| 3185 | if (!lpcbData && lpbData) |
| 3186 | return ERROR_INVALID_PARAMETER; |
| 3187 | |
| 3188 | if (!lpkey) |
| 3189 | return ERROR_INVALID_HANDLE; |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3190 | |
Juergen Schmied | f74fa4e | 1999-01-31 09:19:46 +0000 | [diff] [blame] | 3191 | if (lpkey->nrofvalues <= iValue) |
| 3192 | return ERROR_NO_MORE_ITEMS; |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3193 | |
Juergen Schmied | f74fa4e | 1999-01-31 09:19:46 +0000 | [diff] [blame] | 3194 | val = &(lpkey->values[iValue]); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3195 | |
| 3196 | if (val->name) { |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3197 | if (lstrlenW(val->name)+1>*lpcchValue) { |
| 3198 | *lpcchValue = lstrlenW(val->name)+1; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3199 | return ERROR_MORE_DATA; |
| 3200 | } |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3201 | memcpy(lpszValue,val->name,2 * (lstrlenW(val->name)+1) ); |
| 3202 | *lpcchValue=lstrlenW(val->name); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3203 | } else { |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3204 | *lpszValue = 0; |
Alexandre Julliard | 0623a6f | 1998-01-18 18:01:49 +0000 | [diff] [blame] | 3205 | *lpcchValue = 0; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3206 | } |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 3207 | |
Juergen Schmied | f74fa4e | 1999-01-31 09:19:46 +0000 | [diff] [blame] | 3208 | /* Can be NULL if the type code is not required */ |
| 3209 | if (lpdwType) |
| 3210 | *lpdwType = val->type; |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 3211 | |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3212 | if (lpbData) { |
Marcus Meissner | fe9bdf9 | 1999-07-15 14:33:17 +0000 | [diff] [blame] | 3213 | if (val->len>*lpcbData) { |
| 3214 | *lpcbData = val->len; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3215 | return ERROR_MORE_DATA; |
Marcus Meissner | fe9bdf9 | 1999-07-15 14:33:17 +0000 | [diff] [blame] | 3216 | } |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3217 | memcpy(lpbData,val->data,val->len); |
| 3218 | *lpcbData = val->len; |
| 3219 | } |
Juergen Schmied | f74fa4e | 1999-01-31 09:19:46 +0000 | [diff] [blame] | 3220 | |
Sylvain St.Germain | e533222 | 1999-04-10 16:46:15 +0000 | [diff] [blame] | 3221 | debug_print_value ( val->data, val ); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3222 | return ERROR_SUCCESS; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3223 | } |
| 3224 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3225 | |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3226 | /****************************************************************************** |
| 3227 | * RegEnumValue32A [ADVAPI32.141] |
| 3228 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3229 | DWORD WINAPI RegEnumValueA( HKEY hkey, DWORD iValue, LPSTR lpszValue, |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3230 | LPDWORD lpcchValue, LPDWORD lpdReserved, |
| 3231 | LPDWORD lpdwType, LPBYTE lpbData, |
| 3232 | LPDWORD lpcbData ) |
| 3233 | { |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3234 | LPWSTR lpszValueW; |
| 3235 | LPBYTE lpbDataW; |
| 3236 | DWORD ret,lpcbDataW; |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 3237 | DWORD dwType; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3238 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 3239 | TRACE_(reg)("(%x,%ld,%p,%p,%p,%p,%p,%p)\n",hkey,iValue,lpszValue,lpcchValue, |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 3240 | lpdReserved,lpdwType,lpbData,lpcbData); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3241 | |
| 3242 | lpszValueW = (LPWSTR)xmalloc(*lpcchValue*2); |
| 3243 | if (lpbData) { |
| 3244 | lpbDataW = (LPBYTE)xmalloc(*lpcbData*2); |
Uwe Bonnes | 8776344 | 1998-11-08 14:22:31 +0000 | [diff] [blame] | 3245 | lpcbDataW = *lpcbData; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3246 | } else |
| 3247 | lpbDataW = NULL; |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 3248 | |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3249 | ret = RegEnumValueW( hkey, iValue, lpszValueW, lpcchValue, |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 3250 | lpdReserved, &dwType, lpbDataW, &lpcbDataW ); |
| 3251 | |
| 3252 | if (lpdwType) |
| 3253 | *lpdwType = dwType; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3254 | |
| 3255 | if (ret==ERROR_SUCCESS) { |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 3256 | lstrcpyWtoA(lpszValue,lpszValueW); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3257 | if (lpbData) { |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 3258 | if ((1<<dwType) & UNICONVMASK) { |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 3259 | lstrcpyWtoA(lpbData,(LPWSTR)lpbDataW); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3260 | } else { |
Marcus Meissner | fe9bdf9 | 1999-07-15 14:33:17 +0000 | [diff] [blame] | 3261 | if (lpcbDataW > *lpcbData) { |
| 3262 | *lpcbData = lpcbDataW; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3263 | ret = ERROR_MORE_DATA; |
Marcus Meissner | fe9bdf9 | 1999-07-15 14:33:17 +0000 | [diff] [blame] | 3264 | } else |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3265 | memcpy(lpbData,lpbDataW,lpcbDataW); |
| 3266 | } |
| 3267 | *lpcbData = lpcbDataW; |
| 3268 | } |
| 3269 | } |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 3270 | if (lpbDataW) free(lpbDataW); |
| 3271 | if (lpszValueW) free(lpszValueW); |
| 3272 | return ret; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3273 | } |
| 3274 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3275 | |
| 3276 | /****************************************************************************** |
| 3277 | * RegEnumValue16 [KERNEL.223] |
| 3278 | */ |
| 3279 | DWORD WINAPI RegEnumValue16( HKEY hkey, DWORD iValue, LPSTR lpszValue, |
| 3280 | LPDWORD lpcchValue, LPDWORD lpdReserved, |
| 3281 | LPDWORD lpdwType, LPBYTE lpbData, |
| 3282 | LPDWORD lpcbData ) |
| 3283 | { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 3284 | TRACE_(reg)("(%x,%ld,%p,%p,%p,%p,%p,%p)\n",hkey,iValue,lpszValue,lpcchValue, |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3285 | lpdReserved,lpdwType,lpbData,lpcbData); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3286 | return RegEnumValueA( hkey, iValue, lpszValue, lpcchValue, lpdReserved, |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3287 | lpdwType, lpbData, lpcbData ); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3288 | } |
| 3289 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3290 | |
| 3291 | /****************************************************************************** |
| 3292 | * RegCloseKey [SHELL.3] [KERNEL.220] [ADVAPI32.126] |
| 3293 | * Releases the handle of the specified key |
| 3294 | * |
| 3295 | * PARAMS |
| 3296 | * hkey [I] Handle of key to close |
| 3297 | * |
| 3298 | * RETURNS |
| 3299 | * Success: ERROR_SUCCESS |
| 3300 | * Failure: Error code |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3301 | */ |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3302 | DWORD WINAPI RegCloseKey( HKEY hkey ) |
| 3303 | { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 3304 | TRACE_(reg)("(%x)\n",hkey); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3305 | |
| 3306 | /* The standard handles are allowed to succeed, even though they are not |
| 3307 | closed */ |
| 3308 | if (is_standard_hkey(hkey)) |
| 3309 | return ERROR_SUCCESS; |
| 3310 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3311 | return remove_handle(hkey); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3312 | } |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3313 | |
| 3314 | |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3315 | /* |
| 3316 | * Delete registry key |
| 3317 | * |
| 3318 | * Callpath: |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 3319 | * RegDeleteKey16 -> RegDeleteKey32A -> RegDeleteKey32W |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3320 | */ |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3321 | |
| 3322 | |
| 3323 | /****************************************************************************** |
| 3324 | * RegDeleteKey32W [ADVAPI32.134] |
| 3325 | * |
| 3326 | * PARAMS |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 3327 | * hkey [I] Handle to open key |
| 3328 | * lpszSubKey [I] Name of subkey to delete |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3329 | * |
| 3330 | * RETURNS |
| 3331 | * Success: ERROR_SUCCESS |
| 3332 | * Failure: Error code |
| 3333 | */ |
Huw D M Davies | df088c6 | 1999-07-10 11:41:24 +0000 | [diff] [blame] | 3334 | DWORD WINAPI RegDeleteKeyW( HKEY hkey, LPCWSTR lpszSubKey ) |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3335 | { |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3336 | LPKEYSTRUCT *lplpPrevKey,lpNextKey,lpxkey; |
| 3337 | LPWSTR *wps; |
| 3338 | int wpc,i; |
| 3339 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 3340 | TRACE_(reg)("(%x,%s)\n",hkey,debugstr_w(lpszSubKey)); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3341 | |
| 3342 | lpNextKey = lookup_hkey(hkey); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3343 | if (!lpNextKey) |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3344 | return ERROR_INVALID_HANDLE; |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3345 | |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 3346 | /* Subkey param cannot be NULL */ |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3347 | if (!lpszSubKey || !*lpszSubKey) |
| 3348 | return ERROR_BADKEY; |
| 3349 | |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 3350 | /* We need to know the previous key in the hier. */ |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3351 | split_keypath(lpszSubKey,&wps,&wpc); |
| 3352 | i = 0; |
| 3353 | lpxkey = lpNextKey; |
| 3354 | while (i<wpc-1) { |
| 3355 | lpxkey=lpNextKey->nextsub; |
| 3356 | while (lpxkey) { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 3357 | TRACE_(reg)(" Scanning [%s]\n", |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 3358 | debugstr_w(lpxkey->keyname)); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3359 | if (!lstrcmpiW(wps[i],lpxkey->keyname)) |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3360 | break; |
| 3361 | lpxkey=lpxkey->next; |
| 3362 | } |
| 3363 | if (!lpxkey) { |
| 3364 | FREE_KEY_PATH; |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 3365 | TRACE_(reg)(" Not found.\n"); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3366 | /* not found is success */ |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3367 | return ERROR_SUCCESS; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3368 | } |
| 3369 | i++; |
| 3370 | lpNextKey = lpxkey; |
| 3371 | } |
| 3372 | lpxkey = lpNextKey->nextsub; |
| 3373 | lplpPrevKey = &(lpNextKey->nextsub); |
| 3374 | while (lpxkey) { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 3375 | TRACE_(reg)(" Scanning [%s]\n", |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 3376 | debugstr_w(lpxkey->keyname)); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3377 | if (!lstrcmpiW(wps[i],lpxkey->keyname)) |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3378 | break; |
| 3379 | lplpPrevKey = &(lpxkey->next); |
| 3380 | lpxkey = lpxkey->next; |
| 3381 | } |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3382 | |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 3383 | if (!lpxkey) { |
| 3384 | FREE_KEY_PATH; |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 3385 | WARN_(reg)(" Not found.\n"); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3386 | return ERROR_FILE_NOT_FOUND; |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 3387 | } |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3388 | |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 3389 | if (lpxkey->nextsub) { |
| 3390 | FREE_KEY_PATH; |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 3391 | WARN_(reg)(" Not empty.\n"); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3392 | return ERROR_CANTWRITE; |
Alexandre Julliard | a0b2b1d | 1997-11-16 17:38:29 +0000 | [diff] [blame] | 3393 | } |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3394 | *lplpPrevKey = lpxkey->next; |
| 3395 | free(lpxkey->keyname); |
| 3396 | if (lpxkey->class) |
| 3397 | free(lpxkey->class); |
| 3398 | if (lpxkey->values) |
| 3399 | free(lpxkey->values); |
| 3400 | free(lpxkey); |
| 3401 | FREE_KEY_PATH; |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 3402 | TRACE_(reg)(" Done.\n"); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3403 | return ERROR_SUCCESS; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3404 | } |
| 3405 | |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3406 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3407 | /****************************************************************************** |
| 3408 | * RegDeleteKey32A [ADVAPI32.133] |
| 3409 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3410 | DWORD WINAPI RegDeleteKeyA( HKEY hkey, LPCSTR lpszSubKey ) |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3411 | { |
| 3412 | LPWSTR lpszSubKeyW; |
| 3413 | DWORD ret; |
| 3414 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 3415 | TRACE_(reg)("(%x,%s)\n",hkey,debugstr_a(lpszSubKey)); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3416 | lpszSubKeyW = lpszSubKey?strdupA2W(lpszSubKey):NULL; |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3417 | ret = RegDeleteKeyW( hkey, lpszSubKeyW ); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3418 | if(lpszSubKeyW) free(lpszSubKeyW); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3419 | return ret; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3420 | } |
| 3421 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3422 | |
| 3423 | /****************************************************************************** |
| 3424 | * RegDeleteKey16 [SHELL.4] [KERNEL.219] |
| 3425 | */ |
| 3426 | DWORD WINAPI RegDeleteKey16( HKEY hkey, LPCSTR lpszSubKey ) |
| 3427 | { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 3428 | TRACE_(reg)("(%x,%s)\n",hkey,debugstr_a(lpszSubKey)); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3429 | return RegDeleteKeyA( hkey, lpszSubKey ); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3430 | } |
| 3431 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3432 | |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3433 | /* |
| 3434 | * Delete registry value |
| 3435 | * |
| 3436 | * Callpath: |
Alexandre Julliard | e2bfa4c | 1996-05-16 18:21:06 +0000 | [diff] [blame] | 3437 | * RegDeleteValue16 -> RegDeleteValue32A -> RegDeleteValue32W |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3438 | */ |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3439 | |
| 3440 | |
| 3441 | /****************************************************************************** |
| 3442 | * RegDeleteValue32W [ADVAPI32.136] |
| 3443 | * |
| 3444 | * PARAMS |
| 3445 | * hkey [I] |
| 3446 | * lpszValue [I] |
| 3447 | * |
| 3448 | * RETURNS |
| 3449 | */ |
Huw D M Davies | df088c6 | 1999-07-10 11:41:24 +0000 | [diff] [blame] | 3450 | DWORD WINAPI RegDeleteValueW( HKEY hkey, LPCWSTR lpszValue ) |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 3451 | { |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3452 | DWORD i; |
| 3453 | LPKEYSTRUCT lpkey; |
| 3454 | LPKEYVALUE val; |
| 3455 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 3456 | TRACE_(reg)("(%x,%s)\n",hkey,debugstr_w(lpszValue)); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3457 | |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3458 | lpkey = lookup_hkey( hkey ); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3459 | if (!lpkey) |
| 3460 | return ERROR_INVALID_HANDLE; |
| 3461 | |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3462 | if (lpszValue) { |
| 3463 | for (i=0;i<lpkey->nrofvalues;i++) |
Alexandre Julliard | 0e270f4 | 1996-08-24 18:26:35 +0000 | [diff] [blame] | 3464 | if ( lpkey->values[i].name && |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3465 | !lstrcmpiW(lpkey->values[i].name,lpszValue) |
Alexandre Julliard | 0e270f4 | 1996-08-24 18:26:35 +0000 | [diff] [blame] | 3466 | ) |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3467 | break; |
| 3468 | } else { |
| 3469 | for (i=0;i<lpkey->nrofvalues;i++) |
| 3470 | if (lpkey->values[i].name==NULL) |
| 3471 | break; |
| 3472 | } |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3473 | |
| 3474 | if (i == lpkey->nrofvalues) |
| 3475 | return ERROR_FILE_NOT_FOUND; |
| 3476 | |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3477 | val = lpkey->values+i; |
| 3478 | if (val->name) free(val->name); |
| 3479 | if (val->data) free(val->data); |
| 3480 | memcpy( |
| 3481 | lpkey->values+i, |
| 3482 | lpkey->values+i+1, |
| 3483 | sizeof(KEYVALUE)*(lpkey->nrofvalues-i-1) |
| 3484 | ); |
| 3485 | lpkey->values = (LPKEYVALUE)xrealloc( |
| 3486 | lpkey->values, |
| 3487 | (lpkey->nrofvalues-1)*sizeof(KEYVALUE) |
| 3488 | ); |
| 3489 | lpkey->nrofvalues--; |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3490 | return ERROR_SUCCESS; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3491 | } |
| 3492 | |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3493 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3494 | /****************************************************************************** |
| 3495 | * RegDeleteValue32A [ADVAPI32.135] |
| 3496 | */ |
Huw D M Davies | df088c6 | 1999-07-10 11:41:24 +0000 | [diff] [blame] | 3497 | DWORD WINAPI RegDeleteValueA( HKEY hkey, LPCSTR lpszValue ) |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3498 | { |
| 3499 | LPWSTR lpszValueW; |
| 3500 | DWORD ret; |
| 3501 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 3502 | TRACE_(reg)("(%x,%s)\n",hkey,debugstr_a(lpszValue)); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3503 | lpszValueW = lpszValue?strdupA2W(lpszValue):NULL; |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3504 | ret = RegDeleteValueW( hkey, lpszValueW ); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3505 | if(lpszValueW) free(lpszValueW); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3506 | return ret; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3507 | } |
| 3508 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3509 | |
| 3510 | /****************************************************************************** |
| 3511 | * RegDeleteValue16 [KERNEL.222] |
| 3512 | */ |
| 3513 | DWORD WINAPI RegDeleteValue16( HKEY hkey, LPSTR lpszValue ) |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 3514 | { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 3515 | TRACE_(reg)("(%x,%s)\n", hkey,debugstr_a(lpszValue)); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3516 | return RegDeleteValueA( hkey, lpszValue ); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3517 | } |
| 3518 | |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 3519 | |
| 3520 | /****************************************************************************** |
| 3521 | * RegFlushKey [KERNEL.227] [ADVAPI32.143] |
Andreas Mohr | d4b13da | 1999-08-07 14:17:10 +0000 | [diff] [blame] | 3522 | * Immediately writes key to registry. |
| 3523 | * Only returns after data has been written to disk. |
| 3524 | * |
| 3525 | * FIXME: does it really wait until data is written ? |
| 3526 | * |
| 3527 | * I guess that we can remove the REG_OPTION_TAINTED flag from every key |
| 3528 | * written if this function really works (and only if !). |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 3529 | * |
| 3530 | * PARAMS |
| 3531 | * hkey [I] Handle of key to write |
| 3532 | * |
| 3533 | * RETURNS |
| 3534 | * Success: ERROR_SUCCESS |
| 3535 | * Failure: Error code |
| 3536 | */ |
| 3537 | DWORD WINAPI RegFlushKey( HKEY hkey ) |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 3538 | { |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3539 | LPKEYSTRUCT lpkey; |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3540 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 3541 | TRACE_(reg)("(%x)\n", hkey); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3542 | |
| 3543 | lpkey = lookup_hkey( hkey ); |
| 3544 | if (!lpkey) |
Andreas Mohr | 743885a | 1999-02-13 12:40:22 +0000 | [diff] [blame] | 3545 | return ERROR_BADKEY; |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3546 | |
Andreas Mohr | d4b13da | 1999-08-07 14:17:10 +0000 | [diff] [blame] | 3547 | SHELL_SaveRegistryBranch(find_root_key(lpkey), TRUE); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3548 | return ERROR_SUCCESS; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3549 | } |
| 3550 | |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 3551 | |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3552 | /* FIXME: lpcchXXXX ... is this counting in WCHARS or in BYTEs ?? */ |
| 3553 | |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 3554 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3555 | /****************************************************************************** |
| 3556 | * RegQueryInfoKey32W [ADVAPI32.153] |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 3557 | * |
| 3558 | * PARAMS |
| 3559 | * hkey [I] Handle to key to query |
| 3560 | * lpszClass [O] Buffer for class string |
| 3561 | * lpcchClass [O] Size of class string buffer |
| 3562 | * lpdwReserved [I] Reserved |
| 3563 | * lpcSubKeys [I] Buffer for number of subkeys |
| 3564 | * lpcchMaxSubKey [O] Buffer for longest subkey name length |
| 3565 | * lpcchMaxClass [O] Buffer for longest class string length |
| 3566 | * lpcValues [O] Buffer for number of value entries |
| 3567 | * lpcchMaxValueName [O] Buffer for longest value name length |
| 3568 | * lpccbMaxValueData [O] Buffer for longest value data length |
| 3569 | * lpcbSecurityDescriptor [O] Buffer for security descriptor length |
| 3570 | * ft |
John Richardson | 2bb013b | 1998-11-06 17:36:13 +0000 | [diff] [blame] | 3571 | * - win95 allows lpszClass to be valid and lpcchClass to be NULL |
| 3572 | * - winnt returns ERROR_INVALID_PARAMETER if lpszClass is valid and |
| 3573 | * lpcchClass is NULL |
| 3574 | * - both allow lpszClass to be NULL and lpcchClass to be NULL |
| 3575 | * (it's hard to test validity, so test !NULL instead) |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3576 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3577 | DWORD WINAPI RegQueryInfoKeyW( HKEY hkey, LPWSTR lpszClass, |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 3578 | LPDWORD lpcchClass, LPDWORD lpdwReserved, |
| 3579 | LPDWORD lpcSubKeys, LPDWORD lpcchMaxSubkey, |
| 3580 | LPDWORD lpcchMaxClass, LPDWORD lpcValues, |
| 3581 | LPDWORD lpcchMaxValueName, |
| 3582 | LPDWORD lpccbMaxValueData, |
| 3583 | LPDWORD lpcbSecurityDescriptor, FILETIME *ft ) |
| 3584 | { |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3585 | LPKEYSTRUCT lpkey,lpxkey; |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3586 | int nrofkeys,maxsubkey,maxclass,maxvname,maxvdata; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3587 | int i; |
| 3588 | |
Marcus Meissner | 450bc79 | 1999-05-09 15:59:27 +0000 | [diff] [blame] | 3589 | TRACE_(reg)("(%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", |
| 3590 | hkey, lpszClass, lpcchClass?*lpcchClass:0,lpdwReserved, |
| 3591 | lpcSubKeys,lpcchMaxSubkey,lpcValues,lpcchMaxValueName, |
| 3592 | lpccbMaxValueData,lpcbSecurityDescriptor,ft |
| 3593 | ); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3594 | lpkey = lookup_hkey(hkey); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3595 | if (!lpkey) |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3596 | return ERROR_INVALID_HANDLE; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3597 | if (lpszClass) { |
John Richardson | 2bb013b | 1998-11-06 17:36:13 +0000 | [diff] [blame] | 3598 | if (VERSION_GetVersion() == NT40 && lpcchClass == NULL) { |
| 3599 | return ERROR_INVALID_PARAMETER; |
| 3600 | } |
| 3601 | /* either lpcchClass is valid or this is win95 and lpcchClass |
| 3602 | could be invalid */ |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3603 | if (lpkey->class) { |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3604 | DWORD classLen = lstrlenW(lpkey->class); |
John Richardson | 2bb013b | 1998-11-06 17:36:13 +0000 | [diff] [blame] | 3605 | |
| 3606 | if (lpcchClass && classLen+1>*lpcchClass) { |
| 3607 | *lpcchClass=classLen+1; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3608 | return ERROR_MORE_DATA; |
| 3609 | } |
John Richardson | 2bb013b | 1998-11-06 17:36:13 +0000 | [diff] [blame] | 3610 | if (lpcchClass) |
| 3611 | *lpcchClass=classLen; |
| 3612 | memcpy(lpszClass,lpkey->class, classLen*2 + 2); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3613 | } else { |
| 3614 | *lpszClass = 0; |
John Richardson | 2bb013b | 1998-11-06 17:36:13 +0000 | [diff] [blame] | 3615 | if (lpcchClass) |
| 3616 | *lpcchClass = 0; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3617 | } |
| 3618 | } else { |
| 3619 | if (lpcchClass) |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3620 | *lpcchClass = lstrlenW(lpkey->class); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3621 | } |
| 3622 | lpxkey=lpkey->nextsub; |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3623 | nrofkeys=maxsubkey=maxclass=maxvname=maxvdata=0; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3624 | while (lpxkey) { |
| 3625 | nrofkeys++; |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3626 | if (lstrlenW(lpxkey->keyname)>maxsubkey) |
| 3627 | maxsubkey=lstrlenW(lpxkey->keyname); |
| 3628 | if (lpxkey->class && lstrlenW(lpxkey->class)>maxclass) |
| 3629 | maxclass=lstrlenW(lpxkey->class); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3630 | lpxkey=lpxkey->next; |
| 3631 | } |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3632 | for (i=0;i<lpkey->nrofvalues;i++) { |
| 3633 | LPKEYVALUE val=lpkey->values+i; |
| 3634 | |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3635 | if (val->name && lstrlenW(val->name)>maxvname) |
| 3636 | maxvname=lstrlenW(val->name); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3637 | if (val->len>maxvdata) |
| 3638 | maxvdata=val->len; |
| 3639 | } |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3640 | if (!maxclass) maxclass = 1; |
| 3641 | if (!maxvname) maxvname = 1; |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3642 | if (lpcValues) |
| 3643 | *lpcValues = lpkey->nrofvalues; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3644 | if (lpcSubKeys) |
| 3645 | *lpcSubKeys = nrofkeys; |
| 3646 | if (lpcchMaxSubkey) |
John Richardson | 2bb013b | 1998-11-06 17:36:13 +0000 | [diff] [blame] | 3647 | *lpcchMaxSubkey = maxsubkey; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3648 | if (lpcchMaxClass) |
John Richardson | 2bb013b | 1998-11-06 17:36:13 +0000 | [diff] [blame] | 3649 | *lpcchMaxClass = maxclass; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3650 | if (lpcchMaxValueName) |
| 3651 | *lpcchMaxValueName= maxvname; |
| 3652 | if (lpccbMaxValueData) |
| 3653 | *lpccbMaxValueData= maxvdata; |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3654 | return ERROR_SUCCESS; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3655 | } |
| 3656 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3657 | |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 3658 | /****************************************************************************** |
| 3659 | * RegQueryInfoKey32A [ADVAPI32.152] |
| 3660 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3661 | DWORD WINAPI RegQueryInfoKeyA( HKEY hkey, LPSTR lpszClass, LPDWORD lpcchClass, |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 3662 | LPDWORD lpdwReserved, LPDWORD lpcSubKeys, |
| 3663 | LPDWORD lpcchMaxSubkey, LPDWORD lpcchMaxClass, |
| 3664 | LPDWORD lpcValues, LPDWORD lpcchMaxValueName, |
| 3665 | LPDWORD lpccbMaxValueData, |
| 3666 | LPDWORD lpcbSecurityDescriptor, FILETIME *ft ) |
| 3667 | { |
John Richardson | 2bb013b | 1998-11-06 17:36:13 +0000 | [diff] [blame] | 3668 | LPWSTR lpszClassW = NULL; |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3669 | DWORD ret; |
| 3670 | |
Marcus Meissner | 450bc79 | 1999-05-09 15:59:27 +0000 | [diff] [blame] | 3671 | TRACE_(reg)("(%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", |
| 3672 | hkey, lpszClass, lpcchClass?*lpcchClass:0,lpdwReserved, |
| 3673 | lpcSubKeys,lpcchMaxSubkey,lpcValues,lpcchMaxValueName, |
| 3674 | lpccbMaxValueData,lpcbSecurityDescriptor,ft |
| 3675 | ); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3676 | if (lpszClass) { |
John Richardson | 2bb013b | 1998-11-06 17:36:13 +0000 | [diff] [blame] | 3677 | if (lpcchClass) { |
| 3678 | lpszClassW = (LPWSTR)xmalloc((*lpcchClass) * 2); |
| 3679 | } else if (VERSION_GetVersion() == WIN95) { |
| 3680 | /* win95 allows lpcchClass to be null */ |
| 3681 | /* we don't know how big lpszClass is, would |
| 3682 | MAX_PATHNAME_LEN be the correct default? */ |
| 3683 | lpszClassW = (LPWSTR)xmalloc(MAX_PATHNAME_LEN*2); |
| 3684 | } |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3685 | |
| 3686 | } else |
| 3687 | lpszClassW = NULL; |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3688 | ret=RegQueryInfoKeyW( |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3689 | hkey, |
| 3690 | lpszClassW, |
| 3691 | lpcchClass, |
| 3692 | lpdwReserved, |
| 3693 | lpcSubKeys, |
| 3694 | lpcchMaxSubkey, |
| 3695 | lpcchMaxClass, |
| 3696 | lpcValues, |
| 3697 | lpcchMaxValueName, |
| 3698 | lpccbMaxValueData, |
| 3699 | lpcbSecurityDescriptor, |
| 3700 | ft |
| 3701 | ); |
Alexandre Julliard | 641ee76 | 1997-08-04 16:34:36 +0000 | [diff] [blame] | 3702 | if (ret==ERROR_SUCCESS && lpszClass) |
Alexandre Julliard | 7ebe1a4 | 1996-12-22 18:27:48 +0000 | [diff] [blame] | 3703 | lstrcpyWtoA(lpszClass,lpszClassW); |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 3704 | if (lpszClassW) |
| 3705 | free(lpszClassW); |
| 3706 | return ret; |
| 3707 | } |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3708 | |
| 3709 | |
| 3710 | /****************************************************************************** |
| 3711 | * RegConnectRegistry32W [ADVAPI32.128] |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3712 | * |
| 3713 | * PARAMS |
| 3714 | * lpMachineName [I] Address of name of remote computer |
| 3715 | * hHey [I] Predefined registry handle |
| 3716 | * phkResult [I] Address of buffer for remote registry handle |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3717 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3718 | LONG WINAPI RegConnectRegistryW( LPCWSTR lpMachineName, HKEY hKey, |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3719 | LPHKEY phkResult ) |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 3720 | { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 3721 | TRACE_(reg)("(%s,%x,%p): stub\n",debugstr_w(lpMachineName),hKey,phkResult); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3722 | |
| 3723 | if (!lpMachineName || !*lpMachineName) { |
| 3724 | /* Use the local machine name */ |
| 3725 | return RegOpenKey16( hKey, "", phkResult ); |
| 3726 | } |
| 3727 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 3728 | FIXME_(reg)("Cannot connect to %s\n",debugstr_w(lpMachineName)); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3729 | return ERROR_BAD_NETPATH; |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3730 | } |
| 3731 | |
| 3732 | |
| 3733 | /****************************************************************************** |
| 3734 | * RegConnectRegistry32A [ADVAPI32.127] |
| 3735 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3736 | LONG WINAPI RegConnectRegistryA( LPCSTR machine, HKEY hkey, LPHKEY reskey ) |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3737 | { |
| 3738 | DWORD ret; |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3739 | LPWSTR machineW = strdupA2W(machine); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3740 | ret = RegConnectRegistryW( machineW, hkey, reskey ); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3741 | free(machineW); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3742 | return ret; |
Alexandre Julliard | 01d6346 | 1997-01-20 19:43:45 +0000 | [diff] [blame] | 3743 | } |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 3744 | |
| 3745 | |
| 3746 | /****************************************************************************** |
| 3747 | * RegGetKeySecurity [ADVAPI32.144] |
| 3748 | * Retrieves a copy of security descriptor protecting the registry key |
| 3749 | * |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3750 | * PARAMS |
| 3751 | * hkey [I] Open handle of key to set |
| 3752 | * SecurityInformation [I] Descriptor contents |
| 3753 | * pSecurityDescriptor [O] Address of descriptor for key |
| 3754 | * lpcbSecurityDescriptor [I/O] Address of size of buffer and description |
| 3755 | * |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 3756 | * RETURNS |
| 3757 | * Success: ERROR_SUCCESS |
| 3758 | * Failure: Error code |
| 3759 | */ |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3760 | LONG WINAPI RegGetKeySecurity( HKEY hkey, |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 3761 | SECURITY_INFORMATION SecurityInformation, |
Juergen Schmied | 1ed51af | 1999-02-12 17:47:07 +0000 | [diff] [blame] | 3762 | PSECURITY_DESCRIPTOR pSecurityDescriptor, |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 3763 | LPDWORD lpcbSecurityDescriptor ) |
| 3764 | { |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3765 | LPKEYSTRUCT lpkey; |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3766 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 3767 | TRACE_(reg)("(%x,%ld,%p,%ld)\n",hkey,SecurityInformation,pSecurityDescriptor, |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 3768 | lpcbSecurityDescriptor?*lpcbSecurityDescriptor:0); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3769 | |
| 3770 | lpkey = lookup_hkey( hkey ); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3771 | if (!lpkey) |
| 3772 | return ERROR_INVALID_HANDLE; |
| 3773 | |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 3774 | /* FIXME: Check for valid SecurityInformation values */ |
| 3775 | |
Alexandre Julliard | b24fc08 | 1999-02-25 16:36:07 +0000 | [diff] [blame] | 3776 | if (*lpcbSecurityDescriptor < sizeof(SECURITY_DESCRIPTOR)) |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3777 | return ERROR_INSUFFICIENT_BUFFER; |
| 3778 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 3779 | FIXME_(reg)("(%x,%ld,%p,%ld): stub\n",hkey,SecurityInformation, |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 3780 | pSecurityDescriptor,lpcbSecurityDescriptor?*lpcbSecurityDescriptor:0); |
| 3781 | |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 3782 | return ERROR_SUCCESS; |
| 3783 | } |
| 3784 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3785 | |
| 3786 | /****************************************************************************** |
| 3787 | * RegLoadKey32W [ADVAPI32.???] |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3788 | * |
| 3789 | * PARAMS |
| 3790 | * hkey [I] Handle of open key |
| 3791 | * lpszSubKey [I] Address of name of subkey |
| 3792 | * lpszFile [I] Address of filename for registry information |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3793 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3794 | LONG WINAPI RegLoadKeyW( HKEY hkey, LPCWSTR lpszSubKey, LPCWSTR lpszFile ) |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3795 | { |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3796 | LPKEYSTRUCT lpkey; |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 3797 | TRACE_(reg)("(%x,%s,%s)\n",hkey,debugstr_w(lpszSubKey),debugstr_w(lpszFile)); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3798 | |
| 3799 | /* Do this check before the hkey check */ |
| 3800 | if (!lpszSubKey || !*lpszSubKey || !lpszFile || !*lpszFile) |
| 3801 | return ERROR_INVALID_PARAMETER; |
| 3802 | |
| 3803 | lpkey = lookup_hkey( hkey ); |
| 3804 | if (!lpkey) |
| 3805 | return ERROR_INVALID_HANDLE; |
| 3806 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 3807 | FIXME_(reg)("(%x,%s,%s): stub\n",hkey,debugstr_w(lpszSubKey), |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 3808 | debugstr_w(lpszFile)); |
| 3809 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3810 | return ERROR_SUCCESS; |
| 3811 | } |
| 3812 | |
| 3813 | |
| 3814 | /****************************************************************************** |
| 3815 | * RegLoadKey32A [ADVAPI32.???] |
| 3816 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3817 | LONG WINAPI RegLoadKeyA( HKEY hkey, LPCSTR lpszSubKey, LPCSTR lpszFile ) |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3818 | { |
| 3819 | LONG ret; |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3820 | LPWSTR lpszSubKeyW = strdupA2W(lpszSubKey); |
| 3821 | LPWSTR lpszFileW = strdupA2W(lpszFile); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3822 | ret = RegLoadKeyW( hkey, lpszSubKeyW, lpszFileW ); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3823 | if(lpszFileW) free(lpszFileW); |
| 3824 | if(lpszSubKeyW) free(lpszSubKeyW); |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3825 | return ret; |
| 3826 | } |
| 3827 | |
| 3828 | |
| 3829 | /****************************************************************************** |
| 3830 | * RegNotifyChangeKeyValue [ADVAPI32.???] |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3831 | * |
| 3832 | * PARAMS |
| 3833 | * hkey [I] Handle of key to watch |
| 3834 | * fWatchSubTree [I] Flag for subkey notification |
| 3835 | * fdwNotifyFilter [I] Changes to be reported |
| 3836 | * hEvent [I] Handle of signaled event |
| 3837 | * fAsync [I] Flag for asynchronous reporting |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3838 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3839 | LONG WINAPI RegNotifyChangeKeyValue( HKEY hkey, BOOL fWatchSubTree, |
| 3840 | DWORD fdwNotifyFilter, HANDLE hEvent, |
| 3841 | BOOL fAsync ) |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3842 | { |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3843 | LPKEYSTRUCT lpkey; |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 3844 | TRACE_(reg)("(%x,%i,%ld,%x,%i)\n",hkey,fWatchSubTree,fdwNotifyFilter, |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3845 | hEvent,fAsync); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3846 | |
| 3847 | lpkey = lookup_hkey( hkey ); |
| 3848 | if (!lpkey) |
| 3849 | return ERROR_INVALID_HANDLE; |
| 3850 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 3851 | FIXME_(reg)("(%x,%i,%ld,%x,%i): stub\n",hkey,fWatchSubTree,fdwNotifyFilter, |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 3852 | hEvent,fAsync); |
| 3853 | |
Alexandre Julliard | dadf78f | 1998-05-17 17:13:43 +0000 | [diff] [blame] | 3854 | return ERROR_SUCCESS; |
| 3855 | } |
| 3856 | |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 3857 | |
| 3858 | /****************************************************************************** |
| 3859 | * RegUnLoadKey32W [ADVAPI32.173] |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3860 | * |
| 3861 | * PARAMS |
| 3862 | * hkey [I] Handle of open key |
| 3863 | * lpSubKey [I] Address of name of subkey to unload |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 3864 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3865 | LONG WINAPI RegUnLoadKeyW( HKEY hkey, LPCWSTR lpSubKey ) |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 3866 | { |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 3867 | FIXME_(reg)("(%x,%s): stub\n",hkey, debugstr_w(lpSubKey)); |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 3868 | return ERROR_SUCCESS; |
| 3869 | } |
| 3870 | |
| 3871 | |
| 3872 | /****************************************************************************** |
| 3873 | * RegUnLoadKey32A [ADVAPI32.172] |
| 3874 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3875 | LONG WINAPI RegUnLoadKeyA( HKEY hkey, LPCSTR lpSubKey ) |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 3876 | { |
| 3877 | LONG ret; |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3878 | LPWSTR lpSubKeyW = strdupA2W(lpSubKey); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3879 | ret = RegUnLoadKeyW( hkey, lpSubKeyW ); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3880 | if(lpSubKeyW) free(lpSubKeyW); |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 3881 | return ret; |
| 3882 | } |
| 3883 | |
| 3884 | |
| 3885 | /****************************************************************************** |
| 3886 | * RegSetKeySecurity [ADVAPI32.167] |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3887 | * |
| 3888 | * PARAMS |
| 3889 | * hkey [I] Open handle of key to set |
| 3890 | * SecurityInfo [I] Descriptor contents |
| 3891 | * pSecurityDesc [I] Address of descriptor for key |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 3892 | */ |
| 3893 | LONG WINAPI RegSetKeySecurity( HKEY hkey, SECURITY_INFORMATION SecurityInfo, |
Juergen Schmied | 1ed51af | 1999-02-12 17:47:07 +0000 | [diff] [blame] | 3894 | PSECURITY_DESCRIPTOR pSecurityDesc ) |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 3895 | { |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3896 | LPKEYSTRUCT lpkey; |
| 3897 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 3898 | TRACE_(reg)("(%x,%ld,%p)\n",hkey,SecurityInfo,pSecurityDesc); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3899 | |
| 3900 | /* It seems to perform this check before the hkey check */ |
| 3901 | if ((SecurityInfo & OWNER_SECURITY_INFORMATION) || |
| 3902 | (SecurityInfo & GROUP_SECURITY_INFORMATION) || |
| 3903 | (SecurityInfo & DACL_SECURITY_INFORMATION) || |
| 3904 | (SecurityInfo & SACL_SECURITY_INFORMATION)) { |
| 3905 | /* Param OK */ |
| 3906 | } else |
| 3907 | return ERROR_INVALID_PARAMETER; |
| 3908 | |
| 3909 | if (!pSecurityDesc) |
| 3910 | return ERROR_INVALID_PARAMETER; |
| 3911 | |
| 3912 | lpkey = lookup_hkey( hkey ); |
| 3913 | if (!lpkey) |
| 3914 | return ERROR_INVALID_HANDLE; |
| 3915 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 3916 | FIXME_(reg)(":(%x,%ld,%p): stub\n",hkey,SecurityInfo,pSecurityDesc); |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 3917 | |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 3918 | return ERROR_SUCCESS; |
| 3919 | } |
| 3920 | |
| 3921 | |
| 3922 | /****************************************************************************** |
| 3923 | * RegSaveKey32W [ADVAPI32.166] |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3924 | * |
| 3925 | * PARAMS |
| 3926 | * hkey [I] Handle of key where save begins |
| 3927 | * lpFile [I] Address of filename to save to |
| 3928 | * sa [I] Address of security structure |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 3929 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3930 | LONG WINAPI RegSaveKeyW( HKEY hkey, LPCWSTR lpFile, |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 3931 | LPSECURITY_ATTRIBUTES sa ) |
| 3932 | { |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3933 | LPKEYSTRUCT lpkey; |
| 3934 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 3935 | TRACE_(reg)("(%x,%s,%p)\n", hkey, debugstr_w(lpFile), sa); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3936 | |
| 3937 | /* It appears to do this check before the hkey check */ |
| 3938 | if (!lpFile || !*lpFile) |
| 3939 | return ERROR_INVALID_PARAMETER; |
| 3940 | |
| 3941 | lpkey = lookup_hkey( hkey ); |
| 3942 | if (!lpkey) |
| 3943 | return ERROR_INVALID_HANDLE; |
| 3944 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 3945 | FIXME_(reg)("(%x,%s,%p): stub\n", hkey, debugstr_w(lpFile), sa); |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 3946 | |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 3947 | return ERROR_SUCCESS; |
| 3948 | } |
| 3949 | |
| 3950 | |
| 3951 | /****************************************************************************** |
| 3952 | * RegSaveKey32A [ADVAPI32.165] |
| 3953 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3954 | LONG WINAPI RegSaveKeyA( HKEY hkey, LPCSTR lpFile, |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 3955 | LPSECURITY_ATTRIBUTES sa ) |
| 3956 | { |
| 3957 | LONG ret; |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3958 | LPWSTR lpFileW = strdupA2W(lpFile); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3959 | ret = RegSaveKeyW( hkey, lpFileW, sa ); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3960 | free(lpFileW); |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 3961 | return ret; |
| 3962 | } |
| 3963 | |
| 3964 | |
| 3965 | /****************************************************************************** |
| 3966 | * RegRestoreKey32W [ADVAPI32.164] |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3967 | * |
| 3968 | * PARAMS |
| 3969 | * hkey [I] Handle of key where restore begins |
| 3970 | * lpFile [I] Address of filename containing saved tree |
| 3971 | * dwFlags [I] Optional flags |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 3972 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3973 | LONG WINAPI RegRestoreKeyW( HKEY hkey, LPCWSTR lpFile, DWORD dwFlags ) |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 3974 | { |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3975 | LPKEYSTRUCT lpkey; |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 3976 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 3977 | TRACE_(reg)("(%x,%s,%ld)\n",hkey,debugstr_w(lpFile),dwFlags); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3978 | |
| 3979 | /* It seems to do this check before the hkey check */ |
| 3980 | if (!lpFile || !*lpFile) |
| 3981 | return ERROR_INVALID_PARAMETER; |
| 3982 | |
| 3983 | lpkey = lookup_hkey( hkey ); |
| 3984 | if (!lpkey) |
| 3985 | return ERROR_INVALID_HANDLE; |
| 3986 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 3987 | FIXME_(reg)("(%x,%s,%ld): stub\n",hkey,debugstr_w(lpFile),dwFlags); |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 3988 | |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 3989 | /* Check for file existence */ |
| 3990 | |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 3991 | return ERROR_SUCCESS; |
| 3992 | } |
| 3993 | |
| 3994 | |
| 3995 | /****************************************************************************** |
| 3996 | * RegRestoreKey32A [ADVAPI32.163] |
| 3997 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 3998 | LONG WINAPI RegRestoreKeyA( HKEY hkey, LPCSTR lpFile, DWORD dwFlags ) |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 3999 | { |
| 4000 | LONG ret; |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 4001 | LPWSTR lpFileW = strdupA2W(lpFile); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 4002 | ret = RegRestoreKeyW( hkey, lpFileW, dwFlags ); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 4003 | if(lpFileW) free(lpFileW); |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 4004 | return ret; |
| 4005 | } |
| 4006 | |
| 4007 | |
| 4008 | /****************************************************************************** |
| 4009 | * RegReplaceKey32W [ADVAPI32.162] |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 4010 | * |
| 4011 | * PARAMS |
| 4012 | * hkey [I] Handle of open key |
| 4013 | * lpSubKey [I] Address of name of subkey |
| 4014 | * lpNewFile [I] Address of filename for file with new data |
| 4015 | * lpOldFile [I] Address of filename for backup file |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 4016 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 4017 | LONG WINAPI RegReplaceKeyW( HKEY hkey, LPCWSTR lpSubKey, LPCWSTR lpNewFile, |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 4018 | LPCWSTR lpOldFile ) |
| 4019 | { |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 4020 | LPKEYSTRUCT lpkey; |
| 4021 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 4022 | TRACE_(reg)("(%x,%s,%s,%s)\n",hkey,debugstr_w(lpSubKey), |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 4023 | debugstr_w(lpNewFile),debugstr_w(lpOldFile)); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 4024 | |
| 4025 | lpkey = lookup_hkey( hkey ); |
| 4026 | if (!lpkey) |
| 4027 | return ERROR_INVALID_HANDLE; |
| 4028 | |
Alexandre Julliard | 06c275a | 1999-05-02 14:32:27 +0000 | [diff] [blame] | 4029 | FIXME_(reg)("(%x,%s,%s,%s): stub\n", hkey, debugstr_w(lpSubKey), |
Alexandre Julliard | 642d313 | 1998-07-12 19:29:36 +0000 | [diff] [blame] | 4030 | debugstr_w(lpNewFile),debugstr_w(lpOldFile)); |
| 4031 | |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 4032 | return ERROR_SUCCESS; |
| 4033 | } |
| 4034 | |
| 4035 | |
| 4036 | /****************************************************************************** |
| 4037 | * RegReplaceKey32A [ADVAPI32.161] |
| 4038 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 4039 | LONG WINAPI RegReplaceKeyA( HKEY hkey, LPCSTR lpSubKey, LPCSTR lpNewFile, |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 4040 | LPCSTR lpOldFile ) |
| 4041 | { |
| 4042 | LONG ret; |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 4043 | LPWSTR lpSubKeyW = strdupA2W(lpSubKey); |
| 4044 | LPWSTR lpNewFileW = strdupA2W(lpNewFile); |
| 4045 | LPWSTR lpOldFileW = strdupA2W(lpOldFile); |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 4046 | ret = RegReplaceKeyW( hkey, lpSubKeyW, lpNewFileW, lpOldFileW ); |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 4047 | free(lpOldFileW); |
| 4048 | free(lpNewFileW); |
| 4049 | free(lpSubKeyW); |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 4050 | return ret; |
| 4051 | } |
| 4052 | |