blob: 2c93d17da2a70b19980b9e896e131bbdb5b16b85 [file] [log] [blame]
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00001/*
2 * Registry Functions
3 *
4 * Copyright 1996 Marcus Meissner
Alexandre Julliardf90efa91998-06-14 15:24:15 +00005 * Copyright 1998 Matthew Becker
Sylvain St.Germaine5332221999-04-10 16:46:15 +00006 * Copyright 1999 Sylvain St-Germain
Alexandre Julliard02e90081998-01-04 17:49:09 +00007 *
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 Julliarddadf78f1998-05-17 17:13:43 +000011 *
Alexandre Julliarddadf78f1998-05-17 17:13:43 +000012 * 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 Julliardf90efa91998-06-14 15:24:15 +000018 * Option handling
Alexandre Julliard642d3131998-07-12 19:29:36 +000019 * Time for RegEnumKey*, RegQueryInfoKey*
Alexandre Julliardc981d0b1996-03-31 16:40:13 +000020 */
21
Marcus Meissner31b9dab1999-10-24 22:08:33 +000022#include "config.h"
23
Alexandre Julliardc981d0b1996-03-31 16:40:13 +000024#include <stdlib.h>
Alexandre Julliardc981d0b1996-03-31 16:40:13 +000025#include <string.h>
26#include <unistd.h>
27#include <ctype.h>
Alexandre Julliard8664b891996-04-05 14:58:24 +000028#include <errno.h>
Howard Abrams13277481999-07-10 13:16:29 +000029#ifdef HAVE_SYS_ERRNO_H
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000030#include <sys/errno.h>
Howard Abrams13277481999-07-10 13:16:29 +000031#endif
Alexandre Julliardcdcdede1996-04-21 14:57:41 +000032#include <sys/types.h>
33#include <sys/fcntl.h>
34#include <sys/stat.h>
Alexandre Julliard0623a6f1998-01-18 18:01:49 +000035#include <assert.h>
Alexandre Julliardcdcdede1996-04-21 14:57:41 +000036#include <time.h>
Marcus Meissner04c3e1d1999-02-19 10:37:02 +000037#include "windef.h"
38#include "winbase.h"
39#include "wine/winbase16.h"
40#include "wine/winestring.h"
Alexandre Julliardc981d0b1996-03-31 16:40:13 +000041#include "winerror.h"
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +000042#include "file.h"
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +000043#include "heap.h"
Alexandre Julliard06c275a1999-05-02 14:32:27 +000044#include "debugtools.h"
Alexandre Julliardc981d0b1996-03-31 16:40:13 +000045#include "xmalloc.h"
Marcus Meissner6b9dd2e1999-03-18 17:39:57 +000046#include "options.h"
Alexandre Julliardc981d0b1996-03-31 16:40:13 +000047#include "winreg.h"
John Richardson2bb013b1998-11-06 17:36:13 +000048#include "winversion.h"
Alexandre Julliardc981d0b1996-03-31 16:40:13 +000049
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000050DECLARE_DEBUG_CHANNEL(reg)
51DECLARE_DEBUG_CHANNEL(string)
52
Juergen Schmiedebc2b771998-11-14 18:59:30 +000053static void REGISTRY_Init(void);
Alexandre Julliardcdcdede1996-04-21 14:57:41 +000054/* FIXME: following defines should be configured global ... */
Alexandre Julliardc981d0b1996-03-31 16:40:13 +000055
Alexandre Julliardcdcdede1996-04-21 14:57:41 +000056/* NOTE: do not append a /. linux' mkdir() WILL FAIL if you do that */
Sylvain St.Germaine5332221999-04-10 16:46:15 +000057#define WINE_PREFIX "/.wine"
Marcus Meissneradf8a0c1999-06-12 08:18:38 +000058#define SAVE_USERS_DEFAULT ETCDIR"/wine.userreg"
59#define SAVE_LOCAL_MACHINE_DEFAULT ETCDIR"/wine.systemreg"
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +000060
61/* relative in ~user/.wine/ : */
Sylvain St.Germaine5332221999-04-10 16:46:15 +000062#define SAVE_CURRENT_USER "user.reg"
63#define SAVE_LOCAL_USERS_DEFAULT "wine.userreg"
64#define SAVE_LOCAL_MACHINE "system.reg"
Alexandre Julliardcdcdede1996-04-21 14:57:41 +000065
Sylvain St.Germaine5332221999-04-10 16:46:15 +000066#define KEY_REGISTRY "Software\\The WINE team\\WINE\\Registry"
67#define VAL_SAVEUPDATED "SaveOnlyUpdatedKeys"
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +000068
Alexandre Julliardd90840e1996-06-11 16:02:08 +000069/* one value of a key */
70typedef struct tagKEYVALUE
71{
72 LPWSTR name; /* name of value (UNICODE) or NULL for win31 */
73 DWORD type; /* type of value */
Alexandre Julliarda69b88b1998-03-15 20:29:56 +000074 DWORD len; /* length of data in BYTEs */
Alexandre Julliardd90840e1996-06-11 16:02:08 +000075 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 */
80typedef 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 Julliardcdcdede1996-04-21 14:57:41 +000094static KEYSTRUCT *key_classes_root=NULL; /* windows 3.1 global values */
Alexandre Julliardc981d0b1996-03-31 16:40:13 +000095static KEYSTRUCT *key_current_user=NULL; /* user specific values */
96static KEYSTRUCT *key_local_machine=NULL;/* machine specific values */
97static KEYSTRUCT *key_users=NULL; /* all users? */
98
99/* dynamic, not saved */
100static KEYSTRUCT *key_performance_data=NULL;
101static KEYSTRUCT *key_current_config=NULL;
102static 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 Julliarde658d821997-11-30 17:45:40 +0000107
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000108static struct openhandle {
109 LPKEYSTRUCT lpkey;
110 HKEY hkey;
111 REGSAM accessmask;
112} *openhandles=NULL;
113static int nrofopenhandles=0;
114/* Starts after 1 because 0,1 are reserved for Win16 */
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000115/* Note: Should always be even, as Win95 ADVAPI32.DLL reserves odd
116 HKEYs for remote registry access */
117static int currenthandle=2;
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000118
119
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000120/*
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000121 * QUESTION
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000122 * Are these doing the same as HEAP_strdupAtoW and HEAP_strdupWtoA?
123 * If so, can we remove them?
Alexandre Julliarda845b881998-06-01 10:44:35 +0000124 * 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 Julliarddadf78f1998-05-17 17:13:43 +0000128 */
Alexandre Julliarde658d821997-11-30 17:45:40 +0000129static LPWSTR strdupA2W(LPCSTR src)
130{
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000131 if(src) {
Alexandre Julliarde658d821997-11-30 17:45:40 +0000132 LPWSTR dest=xmalloc(2*strlen(src)+2);
133 lstrcpyAtoW(dest,src);
134 return dest;
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000135 }
136 return NULL;
Alexandre Julliarde658d821997-11-30 17:45:40 +0000137}
138
139static LPWSTR strdupW(LPCWSTR a) {
140 LPWSTR b;
141 int len;
142
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000143 if(a) {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000144 len=sizeof(WCHAR)*(lstrlenW(a)+1);
Alexandre Julliarde658d821997-11-30 17:45:40 +0000145 b=(LPWSTR)xmalloc(len);
146 memcpy(b,a,len);
147 return b;
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000148 }
149 return NULL;
150}
151
152LPWSTR 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 Julliarde658d821997-11-30 17:45:40 +0000160}
Juergen Schmied26cae9d1999-01-23 12:11:09 +0000161/*
162 * we need to convert A to W with '\0' in strings (MULTI_SZ)
163 */
164
Alexandre Julliarda3960291999-02-26 11:11:13 +0000165static LPWSTR lmemcpynAtoW( LPWSTR dst, LPCSTR src, INT n )
Juergen Schmied26cae9d1999-01-23 12:11:09 +0000166{ LPWSTR p = dst;
167
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000168 TRACE_(reg)("\"%s\" %i\n",src, n);
Juergen Schmied26cae9d1999-01-23 12:11:09 +0000169
170 while (n-- > 0) *p++ = (WCHAR)(unsigned char)*src++;
171
172 return dst;
173}
Alexandre Julliarda3960291999-02-26 11:11:13 +0000174static LPSTR lmemcpynWtoA( LPSTR dst, LPCWSTR src, INT n )
Juergen Schmied26cae9d1999-01-23 12:11:09 +0000175{ LPSTR p = dst;
176
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000177 TRACE_(string)("L\"%s\" %i\n",debugstr_w(src), n);
Juergen Schmied26cae9d1999-01-23 12:11:09 +0000178
179 while (n-- > 0) *p++ = (CHAR)*src++;
180
181 return dst;
182}
183
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000184static void debug_print_value (LPBYTE lpbData, LPKEYVALUE key)
185{
186 if (TRACE_ON(reg) && lpbData)
187 {
188 switch(key->type)
189 {
Noomen Hamzac4cd0bf1999-05-08 10:50:34 +0000190 case REG_EXPAND_SZ:
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000191 case REG_SZ:
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000192 TRACE_(reg)(" Value %s, Data(sz)=%s\n",
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000193 debugstr_w(key->name),
194 debugstr_w((LPCWSTR)lpbData));
195 break;
Juergen Schmied26cae9d1999-01-23 12:11:09 +0000196
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000197 case REG_DWORD:
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000198 TRACE_(reg)(" Value %s, Data(dword)=0x%08lx\n",
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000199 debugstr_w(key->name),
200 (DWORD)*lpbData);
201 break;
202
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000203 case REG_MULTI_SZ:
204 {
205 int i;
206 LPCWSTR ptr = (LPCWSTR)lpbData;
207 for (i=0;ptr[0];i++)
208 {
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000209 TRACE_(reg)(" Value %s, MULTI_SZ(%i=%s)\n",
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000210 debugstr_w(key->name),
211 i,
212 debugstr_w(ptr));
Juergen Schmied26cae9d1999-01-23 12:11:09 +0000213
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000214 ptr += lstrlenW(ptr)+1;
215 }
216 }
217 break;
218
Noomen Hamzac4cd0bf1999-05-08 10:50:34 +0000219 default:
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000220 {
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 Julliard06c275a1999-05-02 14:32:27 +0000232 TRACE_(reg)(" Value %s, Data(raw)=(%s)\n",
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000233 debugstr_w(key->name),
234 szTemp);
235 }
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000236 } /* switch */
237 } /* if */
Juergen Schmied26cae9d1999-01-23 12:11:09 +0000238}
239
Alexandre Julliarde658d821997-11-30 17:45:40 +0000240
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000241/******************************************************************************
242 * is_standard_hkey [Internal]
243 * Determines if a hkey is a standard key
244 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000245static BOOL is_standard_hkey( HKEY hkey )
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000246{
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 Julliardc981d0b1996-03-31 16:40:13 +0000262
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000263/******************************************************************************
264 * add_handle [Internal]
265 */
266static void add_handle( HKEY hkey, LPKEYSTRUCT lpkey, REGSAM accessmask )
267{
268 int i;
269
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000270 TRACE_(reg)("(0x%x,%p,0x%lx)\n",hkey,lpkey,accessmask);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000271 /* 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 Julliard06c275a1999-05-02 14:32:27 +0000279 WARN_(reg)("Adding handle %x twice\n",hkey);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000280 }
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 Julliardc981d0b1996-03-31 16:40:13 +0000289}
290
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000291
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000292/******************************************************************************
293 * get_handle [Internal]
294 *
295 * RETURNS
296 * Success: Pointer to key
297 * Failure: NULL
298 */
299static 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 Julliard06c275a1999-05-02 14:32:27 +0000306 WARN_(reg)("Could not find handle 0x%x\n",hkey);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000307 return NULL;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000308}
309
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000310
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000311/******************************************************************************
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 */
321static 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 Julliard06c275a1999-05-02 14:32:27 +0000330 WARN_(reg)("Could not find handle 0x%x\n",hkey);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000331 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 Julliardc981d0b1996-03-31 16:40:13 +0000341}
342
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000343/******************************************************************************
344 * lookup_hkey [Internal]
Alexandre Julliarda845b881998-06-01 10:44:35 +0000345 *
346 * Just as the name says. Creates the root keys on demand, so we can call the
347 * Reg* functions at any time.
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000348 *
349 * RETURNS
350 * Success: Pointer to key structure
351 * Failure: NULL
352 */
Alexandre Julliarda845b881998-06-01 10:44:35 +0000353#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 Julliarddadf78f1998-05-17 17:13:43 +0000358static LPKEYSTRUCT lookup_hkey( HKEY hkey )
359{
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000360 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 Julliarda845b881998-06-01 10:44:35 +0000371
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000372 /* calls lookup_hkey recursively, TWICE */
373 if ( RegCreateKey16(
374 HKEY_LOCAL_MACHINE,
375 "SOFTWARE\\Classes",
376 &cl_r_hkey) != ERROR_SUCCESS)
377 {
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000378 ERR_(reg)("Could not create HKLM\\SOFTWARE\\Classes. This is impossible.\n");
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000379 exit(1);
380 }
Alexandre Julliarda845b881998-06-01 10:44:35 +0000381
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000382 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 Julliardc981d0b1996-03-31 16:40:13 +0000429}
Andreas Mohrd4b13da1999-08-07 14:17:10 +0000430
431
432/*
433 * recursively searches for lpkey_to_find in the root key branch
434 * given in lpcurrkey.
435 */
436static int subkey_found(LPKEYSTRUCT lpcurrkey, LPKEYSTRUCT lpkey_to_find)
437{
Andreas Mohrd4b13da1999-08-07 14:17:10 +0000438 while (lpcurrkey)
439 {
Marcus Meissner1c405621999-09-03 12:19:34 +0000440 if (lpcurrkey == lpkey_to_find)
441 return 1;
Andreas Mohrd4b13da1999-08-07 14:17:10 +0000442 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 */
456static HKEY find_root_key(LPKEYSTRUCT lpkey)
457{
458 typedef struct tagROOT_KEYS {
Patrik Stridvalle92331f1999-09-20 18:52:06 +0000459 KEYSTRUCT *lpkey;
460 HKEY hkey;
Andreas Mohrd4b13da1999-08-07 14:17:10 +0000461 } ROOT_KEYS;
Patrik Stridvalle92331f1999-09-20 18:52:06 +0000462 ROOT_KEYS root_keys[4];
Andreas Mohrd4b13da1999-08-07 14:17:10 +0000463 int i;
464
Patrik Stridvalle92331f1999-09-20 18:52:06 +0000465 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 Mohrd4b13da1999-08-07 14:17:10 +0000474 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 Julliarda845b881998-06-01 10:44:35 +0000483#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 Julliarddadf78f1998-05-17 17:13:43 +0000492
493/******************************************************************************
494 * split_keypath [Internal]
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000495 * splits the unicode string 'wp' into an array of strings.
496 * the array is allocated by this function.
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000497 * Free the array using FREE_KEY_PATH
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000498 *
499 * PARAMS
500 * wp [I] String to split up
501 * wpv [O] Array of pointers to strings
502 * wpc [O] Number of components
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000503 */
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000504static void split_keypath( LPCWSTR wp, LPWSTR **wpv, int *wpc)
505{
506 int i,j,len;
507 LPWSTR ws;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000508
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000509 TRACE_(reg)("(%s,%p,%p)\n",debugstr_w(wp),wpv,wpc);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000510
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 Daviesf49cb521999-11-12 00:58:15 +0000536 /*TRACE_(reg) (" Subitem %d = %s\n",j-1,debugstr_w((*wpv)[j-1]));*/
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000537 }
538
539 (*wpv)[j]=NULL;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000540}
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000541#define FREE_KEY_PATH HeapFree(SystemHeap,0,wps[0]);HeapFree(SystemHeap,0,wps);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000542
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000543
544
545
546/******************************************************************************
Alexandre Julliarda845b881998-06-01 10:44:35 +0000547 * REGISTRY_Init [Internal]
548 * Registry initialisation, allocates some default keys.
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000549 */
Juergen Schmiedebc2b771998-11-14 18:59:30 +0000550static void REGISTRY_Init(void) {
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000551 HKEY hkey;
552 char buf[200];
Alexandre Julliard8bbf8181996-09-13 16:50:47 +0000553
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000554 TRACE_(reg)("(void)\n");
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000555
556 RegCreateKey16(HKEY_DYN_DATA,"PerfStats\\StatData",&hkey);
Alexandre Julliard8bbf8181996-09-13 16:50:47 +0000557 RegCloseKey(hkey);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000558
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000559 /* 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 Julliarda3960291999-02-26 11:11:13 +0000562 RegSetValueExA(hkey,"Identifier",0,REG_SZ,"SystemType WINE",strlen("SystemType WINE"));
Alexandre Julliard8bbf8181996-09-13 16:50:47 +0000563 RegCloseKey(hkey);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000564
Alexandre Julliard8bbf8181996-09-13 16:50:47 +0000565 /* \\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 Daviesf49cb521999-11-12 00:58:15 +0000577 */
Alexandre Julliard8bbf8181996-09-13 16:50:47 +0000578 if (-1!=gethostname(buf,200)) {
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000579 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 Julliard8bbf8181996-09-13 16:50:47 +0000582 }
583}
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000584
585
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000586/************************ 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 Julliardcdcdede1996-04-21 14:57:41 +0000595 * "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 Julliardc981d0b1996-03-31 16:40:13 +0000609 *
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000610 * FIXME: doesn't save 'class' (what does it mean anyway?), nor flags.
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000611 *
612 * [HKEY_CURRENT_USER\\Software\\The WINE team\\WINE\\Registry]
613 * SaveOnlyUpdatedKeys=yes
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000614 */
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000615
616/******************************************************************************
617 * _save_check_tainted [Internal]
618 */
619static int _save_check_tainted( LPKEYSTRUCT lpkey )
620{
Huw D M Daviesf49cb521999-11-12 00:58:15 +0000621 int tainted = 0;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000622
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000623 while (lpkey) {
Huw D M Daviesf49cb521999-11-12 00:58:15 +0000624 if (_save_check_tainted(lpkey->nextsub))
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000625 lpkey->flags |= REG_OPTION_TAINTED;
Huw D M Daviesf49cb521999-11-12 00:58:15 +0000626 if (lpkey->flags & REG_OPTION_TAINTED)
627 tainted = 1;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000628 lpkey = lpkey->next;
629 }
630 return tainted;
631}
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000632
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000633/******************************************************************************
634 * _save_USTRING [Internal]
635 */
636static void _save_USTRING( FILE *F, LPWSTR wstr, int escapeeq )
637{
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000638 LPWSTR s;
639 int doescape;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000640
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000641 if (wstr==NULL)
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000642 return;
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000643 s=wstr;
644 while (*s) {
645 doescape=0;
Marcus Meissner229a28f1999-10-13 12:15:19 +0000646 if (*s>0x7f)
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000647 doescape = 1;
648 if (*s=='\n')
649 doescape = 1;
650 if (escapeeq && *s=='=')
651 doescape = 1;
652 if (*s=='\\')
Alexandre Julliard641ee761997-08-04 16:34:36 +0000653 fputc(*s,F); /* if \\ then put it twice. */
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000654 if (doescape)
655 fprintf(F,"\\u%04x",*((unsigned short*)s));
656 else
657 fputc(*s,F);
658 s++;
659 }
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000660}
661
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000662/******************************************************************************
663 * _savesubkey [Internal]
Juergen Schmiedf74fa4e1999-01-31 09:19:46 +0000664 *
665 * NOTES
666 * REG_MULTI_SZ is handled as binary (like in win95) (js)
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000667 */
668static int _savesubkey( FILE *F, LPKEYSTRUCT lpkey, int level, int all )
669{
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000670 LPKEYSTRUCT lpxkey;
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000671 int i,tabs,j;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000672
673 lpxkey = lpkey;
674 while (lpxkey) {
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000675 if ( !(lpxkey->flags & REG_OPTION_VOLATILE) &&
676 (all || (lpxkey->flags & REG_OPTION_TAINTED))
677 ) {
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000678 for (tabs=level;tabs--;)
679 fputc('\t',F);
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000680 _save_USTRING(F,lpxkey->keyname,1);
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000681 fputs("\n",F);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000682 for (i=0;i<lpxkey->nrofvalues;i++) {
683 LPKEYVALUE val=lpxkey->values+i;
684
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000685 for (tabs=level+1;tabs--;)
686 fputc('\t',F);
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000687 _save_USTRING(F,val->name,0);
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000688 fputc('=',F);
689 fprintf(F,"%ld,%ld,",val->type,val->lastmodified);
Juergen Schmiedf74fa4e1999-01-31 09:19:46 +0000690 if ( val->type == REG_SZ || val->type == REG_EXPAND_SZ )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000691 _save_USTRING(F,(LPWSTR)val->data,0);
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000692 else
693 for (j=0;j<val->len;j++)
694 fprintf(F,"%02x",*((unsigned char*)val->data+j));
695 fputs("\n",F);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000696 }
697 /* descend recursively */
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000698 if (!_savesubkey(F,lpxkey->nextsub,level+1,all))
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000699 return 0;
700 }
701 lpxkey=lpxkey->next;
702 }
703 return 1;
704}
705
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000706
707/******************************************************************************
708 * _savesubreg [Internal]
709 */
710static int _savesubreg( FILE *F, LPKEYSTRUCT lpkey, int all )
711{
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000712 fprintf(F,"WINE REGISTRY Version %d\n",REGISTRY_SAVE_VERSION);
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000713 _save_check_tainted(lpkey->nextsub);
714 return _savesubkey(F,lpkey->nextsub,0,all);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000715}
716
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000717
718/******************************************************************************
719 * _savereg [Internal]
720 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000721static BOOL _savereg( LPKEYSTRUCT lpkey, char *fn, int all )
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000722{
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000723 FILE *F;
724
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000725 F=fopen(fn,"w");
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000726 if (F==NULL) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000727 WARN_(reg)("Couldn't open %s for writing: %s\n",
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000728 fn,strerror(errno)
729 );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000730 return FALSE;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000731 }
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000732 if (!_savesubreg(F,lpkey,all)) {
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000733 fclose(F);
734 unlink(fn);
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000735 WARN_(reg)("Failed to save keys, perhaps no more diskspace for %s?\n",fn);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000736 return FALSE;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000737 }
738 fclose(F);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000739 return TRUE;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000740}
741
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000742
743/******************************************************************************
Andreas Mohrd4b13da1999-08-07 14:17:10 +0000744 * SHELL_SaveRegistryBranch [Internal]
745 *
746 * Saves main registry branch specified by hkey.
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000747 */
Andreas Mohrd4b13da1999-08-07 14:17:10 +0000748static void SHELL_SaveRegistryBranch(HKEY hkey, int all)
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000749{
Alexandre Julliard154c99b1999-04-25 12:41:36 +0000750 char *fn, *home, *tmp;
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000751
Nathaniel7bf36ad1999-10-24 19:35:47 +0000752 /* 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 Mohrd4b13da1999-08-07 14:17:10 +0000756 /* FIXME: does this check apply to all keys written below ? */
Alexandre Julliard154c99b1999-04-25 12:41:36 +0000757 if (!(home = getenv( "HOME" )))
Andreas Mohrd4b13da1999-08-07 14:17:10 +0000758 ERR_(reg)("Failed to get homedirectory of UID %ld.\n",(long) getuid());
Andreas Mohrd4b13da1999-08-07 14:17:10 +0000759
Nathaniel7bf36ad1999-10-24 19:35:47 +0000760 /* HKEY_LOCAL_MACHINE contains the HKEY_CLASSES_ROOT branch */
761 if (hkey == HKEY_CLASSES_ROOT) hkey = HKEY_LOCAL_MACHINE;
Andreas Mohrd4b13da1999-08-07 14:17:10 +0000762
Nathaniel7bf36ad1999-10-24 19:35:47 +0000763 switch (hkey)
Andreas Mohrd4b13da1999-08-07 14:17:10 +0000764 {
Nathaniel7bf36ad1999-10-24 19:35:47 +0000765 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 Mohrd4b13da1999-08-07 14:17:10 +0000771
Nathaniel7bf36ad1999-10-24 19:35:47 +0000772 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 Julliard154c99b1999-04-25 12:41:36 +0000778
Nathaniel7bf36ad1999-10-24 19:35:47 +0000779 /* create the directory. don't care about errorcodes. */
780 mkdir(fn,0755); /* drwxr-xr-x */
781 strcat(fn,"/"SAVE_CURRENT_USER);
Nathan Zorichbd3771c1999-03-14 15:12:48 +0000782
Nathaniel7bf36ad1999-10-24 19:35:47 +0000783 tmp = (char*)xmalloc(strlen(fn)+strlen(".tmp")+1);
784 strcpy(tmp,fn);
785 strcat(tmp,".tmp");
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000786
Nathaniel7bf36ad1999-10-24 19:35:47 +0000787 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 Julliard154c99b1999-04-25 12:41:36 +0000792 }
Nathaniel7bf36ad1999-10-24 19:35:47 +0000793 free(tmp);
794 free(fn);
Alexandre Julliard154c99b1999-04-25 12:41:36 +0000795 }
Nathaniel7bf36ad1999-10-24 19:35:47 +0000796 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 Zorichbd3771c1999-03-14 15:12:48 +0000804
Nathaniel7bf36ad1999-10-24 19:35:47 +0000805 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 Julliard154c99b1999-04-25 12:41:36 +0000811
Nathaniel7bf36ad1999-10-24 19:35:47 +0000812 tmp = (char*)xmalloc(strlen(fn)+strlen(".tmp")+1);
813 strcpy(tmp,fn);
814 strcat(tmp,".tmp");
Alexandre Julliard154c99b1999-04-25 12:41:36 +0000815
Nathaniel7bf36ad1999-10-24 19:35:47 +0000816 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 Julliard154c99b1999-04-25 12:41:36 +0000821 }
Nathaniel7bf36ad1999-10-24 19:35:47 +0000822 free(tmp);
823 free(fn);
Alexandre Julliard154c99b1999-04-25 12:41:36 +0000824 }
Nathaniel7bf36ad1999-10-24 19:35:47 +0000825 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 Zorichbd3771c1999-03-14 15:12:48 +0000832
Nathaniel7bf36ad1999-10-24 19:35:47 +0000833 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.Germaine5332221999-04-10 16:46:15 +0000839
Nathaniel7bf36ad1999-10-24 19:35:47 +0000840 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 Julliard154c99b1999-04-25 12:41:36 +0000851 }
Nathaniel7bf36ad1999-10-24 19:35:47 +0000852 break;
853 default:
854 ERR_(reg)("unknown/invalid key handle !\n");
855 break;
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000856 }
Andreas Mohrd4b13da1999-08-07 14:17:10 +0000857}
858
859
860/******************************************************************************
861 * SHELL_SaveRegistry [Internal]
862 */
863void 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 Julliardc981d0b1996-03-31 16:40:13 +0000899}
900
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000901
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000902/************************ LOAD Registry Function ****************************/
903
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000904
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000905
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000906/******************************************************************************
907 * _find_or_add_key [Internal]
908 */
909static LPKEYSTRUCT _find_or_add_key( LPKEYSTRUCT lpkey, LPWSTR keyname )
910{
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000911 LPKEYSTRUCT lpxkey,*lplpkey;
912
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000913 if ((!keyname) || (keyname[0]==0)) {
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000914 free(keyname);
915 return lpkey;
916 }
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000917 lplpkey= &(lpkey->nextsub);
918 lpxkey = *lplpkey;
919 while (lpxkey) {
Marcus Meissnerf2ef1451999-06-26 11:41:33 +0000920 if ( tolower(lpxkey->keyname[0])==tolower(keyname[0]) &&
Alexandre Julliarda3960291999-02-26 11:11:13 +0000921 !lstrcmpiW(lpxkey->keyname,keyname)
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000922 )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000923 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 Julliardf90efa91998-06-14 15:24:15 +0000937/******************************************************************************
938 * _find_or_add_value [Internal]
939 */
940static void _find_or_add_value( LPKEYSTRUCT lpkey, LPWSTR name, DWORD type,
941 LPBYTE data, DWORD len, DWORD lastmodified )
942{
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000943 LPKEYVALUE val=NULL;
944 int i;
945
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000946 if (name && !*name) {/* empty string equals default (NULL) value */
947 free(name);
948 name = NULL;
949 }
950
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000951 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 Meissnerf2ef1451999-06-26 11:41:33 +0000957 if ( val->name!=NULL &&
958 tolower(val->name[0])==tolower(name[0]) &&
Alexandre Julliarda3960291999-02-26 11:11:13 +0000959 !lstrcmpiW(val->name,name)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000960 )
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 Hamza9adef531999-04-24 11:49:26 +0000979
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 Julliarde2bfa4c1996-05-16 18:21:06 +0000987 val->len = len;
988 if (val->data)
989 free(val->data);
990 val->data = data;
991 } else
992 free(data);
993}
994
995
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000996/******************************************************************************
997 * _wine_read_line [Internal]
998 *
999 * reads a line including dynamically enlarging the readbuffer and throwing
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001000 * away comments
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00001001 */
Alexandre Julliardf90efa91998-06-14 15:24:15 +00001002static int _wine_read_line( FILE *F, char **buf, int *len )
1003{
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001004 char *s,*curread;
1005 int mylen,curoff;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00001006
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001007 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 Julliardc981d0b1996-03-31 16:40:13 +00001027 }
1028 }
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001029 /* 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 Julliardf90efa91998-06-14 15:24:15 +00001041
1042/******************************************************************************
1043 * _wine_read_USTRING [Internal]
1044 *
1045 * converts a char* into a UNICODE string (up to a special char)
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001046 * and returns the position exactly after that string
1047 */
Alexandre Julliardf90efa91998-06-14 15:24:15 +00001048static char* _wine_read_USTRING( char *buf, LPWSTR *str )
1049{
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001050 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 Julliard638f1691999-01-17 16:32:32 +00001067 if (!*s) {
1068 /* Dangling \ ... may only happen if a registry
1069 * write was short. FIXME: What do to?
1070 */
1071 break;
1072 }
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001073 if (*s=='\\') {
Alexandre Julliard84c70f51997-05-09 08:40:27 +00001074 *ws++='\\';
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001075 s++;
1076 continue;
1077 }
1078 if (*s!='u') {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001079 WARN_(reg)("Non unicode escape sequence \\%c found in |%s|\n",*s,buf);
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001080 *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 Julliard06c275a1999-05-02 14:32:27 +00001089 WARN_(reg)("Strange escape sequence %s found in |%s|\n",xbuf,buf);
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001090 s+=4;
1091 *ws++ =(unsigned short)wc;
1092 }
1093 }
1094 }
1095 *ws = 0;
1096 ws = *str;
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001097 if (*ws)
1098 *str = strdupW(*str);
1099 else
1100 *str = NULL;
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001101 free(ws);
1102 return s;
1103}
1104
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001105
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 */
1116static int _wine_loadsubkey( FILE *F, LPKEYSTRUCT lpkey, int level, char **buf,
1117 int *buflen, DWORD optflag )
1118{
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001119 LPKEYSTRUCT lpxkey;
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001120 int i;
1121 char *s;
1122 LPWSTR name;
1123
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001124 TRACE_(reg)("(%p,%p,%d,%s,%d,%lx)\n", F, lpkey, level, debugstr_a(*buf),
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001125 *buflen, optflag);
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001126
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001127 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 Julliard06c275a1999-05-02 14:32:27 +00001139 WARN_(reg)("Got a subhierarchy without resp. key?\n");
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001140 return 0;
1141 }
Eric Pouechc0bcf261999-11-04 01:38:11 +00001142 if (!_wine_loadsubkey(F,lpxkey,level+1,buf,buflen,optflag))
1143 if (!_wine_read_line(F,buf,buflen))
1144 return 1;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001145 continue;
1146 }
1147
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001148 /* let the caller handle this line */
1149 if (i<level || **buf=='\0')
1150 return 1;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001151
1152 /* it can be: a value or a keyname. Parse the name first */
1153 s=_wine_read_USTRING(s,&name);
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001154
1155 /* switch() default: hack to avoid gotos */
1156 switch (0) {
1157 default:
1158 if (*s=='\0') {
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001159 lpxkey=_find_or_add_key(lpkey,name);
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001160 } else {
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001161 LPBYTE data;
1162 int len,lastmodified,type;
1163
1164 if (*s!='=') {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001165 WARN_(reg)("Unexpected character: %c\n",*s);
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001166 break;
1167 }
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001168 s++;
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001169 if (2!=sscanf(s,"%d,%d,",&type,&lastmodified)) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001170 WARN_(reg)("Haven't understood possible value in |%s|, skipping.\n",*buf);
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001171 break;
1172 }
1173 /* skip the 2 , */
1174 s=strchr(s,',');s++;
Eric Pouechc0bcf261999-11-04 01:38:11 +00001175 s=strchr(s,',');
1176 if (!s++) {
1177 WARN_(reg)("Haven't understood possible value in |%s|, skipping.\n",*buf);
1178 break;
1179 }
Juergen Schmiedf74fa4e1999-01-31 09:19:46 +00001180 if (type == REG_SZ || type == REG_EXPAND_SZ) {
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001181 s=_wine_read_USTRING(s,(LPWSTR*)&data);
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001182 if (data)
Alexandre Julliarda3960291999-02-26 11:11:13 +00001183 len = lstrlenW((LPWSTR)data)*2+2;
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001184 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 Julliard46ea8b31998-05-03 19:01:20 +00001194 data[i]=(*s-'a'+'\xa')<<4;
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001195 if (*s>='A' && *s<='F')
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001196 data[i]=(*s-'A'+'\xa')<<4;
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001197 s++;
1198 if (*s>='0' && *s<='9')
1199 data[i]|=*s-'0';
1200 if (*s>='a' && *s<='f')
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001201 data[i]|=*s-'a'+'\xa';
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001202 if (*s>='A' && *s<='F')
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001203 data[i]|=*s-'A'+'\xa';
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001204 s++;
1205 }
1206 }
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001207 _find_or_add_value(lpkey,name,type,data,len,lastmodified);
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001208 }
1209 }
1210 /* read the next line */
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001211 if (!_wine_read_line(F,buf,buflen))
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001212 return 1;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001213 }
1214 return 1;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00001215}
1216
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001217
1218/******************************************************************************
1219 * _wine_loadsubreg [Internal]
1220 */
1221static int _wine_loadsubreg( FILE *F, LPKEYSTRUCT lpkey, DWORD optflag )
1222{
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001223 int ver;
1224 char *buf;
1225 int buflen;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00001226
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001227 buf=xmalloc(10);buflen=10;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001228 if (!_wine_read_line(F,&buf,&buflen)) {
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001229 free(buf);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00001230 return 0;
1231 }
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001232 if (!sscanf(buf,"WINE REGISTRY Version %d",&ver)) {
1233 free(buf);
1234 return 0;
1235 }
1236 if (ver!=REGISTRY_SAVE_VERSION) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001237 TRACE_(reg)("Old format (%d) registry found, ignoring it. (buf was %s).\n",ver,buf);
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001238 free(buf);
1239 return 0;
1240 }
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001241 if (!_wine_read_line(F,&buf,&buflen)) {
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001242 free(buf);
1243 return 0;
1244 }
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001245 if (!_wine_loadsubkey(F,lpkey,0,&buf,&buflen,optflag)) {
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001246 free(buf);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00001247 return 0;
1248 }
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001249 free(buf);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00001250 return 1;
1251}
1252
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00001253
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001254/******************************************************************************
1255 * _wine_loadreg [Internal]
1256 */
1257static void _wine_loadreg( LPKEYSTRUCT lpkey, char *fn, DWORD optflag )
1258{
1259 FILE *F;
1260
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001261 TRACE_(reg)("(%p,%s,%lx)\n",lpkey,debugstr_a(fn),optflag);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001262
1263 F = fopen(fn,"rb");
1264 if (F==NULL) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001265 WARN_(reg)("Couldn't open %s for reading: %s\n",fn,strerror(errno) );
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001266 return;
1267 }
1268 if (!_wine_loadsubreg(F,lpkey,optflag)) {
1269 fclose(F);
1270 unlink(fn);
1271 return;
1272 }
1273 fclose(F);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00001274}
1275
Sylvain St.Germaine5332221999-04-10 16:46:15 +00001276/******************************************************************************
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 */
1288static void _flush_reg(LPKEYSTRUCT from);
1289
1290static 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}
1304static 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 Julliarddadf78f1998-05-17 17:13:43 +00001340
1341/******************************************************************************
1342 * _copy_registry [Internal]
1343 */
1344static void _copy_registry( LPKEYSTRUCT from, LPKEYSTRUCT to )
1345{
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001346 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 Julliarda11d7b11998-03-01 20:05:02 +00001361 data=(LPBYTE)xmalloc(valfrom->len);
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001362 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 Julliarddadf78f1998-05-17 17:13:43 +00001378
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001379/* 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 Julliard02e90081998-01-04 17:49:09 +00001386 * 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 Julliarde2bfa4c1996-05-16 18:21:06 +00001392 *
1393 * 20: RGKN_section:
1394 * header:
1395 * 0 : "RGKN" - magic
Alexandre Julliard02e90081998-01-04 17:49:09 +00001396 * 4 : DWORD offset to first RGDB section
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001397 * 8 : DWORD offset to the root record
Alexandre Julliard02e90081998-01-04 17:49:09 +00001398 * C..0x1B: ? (fill in)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001399 * 0x20 ... offset_of_RGDB_part: Disk Key Entry structures
1400 *
1401 * Disk Key Entry Structure:
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001402 * 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 Julliarde2bfa4c1996-05-16 18:21:06 +00001405 * 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 Julliard60ce85c1998-02-01 18:33:27 +00001415 * 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 Julliarde2bfa4c1996-05-16 18:21:06 +00001418 *
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 Julliard60ce85c1998-02-01 18:33:27 +00001423 * CPS - I have not experienced the above phenomenon in my registry files
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001424 *
1425 * RGDB_section:
1426 * 00: "RGDB" - magic
Alexandre Julliard02e90081998-01-04 17:49:09 +00001427 * 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 Julliarde2bfa4c1996-05-16 18:21:06 +00001433 * 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 Julliard02e90081998-01-04 17:49:09 +00001460 * 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 Julliarde2bfa4c1996-05-16 18:21:06 +00001464 * FIXME: this description needs some serious help, yes.
1465 */
1466
1467struct _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
1476struct _w95key {
1477 char *name;
1478 int nrofvals;
1479 struct _w95keyvalue *values;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001480 struct _w95key *prevlvl;
1481 struct _w95key *nextsub;
1482 struct _w95key *next;
1483};
1484
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001485
1486struct _w95_info {
1487 char *rgknbuffer;
1488 int rgknsize;
1489 char *rgdbbuffer;
1490 int rgdbsize;
1491 int depth;
1492 int lastmodified;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001493};
1494
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001495
1496/******************************************************************************
1497 * _w95_processKey [Internal]
1498 */
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001499static LPKEYSTRUCT _w95_processKey ( LPKEYSTRUCT lpkey,
1500 int nrLS, int nrMS, struct _w95_info *info )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001501
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001502{
1503 /* Disk Key Header structure (RGDB part) */
Alexandre Julliarda11d7b11998-03-01 20:05:02 +00001504 struct dkh {
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001505 unsigned long nextkeyoff;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001506 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 Julliarde2bfa4c1996-05-16 18:21:06 +00001523
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001524
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 Gay6f0056d1999-04-11 12:00:15 +00001550 if ((curdata + len) <= end) {\
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001551 memcpy(whereto,curdata,len);\
1552 curdata+=len;\
1553 bytesread+=len;\
1554 }
1555
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001556 while (curdata < next) {
Marcus Meissnerf4f17191998-10-17 12:10:19 +00001557 struct dkh *xdkh = (struct dkh*)curdata;
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001558
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001559 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 Julliard60ce85c1998-02-01 18:33:27 +00001567
1568 if (dkh.nrLS != nrLS) return (NULL);
1569
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001570 if (nrgdb != dkh.nrMS)
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001571 return (NULL);
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001572
Alexandre Julliarda11d7b11998-03-01 20:05:02 +00001573 assert((dkh.keynamelen<2) || curdata[0]);
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001574 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 Julliarda69b88b1998-03-15 20:29:56 +00001590 len = 2*(dkv.valdatalen + 1);
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001591 } 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 Julliard60ce85c1998-02-01 18:33:27 +00001608 }
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001609 return (lpxkey);
1610}
1611
Alexandre Julliardf90efa91998-06-14 15:24:15 +00001612/******************************************************************************
1613 * _w95_walkrgkn [Internal]
1614 */
1615static void _w95_walkrgkn( LPKEYSTRUCT prevkey, char *off,
1616 struct _w95_info *info )
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001617
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 Julliardf90efa91998-06-14 15:24:15 +00001662
1663/******************************************************************************
1664 * _w95_loadreg [Internal]
1665 */
1666static void _w95_loadreg( char* fn, LPKEYSTRUCT lpkey )
1667{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001668 HFILE hfd;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001669 char magic[5];
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001670 unsigned long where,version,rgdbsection,end;
1671 struct _w95_info info;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001672 OFSTRUCT ofs;
Alexandre Julliard8bbf8181996-09-13 16:50:47 +00001673 BY_HANDLE_FILE_INFORMATION hfdinfo;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001674
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001675 TRACE_(reg)("Loading Win95 registry database '%s'\n",fn);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001676 hfd=OpenFile(fn,&ofs,OF_READ);
1677 if (hfd==HFILE_ERROR)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001678 return;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001679 magic[4]=0;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001680 if (4!=_lread(hfd,magic,4))
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001681 return;
1682 if (strcmp(magic,"CREG")) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001683 WARN_(reg)("%s is not a w95 registry.\n",fn);
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001684 return;
1685 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00001686 if (4!=_lread(hfd,&version,4))
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001687 return;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001688 if (4!=_lread(hfd,&rgdbsection,4))
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001689 return;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001690 if (-1==_llseek(hfd,0x20,SEEK_SET))
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001691 return;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001692 if (4!=_lread(hfd,magic,4))
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001693 return;
1694 if (strcmp(magic,"RGKN")) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001695 WARN_(reg)("second IFF header not RGKN, but %s\n", magic);
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001696 return;
1697 }
1698
1699 /* STEP 1: Keylink structures */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001700 if (-1==_llseek(hfd,0x40,SEEK_SET))
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001701 return;
1702 where = 0x40;
1703 end = rgdbsection;
1704
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001705 info.rgknsize = end - where;
1706 info.rgknbuffer = (char*)xmalloc(info.rgknsize);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001707 if (info.rgknsize != _lread(hfd,info.rgknbuffer,info.rgknsize))
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001708 return;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001709
Alexandre Julliard8bbf8181996-09-13 16:50:47 +00001710 if (!GetFileInformationByHandle(hfd,&hfdinfo))
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001711 return;
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001712
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001713 end = hfdinfo.nFileSizeLow;
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001714 info.lastmodified = DOSFS_FileTimeToUnixTime(&hfdinfo.ftLastWriteTime,NULL);
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001715
Alexandre Julliarda3960291999-02-26 11:11:13 +00001716 if (-1==_llseek(hfd,rgdbsection,SEEK_SET))
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001717 return;
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001718
1719 info.rgdbbuffer = (char*)xmalloc(end-rgdbsection);
1720 info.rgdbsize = end - rgdbsection;
1721
Alexandre Julliarda3960291999-02-26 11:11:13 +00001722 if (info.rgdbsize !=_lread(hfd,info.rgdbbuffer,info.rgdbsize))
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001723 return;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001724 _lclose(hfd);
Alexandre Julliard02e90081998-01-04 17:49:09 +00001725
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001726 _w95_walkrgkn(lpkey, NULL, &info);
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001727
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001728 free (info.rgdbbuffer);
1729 free (info.rgknbuffer);
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001730}
1731
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001732
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001733/* 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 */
1773struct _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 */
1785struct _w31_tabent {
1786 unsigned short w0, w1, w2, w3;
1787};
1788
1789/* directory tabent: */
1790struct _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: */
1798struct _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: */
1806struct _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 */
1814void
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 Julliard7ebe1a41996-12-22 18:27:48 +00001826 LPKEYSTRUCT xlpkey = NULL;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001827 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 Julliarda3960291999-02-26 11:11:13 +00001841 if (!level && !lstrcmpA(tail,".classes")) {
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001842 __w31_dumptree(dir->child_idx,txt,tab,head,lpkey,lastmodified,level+1);
1843 idx=dir->sibling_idx;
1844 continue;
1845 }
Alexandre Julliarde658d821997-11-30 17:45:40 +00001846 name=strdupA2W(tail);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001847
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 Julliarde658d821997-11-30 17:45:40 +00001856 value=strdupA2W(tail);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001857 _find_or_add_value(xlpkey,NULL,REG_SZ,(LPBYTE)value,lstrlenW(value)*2+2,lastmodified);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001858 }
1859 }
1860 } else {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001861 TRACE_(reg)("strange: no directory key name, idx=%04x\n", idx);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001862 }
1863 __w31_dumptree(dir->child_idx,txt,tab,head,xlpkey,lastmodified,level+1);
1864 idx=dir->sibling_idx;
1865 }
1866}
1867
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001868
1869/******************************************************************************
1870 * _w31_loadreg [Internal]
1871 */
Juergen Schmiedebc2b771998-11-14 18:59:30 +00001872void _w31_loadreg(void) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001873 HFILE hf;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001874 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 Julliardda0cfb31996-12-01 17:17:47 +00001881 LPKEYSTRUCT lpkey;
1882
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001883 TRACE_(reg)("(void)\n");
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001884
Alexandre Julliarda3960291999-02-26 11:11:13 +00001885 hf = OpenFile("reg.dat",&ofs,OF_READ);
1886 if (hf==HFILE_ERROR)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001887 return;
1888
1889 /* read & dump header */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001890 if (sizeof(head)!=_lread(hf,&head,sizeof(head))) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001891 ERR_(reg)("reg.dat is too short.\n");
Alexandre Julliarda3960291999-02-26 11:11:13 +00001892 _lclose(hf);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001893 return;
1894 }
1895 if (memcmp(head.cookie, "SHCC3.10", sizeof(head.cookie))!=0) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001896 ERR_(reg)("reg.dat has bad signature.\n");
Alexandre Julliarda3960291999-02-26 11:11:13 +00001897 _lclose(hf);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001898 return;
1899 }
1900
1901 len = head.tabcnt * sizeof(struct _w31_tabent);
1902 /* read and dump index table */
1903 tab = xmalloc(len);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001904 if (len!=_lread(hf,tab,len)) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001905 ERR_(reg)("couldn't read %d bytes.\n",len);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001906 free(tab);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001907 _lclose(hf);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001908 return;
1909 }
1910
1911 /* read text */
1912 txt = xmalloc(head.textsize);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001913 if (-1==_llseek(hf,head.textoff,SEEK_SET)) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001914 ERR_(reg)("couldn't seek to textblock.\n");
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001915 free(tab);
1916 free(txt);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001917 _lclose(hf);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001918 return;
1919 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00001920 if (head.textsize!=_lread(hf,txt,head.textsize)) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001921 ERR_(reg)("textblock too short (%d instead of %ld).\n",len,head.textsize);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001922 free(tab);
1923 free(txt);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001924 _lclose(hf);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001925 return;
1926 }
1927
1928 if (!GetFileInformationByHandle(hf,&hfinfo)) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001929 ERR_(reg)("GetFileInformationByHandle failed?.\n");
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001930 free(tab);
1931 free(txt);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001932 _lclose(hf);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001933 return;
1934 }
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001935 lastmodified = DOSFS_FileTimeToUnixTime(&hfinfo.ftLastWriteTime,NULL);
Alexandre Julliarda845b881998-06-01 10:44:35 +00001936 lpkey = lookup_hkey(HKEY_CLASSES_ROOT);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001937 __w31_dumptree(tab[0].w1,txt,tab,&head,lpkey,lastmodified,0);
1938 free(tab);
1939 free(txt);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001940 _lclose(hf);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001941 return;
1942}
1943
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001944
1945/**********************************************************************************
1946 * SHELL_LoadRegistry [Internal]
1947 */
1948void SHELL_LoadRegistry( void )
1949{
Alexandre Julliard154c99b1999-04-25 12:41:36 +00001950 char *fn, *home;
Sylvain St.Germaine5332221999-04-10 16:46:15 +00001951 LPKEYSTRUCT lpkey, HKCU, HKU, HKLM;
1952 HKEY hkey;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001953
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001954 TRACE_(reg)("(void)\n");
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001955
Sylvain St.Germaine5332221999-04-10 16:46:15 +00001956 HKCU = lookup_hkey(HKEY_CURRENT_USER);
1957 HKU = lookup_hkey(HKEY_USERS);
1958 HKLM = lookup_hkey(HKEY_LOCAL_MACHINE);
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001959
Nathaniel7bf36ad1999-10-24 19:35:47 +00001960 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 Julliarde2bfa4c1996-05-16 18:21:06 +00001969
Nathaniel7bf36ad1999-10-24 19:35:47 +00001970 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 Julliarde2bfa4c1996-05-16 18:21:06 +00001976
Nathaniel7bf36ad1999-10-24 19:35:47 +00001977 /*
1978 * Load the global machine defaults directly form sysconfdir
1979 */
1980 _wine_loadreg( HKLM, SAVE_LOCAL_MACHINE_DEFAULT, 0);
1981 }
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001982
Sylvain St.Germaine5332221999-04-10 16:46:15 +00001983 /*
1984 * Load the user saved registries
1985 */
Nathaniel7bf36ad1999-10-24 19:35:47 +00001986 if (!(home = getenv( "HOME" )))
1987 WARN_(reg)("Failed to get homedirectory of UID %ld.\n",(long) getuid());
Marcus Meissner31b9dab1999-10-24 22:08:33 +00001988 else if (PROFILE_GetWineIniBool("registry", "LoadHomeRegistryFiles", 1))
Sylvain St.Germaine5332221999-04-10 16:46:15 +00001989 {
Nathaniel7bf36ad1999-10-24 19:35:47 +00001990 /*
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 Zorichbd3771c1999-03-14 15:12:48 +00001999
Nathaniel7bf36ad1999-10-24 19:35:47 +00002000 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 Zorichbd3771c1999-03-14 15:12:48 +00002005
Nathaniel7bf36ad1999-10-24 19:35:47 +00002006 /*
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.Germaine5332221999-04-10 16:46:15 +00002015 }
Nathaniel7bf36ad1999-10-24 19:35:47 +00002016
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.Germaine5332221999-04-10 16:46:15 +00002022 {
Nathaniel7bf36ad1999-10-24 19:35:47 +00002023 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.Germaine5332221999-04-10 16:46:15 +00002054 /*
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);
Nathaniel7bf36ad1999-10-24 19:35:47 +00002060 if(!lpkey){
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002061 WARN_(reg)("Could not create global user default key\n");
Nathaniel7bf36ad1999-10-24 19:35:47 +00002062 } else {
Sylvain St.Germaine5332221999-04-10 16:46:15 +00002063 _copy_registry(lpkey, HKCU );
Nathaniel7bf36ad1999-10-24 19:35:47 +00002064 }
Sylvain St.Germaine5332221999-04-10 16:46:15 +00002065
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 */
Nathaniel7bf36ad1999-10-24 19:35:47 +00002079 if (home && PROFILE_GetWineIniBool ("registry","LoadHomeRegistryFiles",1))
Alexandre Julliard154c99b1999-04-25 12:41:36 +00002080 {
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.Germaine5332221999-04-10 16:46:15 +00002086
Alexandre Julliard154c99b1999-04-25 12:41:36 +00002087 _wine_loadreg( HKU, fn, REG_OPTION_TAINTED);
Sylvain St.Germaine5332221999-04-10 16:46:15 +00002088
Alexandre Julliard154c99b1999-04-25 12:41:36 +00002089 free(fn);
2090 }
Sylvain St.Germaine5332221999-04-10 16:46:15 +00002091
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 Julliardc981d0b1996-03-31 16:40:13 +00002114}
2115
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002116
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00002117/********************* API FUNCTIONS ***************************************/
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002118/*
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00002119 * Open Keys.
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002120 *
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00002121 * All functions are stubs to RegOpenKeyEx32W where all the
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002122 * magic happens.
2123 *
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002124 * Callpath:
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00002125 * RegOpenKey16 -> RegOpenKey32A -> RegOpenKeyEx32A \
2126 * RegOpenKey32W -> RegOpenKeyEx32W
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002127 */
2128
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002129
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 Julliarda3960291999-02-26 11:11:13 +00002147DWORD WINAPI RegOpenKeyExW( HKEY hkey, LPCWSTR lpszSubKey, DWORD dwReserved,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002148 REGSAM samDesired, LPHKEY retkey )
2149{
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002150 LPKEYSTRUCT lpNextKey,lpxkey;
2151 LPWSTR *wps;
2152 int wpc,i;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002153
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002154 TRACE_(reg)("(0x%x,%s,%ld,%lx,%p)\n", hkey,debugstr_w(lpszSubKey),dwReserved,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002155 samDesired,retkey);
2156
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002157 lpNextKey = lookup_hkey( hkey );
2158 if (!lpNextKey)
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002159 return ERROR_INVALID_HANDLE;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002160
2161 if (!lpszSubKey || !*lpszSubKey) {
2162 /* Either NULL or pointer to empty string, so return a new handle
2163 to the original hkey */
Alexandre Julliard85ed45e1998-08-22 19:03:56 +00002164 currenthandle += 2;
2165 add_handle(currenthandle,lpNextKey,samDesired);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002166 *retkey=currenthandle;
2167 return ERROR_SUCCESS;
2168 }
2169
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002170 if (lpszSubKey[0] == '\\') {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002171 WARN_(reg)("Subkey %s must not begin with backslash.\n",debugstr_w(lpszSubKey));
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002172 return ERROR_BAD_PATHNAME;
2173 }
2174
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002175 split_keypath(lpszSubKey,&wps,&wpc);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002176 i = 0;
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00002177 while ((i<wpc) && (wps[i][0]=='\0')) i++;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002178 lpxkey = lpNextKey;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002179
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002180 while (wps[i]) {
2181 lpxkey=lpNextKey->nextsub;
2182 while (lpxkey) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002183 if (!lstrcmpiW(wps[i],lpxkey->keyname)) {
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002184 break;
2185 }
2186 lpxkey=lpxkey->next;
2187 }
2188
2189 if (!lpxkey) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002190 TRACE_(reg)("Could not find subkey %s\n",debugstr_w(wps[i]));
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002191 FREE_KEY_PATH;
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002192 return ERROR_FILE_NOT_FOUND;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002193 }
2194 i++;
2195 lpNextKey = lpxkey;
2196 }
2197
Alexandre Julliard85ed45e1998-08-22 19:03:56 +00002198 currenthandle += 2;
2199 add_handle(currenthandle,lpxkey,samDesired);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002200 *retkey = currenthandle;
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002201 TRACE_(reg)(" Returning %x\n", currenthandle);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002202 FREE_KEY_PATH;
2203 return ERROR_SUCCESS;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002204}
2205
2206
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002207/******************************************************************************
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002208 * RegOpenKeyEx32A [ADVAPI32.149]
2209 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002210DWORD WINAPI RegOpenKeyExA( HKEY hkey, LPCSTR lpszSubKey, DWORD dwReserved,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002211 REGSAM samDesired, LPHKEY retkey )
2212{
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002213 LPWSTR lpszSubKeyW = strdupA2W(lpszSubKey);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002214 DWORD ret;
2215
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002216 TRACE_(reg)("(%x,%s,%ld,%lx,%p)\n",hkey,debugstr_a(lpszSubKey),dwReserved,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002217 samDesired,retkey);
Alexandre Julliarda3960291999-02-26 11:11:13 +00002218 ret = RegOpenKeyExW( hkey, lpszSubKeyW, dwReserved, samDesired, retkey );
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002219 free(lpszSubKeyW);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002220 return ret;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002221}
2222
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002223
2224/******************************************************************************
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002225 * 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 Julliarda3960291999-02-26 11:11:13 +00002236DWORD WINAPI RegOpenKeyW( HKEY hkey, LPCWSTR lpszSubKey, LPHKEY retkey )
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002237{
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002238 TRACE_(reg)("(%x,%s,%p)\n",hkey,debugstr_w(lpszSubKey),retkey);
Alexandre Julliarda3960291999-02-26 11:11:13 +00002239 return RegOpenKeyExW( hkey, lpszSubKey, 0, KEY_ALL_ACCESS, retkey );
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002240}
2241
2242
2243/******************************************************************************
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002244 * RegOpenKey32A [ADVAPI32.148]
2245 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002246DWORD WINAPI RegOpenKeyA( HKEY hkey, LPCSTR lpszSubKey, LPHKEY retkey )
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002247{
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002248 DWORD ret;
2249 LPWSTR lpszSubKeyW = strdupA2W(lpszSubKey);
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002250 TRACE_(reg)("(%x,%s,%p)\n",hkey,debugstr_a(lpszSubKey),retkey);
Alexandre Julliarda3960291999-02-26 11:11:13 +00002251 ret = RegOpenKeyW( hkey, lpszSubKeyW, retkey );
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002252 free(lpszSubKeyW);
2253 return ret;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002254}
2255
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002256
2257/******************************************************************************
2258 * RegOpenKey16 [SHELL.1] [KERNEL.217]
2259 */
2260DWORD WINAPI RegOpenKey16( HKEY hkey, LPCSTR lpszSubKey, LPHKEY retkey )
2261{
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002262 TRACE_(reg)("(%x,%s,%p)\n",hkey,debugstr_a(lpszSubKey),retkey);
Alexandre Julliarda3960291999-02-26 11:11:13 +00002263 return RegOpenKeyA( hkey, lpszSubKey, retkey );
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002264}
2265
2266
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002267/*
2268 * Create keys
2269 *
2270 * All those functions convert their respective
2271 * arguments and call RegCreateKeyExW at the end.
2272 *
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002273 * We stay away from the Ex functions as long as possible because there are
2274 * differences in the return values
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002275 *
2276 * Callpath:
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002277 * RegCreateKeyEx32A \
2278 * RegCreateKey16 -> RegCreateKey32A -> RegCreateKey32W -> RegCreateKeyEx32W
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002279 */
2280
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002281
2282/******************************************************************************
2283 * RegCreateKeyEx32W [ADVAPI32.131]
2284 *
2285 * PARAMS
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002286 * 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 Julliarddadf78f1998-05-17 17:13:43 +00002295 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002296DWORD WINAPI RegCreateKeyExW( HKEY hkey, LPCWSTR lpszSubKey,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002297 DWORD dwReserved, LPWSTR lpszClass,
2298 DWORD fdwOptions, REGSAM samDesired,
2299 LPSECURITY_ATTRIBUTES lpSecAttribs,
2300 LPHKEY retkey, LPDWORD lpDispos )
2301{
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002302 LPKEYSTRUCT *lplpPrevKey,lpNextKey,lpxkey;
2303 LPWSTR *wps;
2304 int wpc,i;
2305
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002306 TRACE_(reg)("(%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n", hkey,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002307 debugstr_w(lpszSubKey), dwReserved, debugstr_w(lpszClass),
2308 fdwOptions, samDesired, lpSecAttribs, retkey, lpDispos);
2309
2310 lpNextKey = lookup_hkey(hkey);
2311 if (!lpNextKey)
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002312 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 Julliarddadf78f1998-05-17 17:13:43 +00002330
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002331 if (!lpszSubKey || !*lpszSubKey) {
Alexandre Julliard85ed45e1998-08-22 19:03:56 +00002332 currenthandle += 2;
2333 add_handle(currenthandle,lpNextKey,samDesired);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002334 *retkey=currenthandle;
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002335 TRACE_(reg)("Returning %x\n", currenthandle);
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00002336 lpNextKey->flags|=REG_OPTION_TAINTED;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002337 return ERROR_SUCCESS;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002338 }
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002339
Alexandre Julliarda845b881998-06-01 10:44:35 +00002340 if (lpszSubKey[0] == '\\') {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002341 WARN_(reg)("Subkey %s must not begin with backslash.\n",debugstr_w(lpszSubKey));
Alexandre Julliarda845b881998-06-01 10:44:35 +00002342 return ERROR_BAD_PATHNAME;
2343 }
2344
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002345 split_keypath(lpszSubKey,&wps,&wpc);
2346 i = 0;
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00002347 while ((i<wpc) && (wps[i][0]=='\0')) i++;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002348 lpxkey = lpNextKey;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00002349 while (wps[i]) {
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002350 lpxkey=lpNextKey->nextsub;
2351 while (lpxkey) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002352 if (!lstrcmpiW(wps[i],lpxkey->keyname))
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002353 break;
2354 lpxkey=lpxkey->next;
2355 }
2356 if (!lpxkey)
2357 break;
2358 i++;
2359 lpNextKey = lpxkey;
2360 }
2361 if (lpxkey) {
Alexandre Julliard85ed45e1998-08-22 19:03:56 +00002362 currenthandle += 2;
2363 add_handle(currenthandle,lpxkey,samDesired);
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00002364 lpxkey->flags |= REG_OPTION_TAINTED;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002365 *retkey = currenthandle;
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002366 TRACE_(reg)("Returning %x\n", currenthandle);
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00002367 if (lpDispos)
2368 *lpDispos = REG_OPENED_EXISTING_KEY;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002369 FREE_KEY_PATH;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002370 return ERROR_SUCCESS;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002371 }
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002372
2373 /* Good. Now the hard part */
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00002374 while (wps[i]) {
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002375 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 Julliard06c275a1999-05-02 14:32:27 +00002384 TRACE_(reg)("Returning OUTOFMEMORY\n");
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002385 return ERROR_OUTOFMEMORY;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002386 }
2387 memset(*lplpPrevKey,'\0',sizeof(KEYSTRUCT));
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002388 TRACE_(reg)("Adding %s\n", debugstr_w(wps[i]));
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002389 (*lplpPrevKey)->keyname = strdupW(wps[i]);
2390 (*lplpPrevKey)->next = NULL;
2391 (*lplpPrevKey)->nextsub = NULL;
2392 (*lplpPrevKey)->values = NULL;
2393 (*lplpPrevKey)->nrofvalues = 0;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00002394 (*lplpPrevKey)->flags = REG_OPTION_TAINTED;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002395 if (lpszClass)
2396 (*lplpPrevKey)->class = strdupW(lpszClass);
2397 else
2398 (*lplpPrevKey)->class = NULL;
2399 lpNextKey = *lplpPrevKey;
2400 i++;
2401 }
Alexandre Julliard85ed45e1998-08-22 19:03:56 +00002402 currenthandle += 2;
2403 add_handle(currenthandle,lpNextKey,samDesired);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002404
2405 /*FIXME: flag handling correct? */
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00002406 lpNextKey->flags= fdwOptions |REG_OPTION_TAINTED;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002407 if (lpszClass)
2408 lpNextKey->class = strdupW(lpszClass);
2409 else
2410 lpNextKey->class = NULL;
2411 *retkey = currenthandle;
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002412 TRACE_(reg)("Returning %x\n", currenthandle);
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00002413 if (lpDispos)
2414 *lpDispos = REG_CREATED_NEW_KEY;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002415 FREE_KEY_PATH;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002416 return ERROR_SUCCESS;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002417}
2418
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002419
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002420/******************************************************************************
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002421 * RegCreateKeyEx32A [ADVAPI32.130]
2422 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002423DWORD WINAPI RegCreateKeyExA( HKEY hkey, LPCSTR lpszSubKey, DWORD dwReserved,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002424 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 Julliard06c275a1999-05-02 14:32:27 +00002432 TRACE_(reg)("(%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n",hkey,debugstr_a(lpszSubKey),
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002433 dwReserved,debugstr_a(lpszClass),fdwOptions,samDesired,lpSecAttribs,
2434 retkey,lpDispos);
2435
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002436 lpszSubKeyW = lpszSubKey?strdupA2W(lpszSubKey):NULL;
2437 lpszClassW = lpszClass?strdupA2W(lpszClass):NULL;
2438
Alexandre Julliarda3960291999-02-26 11:11:13 +00002439 ret = RegCreateKeyExW( hkey, lpszSubKeyW, dwReserved, lpszClassW,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002440 fdwOptions, samDesired, lpSecAttribs, retkey,
2441 lpDispos );
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002442
2443 if(lpszSubKeyW) free(lpszSubKeyW);
2444 if(lpszClassW) free(lpszClassW);
2445
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002446 return ret;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002447}
2448
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002449
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002450/******************************************************************************
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002451 * RegCreateKey32W [ADVAPI32.132]
2452 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002453DWORD WINAPI RegCreateKeyW( HKEY hkey, LPCWSTR lpszSubKey, LPHKEY retkey )
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002454{
2455 DWORD junk;
2456 LPKEYSTRUCT lpNextKey;
2457
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002458 TRACE_(reg)("(%x,%s,%p)\n", hkey,debugstr_w(lpszSubKey),retkey);
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002459
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 Julliarda3960291999-02-26 11:11:13 +00002466 return RegCreateKeyExW( hkey, lpszSubKey, 0, NULL,
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002467 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
2468 retkey, &junk);
2469}
2470
2471
2472/******************************************************************************
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002473 * RegCreateKey32A [ADVAPI32.129]
2474 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002475DWORD WINAPI RegCreateKeyA( HKEY hkey, LPCSTR lpszSubKey, LPHKEY retkey )
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002476{
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002477 DWORD ret;
2478 LPWSTR lpszSubKeyW;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002479
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002480 TRACE_(reg)("(%x,%s,%p)\n",hkey,debugstr_a(lpszSubKey),retkey);
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002481 lpszSubKeyW = lpszSubKey?strdupA2W(lpszSubKey):NULL;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002482 ret = RegCreateKeyW( hkey, lpszSubKeyW, retkey );
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002483 if(lpszSubKeyW) free(lpszSubKeyW);
2484 return ret;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002485}
2486
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002487
2488/******************************************************************************
2489 * RegCreateKey16 [SHELL.2] [KERNEL.218]
2490 */
2491DWORD WINAPI RegCreateKey16( HKEY hkey, LPCSTR lpszSubKey, LPHKEY retkey )
2492{
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002493 TRACE_(reg)("(%x,%s,%p)\n",hkey,debugstr_a(lpszSubKey),retkey);
Alexandre Julliarda3960291999-02-26 11:11:13 +00002494 return RegCreateKeyA( hkey, lpszSubKey, retkey );
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002495}
2496
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002497
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002498/*
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 Julliarde2bfa4c1996-05-16 18:21:06 +00002506 * RegQueryValue16 -> RegQueryValue32A -> RegQueryValueEx32A \
Alexandre Julliard642d3131998-07-12 19:29:36 +00002507 * RegQueryValue32W -> RegQueryValueEx32W
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002508 */
2509
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002510
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 Schmiedf74fa4e1999-01-31 09:19:46 +00002527 * 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 Julliarddadf78f1998-05-17 17:13:43 +00002529 */
Huw D M Daviesdf088c61999-07-10 11:41:24 +00002530DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR lpValueName,
2531 LPDWORD lpdwReserved, LPDWORD lpdwType,
2532 LPBYTE lpbData, LPDWORD lpcbData )
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002533{
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002534 LPKEYSTRUCT lpkey;
2535 int i;
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002536 DWORD ret;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002537
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002538 TRACE_(reg)("(0x%x,%s,%p,%p,%p,%p=%ld)\n", hkey, debugstr_w(lpValueName),
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002539 lpdwReserved, lpdwType, lpbData, lpcbData, lpcbData?*lpcbData:0);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002540
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002541 lpkey = lookup_hkey(hkey);
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002542
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002543 if (!lpkey)
2544 return ERROR_INVALID_HANDLE;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002545
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002546 if ((lpbData && ! lpcbData) || lpdwReserved)
2547 return ERROR_INVALID_PARAMETER;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002548
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002549 /* 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 Julliarda3960291999-02-26 11:11:13 +00002562 if ( lpkey->values[i].name && !lstrcmpiW(lpValueName,lpkey->values[i].name))
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002563 break;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002564 }
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002565
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002566 if (i==lpkey->nrofvalues)
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002567 { TRACE_(reg)(" Key not found\n");
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002568 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 Julliard06c275a1999-05-02 14:32:27 +00002576 TRACE_(reg)(" Returning an empty string\n");
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002577 return ERROR_SUCCESS;
2578 }
2579 return ERROR_FILE_NOT_FOUND;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002580 }
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002581
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002582 ret = ERROR_SUCCESS;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002583
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002584 if (lpdwType) /* type required ?*/
2585 *lpdwType = lpkey->values[i].type;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002586
Juergen Schmiedf74fa4e1999-01-31 09:19:46 +00002587 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 Meissnerfe9bdf91999-07-15 14:33:17 +00002590 else {
2591 *lpcbData = lpkey->values[i].len;
Juergen Schmiedf74fa4e1999-01-31 09:19:46 +00002592 ret = ERROR_MORE_DATA;
Marcus Meissnerfe9bdf91999-07-15 14:33:17 +00002593 }
Juergen Schmiedf74fa4e1999-01-31 09:19:46 +00002594 }
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002595
Juergen Schmiedf74fa4e1999-01-31 09:19:46 +00002596 if (lpcbData) /* size required ?*/
2597 { *lpcbData = lpkey->values[i].len;
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002598 }
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002599
Sylvain St.Germaine5332221999-04-10 16:46:15 +00002600 debug_print_value ( lpbData, &lpkey->values[i]);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002601
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002602 TRACE_(reg)(" (ret=%lx, type=%lx, len=%ld)\n", ret, lpdwType?*lpdwType:0,lpcbData?*lpcbData:0);
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002603
2604 return ret;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002605}
2606
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002607
2608/******************************************************************************
2609 * RegQueryValue32W [ADVAPI32.159]
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002610 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002611DWORD WINAPI RegQueryValueW( HKEY hkey, LPCWSTR lpszSubKey, LPWSTR lpszData,
Alexandre Julliardb24fc081999-02-25 16:36:07 +00002612 LPLONG lpcbData )
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002613{
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002614 HKEY xhkey;
2615 DWORD ret,lpdwType;
2616
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002617 TRACE_(reg)("(%x,%s,%p,%ld)\n",hkey,debugstr_w(lpszSubKey),lpszData,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002618 lpcbData?*lpcbData:0);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002619
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002620 /* Only open subkey, if we really do descend */
2621 if (lpszSubKey && *lpszSubKey) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002622 ret = RegOpenKeyW( hkey, lpszSubKey, &xhkey );
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002623 if (ret != ERROR_SUCCESS) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002624 WARN_(reg)("Could not open %s\n", debugstr_w(lpszSubKey));
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002625 return ret;
2626 }
2627 } else
2628 xhkey = hkey;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002629
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002630 lpdwType = REG_SZ;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002631 ret = RegQueryValueExW( xhkey, NULL, NULL, &lpdwType, (LPBYTE)lpszData,
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002632 lpcbData );
2633 if (xhkey != hkey)
2634 RegCloseKey(xhkey);
2635 return ret;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002636}
2637
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002638
2639/******************************************************************************
2640 * RegQueryValueEx32A [ADVAPI32.157]
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002641 *
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 Julliarddadf78f1998-05-17 17:13:43 +00002646 */
Huw D M Daviesdf088c61999-07-10 11:41:24 +00002647DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR lpszValueName,
2648 LPDWORD lpdwReserved, LPDWORD lpdwType,
2649 LPBYTE lpbData, LPDWORD lpcbData )
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002650{
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002651 LPWSTR lpszValueNameW;
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002652 LPBYTE mybuf = NULL;
2653 DWORD ret, mytype, mylen = 0;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002654
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002655 TRACE_(reg)("(%x,%s,%p,%p,%p,%p=%ld)\n", hkey,debugstr_a(lpszValueName),
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002656 lpdwReserved,lpdwType,lpbData,lpcbData,lpcbData?*lpcbData:0);
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00002657
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002658 if (!lpcbData && lpbData) /* buffer without size is illegal */
2659 { return ERROR_INVALID_PARAMETER;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002660 }
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002661
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002662 lpszValueNameW = lpszValueName ? strdupA2W(lpszValueName) : NULL;
2663
2664 /* get just the type first */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002665 ret = RegQueryValueExW( hkey, lpszValueNameW, lpdwReserved, &mytype, NULL, NULL );
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002666
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 Schmiedf74fa4e1999-01-31 09:19:46 +00002674 { if (lpbData ) /* value requested? */
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002675 { mylen = 2*( *lpcbData );
2676 mybuf = (LPBYTE)xmalloc( mylen );
2677 }
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002678
Alexandre Julliarda3960291999-02-26 11:11:13 +00002679 ret = RegQueryValueExW( hkey, lpszValueNameW, lpdwReserved, lpdwType, mybuf, &mylen );
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002680
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002681 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 Julliarda3960291999-02-26 11:11:13 +00002690 { ret = RegQueryValueExW( hkey, lpszValueNameW, lpdwReserved, lpdwType, lpbData, lpcbData );
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002691 }
2692 }
2693
2694 if (lpdwType) /* type when requested */
2695 { *lpdwType = mytype;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002696 }
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002697
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002698 TRACE_(reg)(" (ret=%lx,type=%lx, len=%ld)\n", ret,mytype,lpcbData?*lpcbData:0);
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002699
2700 if(mybuf) free(mybuf);
2701 if(lpszValueNameW) free(lpszValueNameW);
2702 return ret;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002703}
2704
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00002705
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002706/******************************************************************************
2707 * RegQueryValueEx16 [KERNEL.225]
2708 */
2709DWORD WINAPI RegQueryValueEx16( HKEY hkey, LPSTR lpszValueName,
2710 LPDWORD lpdwReserved, LPDWORD lpdwType,
2711 LPBYTE lpbData, LPDWORD lpcbData )
2712{
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002713 TRACE_(reg)("(%x,%s,%p,%p,%p,%ld)\n",hkey,debugstr_a(lpszValueName),
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002714 lpdwReserved,lpdwType,lpbData,lpcbData?*lpcbData:0);
Alexandre Julliarda3960291999-02-26 11:11:13 +00002715 return RegQueryValueExA( hkey, lpszValueName, lpdwReserved, lpdwType,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002716 lpbData, lpcbData );
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002717}
2718
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002719
2720/******************************************************************************
2721 * RegQueryValue32A [ADVAPI32.156]
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002722 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002723DWORD WINAPI RegQueryValueA( HKEY hkey, LPCSTR lpszSubKey, LPSTR lpszData,
Alexandre Julliardb24fc081999-02-25 16:36:07 +00002724 LPLONG lpcbData )
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002725{
2726 HKEY xhkey;
2727 DWORD ret, dwType;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002728
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002729 TRACE_(reg)("(%x,%s,%p,%ld)\n",hkey,debugstr_a(lpszSubKey),lpszData,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002730 lpcbData?*lpcbData:0);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002731
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002732 if (lpszSubKey && *lpszSubKey) {
2733 ret = RegOpenKey16( hkey, lpszSubKey, &xhkey );
2734 if( ret != ERROR_SUCCESS )
2735 return ret;
2736 } else
2737 xhkey = hkey;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002738
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002739 dwType = REG_SZ;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002740 ret = RegQueryValueExA( xhkey, NULL,NULL, &dwType, (LPBYTE)lpszData,
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002741 lpcbData );
2742 if( xhkey != hkey )
2743 RegCloseKey( xhkey );
2744 return ret;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002745}
2746
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00002747
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002748/******************************************************************************
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 */
2759DWORD WINAPI RegQueryValue16( HKEY hkey, LPSTR lpszSubKey, LPSTR lpszData,
2760 LPDWORD lpcbData )
2761{
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002762 TRACE_(reg)("(%x,%s,%p,%ld)\n",hkey,debugstr_a(lpszSubKey),lpszData,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002763 lpcbData?*lpcbData:0);
2764
2765 if (lpcbData)
2766 *lpcbData &= 0xFFFF;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002767 return RegQueryValueA(hkey,lpszSubKey,lpszData,lpcbData);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002768}
2769
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002770
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002771/*
2772 * Setting values of Registry keys
2773 *
2774 * Callpath:
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00002775 * RegSetValue16 -> RegSetValue32A -> RegSetValueEx32A \
2776 * RegSetValue32W -> RegSetValueEx32W
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002777 */
2778
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002779
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002780/******************************************************************************
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 Schmiedf74fa4e1999-01-31 09:19:46 +00002795 *
2796 * NOTES
2797 * win95 does not care about cbData for REG_SZ and finds out the len by itself (js)
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002798 */
Huw D M Daviesdf088c61999-07-10 11:41:24 +00002799DWORD WINAPI RegSetValueExW( HKEY hkey, LPCWSTR lpszValueName,
2800 DWORD dwReserved, DWORD dwType,
2801 CONST BYTE *lpbData, DWORD cbData)
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002802{
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002803 LPKEYSTRUCT lpkey;
2804 int i;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002805
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002806 TRACE_(reg)("(%x,%s,%ld,%ld,%p,%ld)\n", hkey, debugstr_w(lpszValueName),
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002807 dwReserved, dwType, lpbData, cbData);
2808
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002809 lpkey = lookup_hkey( hkey );
2810
2811 if (!lpkey)
2812 return ERROR_INVALID_HANDLE;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00002813
2814 lpkey->flags |= REG_OPTION_TAINTED;
2815
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002816 if (lpszValueName==NULL) {
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002817 /* Sets type and name for key's unnamed or default value */
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002818 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 Julliard0e270f41996-08-24 18:26:35 +00002823 if ( lpkey->values[i].name &&
Alexandre Julliarda3960291999-02-26 11:11:13 +00002824 !lstrcmpiW(lpszValueName,lpkey->values[i].name)
Alexandre Julliard0e270f41996-08-24 18:26:35 +00002825 )
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002826 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 Meissnerf4f17191998-10-17 12:10:19 +00002836 if (lpkey->values[i].name==NULL) {
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002837 if (lpszValueName)
2838 lpkey->values[i].name = strdupW(lpszValueName);
2839 else
2840 lpkey->values[i].name = NULL;
Marcus Meissnerf4f17191998-10-17 12:10:19 +00002841 }
Juergen Schmiedf74fa4e1999-01-31 09:19:46 +00002842
2843 if (dwType == REG_SZ)
Alexandre Julliarda3960291999-02-26 11:11:13 +00002844 cbData = 2 * (lstrlenW ((LPCWSTR)lpbData) + 1);
Juergen Schmiedf74fa4e1999-01-31 09:19:46 +00002845
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002846 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 Julliardcdcdede1996-04-21 14:57:41 +00002851 lpkey->values[i].lastmodified = time(NULL);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002852 memcpy(lpkey->values[i].data,lpbData,cbData);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002853 return ERROR_SUCCESS;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002854}
2855
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002856
2857/******************************************************************************
2858 * RegSetValueEx32A [ADVAPI32.169]
2859 *
Juergen Schmiedf74fa4e1999-01-31 09:19:46 +00002860 * NOTES
2861 * win95 does not care about cbData for REG_SZ and finds out the len by itself (js)
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002862 */
Huw D M Daviesdf088c61999-07-10 11:41:24 +00002863DWORD WINAPI RegSetValueExA( HKEY hkey, LPCSTR lpszValueName,
2864 DWORD dwReserved, DWORD dwType,
2865 CONST BYTE *lpbData, DWORD cbData )
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002866{
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002867 LPBYTE buf;
2868 LPWSTR lpszValueNameW;
2869 DWORD ret;
2870
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002871 if (!lpbData)
2872 return (ERROR_INVALID_PARAMETER);
2873
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002874 TRACE_(reg)("(%x,%s,%ld,%ld,%p,%ld)\n",hkey,debugstr_a(lpszValueName),
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002875 dwReserved,dwType,lpbData,cbData);
2876
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002877 if ((1<<dwType) & UNICONVMASK)
Juergen Schmiedf74fa4e1999-01-31 09:19:46 +00002878 { if (dwType == REG_SZ)
2879 cbData = strlen ((LPCSTR)lpbData)+1;
2880
2881 buf = (LPBYTE)xmalloc( cbData *2 );
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002882 lmemcpynAtoW ((LPVOID)buf, lpbData, cbData );
2883 cbData=2*cbData;
2884 }
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002885 else
Huw D M Daviesdf088c61999-07-10 11:41:24 +00002886 buf=(LPBYTE)lpbData;
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002887
2888 if (lpszValueName)
2889 lpszValueNameW = strdupA2W(lpszValueName);
2890 else
2891 lpszValueNameW = NULL;
2892
Alexandre Julliarda3960291999-02-26 11:11:13 +00002893 ret=RegSetValueExW(hkey,lpszValueNameW,dwReserved,dwType,buf,cbData);
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002894
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002895 if (lpszValueNameW)
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002896 free(lpszValueNameW);
2897
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002898 if (buf!=lpbData)
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002899 free(buf);
2900
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002901 return ret;
2902}
2903
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002904
2905/******************************************************************************
2906 * RegSetValueEx16 [KERNEL.226]
2907 */
2908DWORD WINAPI RegSetValueEx16( HKEY hkey, LPSTR lpszValueName, DWORD dwReserved,
2909 DWORD dwType, LPBYTE lpbData, DWORD cbData )
2910{
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002911 TRACE_(reg)("(%x,%s,%ld,%ld,%p,%ld)\n",hkey,debugstr_a(lpszValueName),
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002912 dwReserved,dwType,lpbData,cbData);
Alexandre Julliarda3960291999-02-26 11:11:13 +00002913 return RegSetValueExA( hkey, lpszValueName, dwReserved, dwType, lpbData,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002914 cbData );
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002915}
2916
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002917
2918/******************************************************************************
2919 * RegSetValue32W [ADVAPI32.171]
2920 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002921DWORD WINAPI RegSetValueW( HKEY hkey, LPCWSTR lpszSubKey, DWORD dwType,
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002922 LPCWSTR lpszData, DWORD cbData )
2923{
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002924 HKEY xhkey;
2925 DWORD ret;
2926
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002927 TRACE_(reg)("(%x,%s,%ld,%s,%ld)\n",
Alexandre Julliarda845b881998-06-01 10:44:35 +00002928 hkey,debugstr_w(lpszSubKey),dwType,debugstr_w(lpszData),cbData
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002929 );
2930 if (lpszSubKey && *lpszSubKey) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002931 ret=RegCreateKeyW(hkey,lpszSubKey,&xhkey);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002932 if (ret!=ERROR_SUCCESS)
2933 return ret;
2934 } else
2935 xhkey=hkey;
2936 if (dwType!=REG_SZ) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002937 TRACE_(reg)("dwType=%ld - Changing to REG_SZ\n",dwType);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002938 dwType=REG_SZ;
2939 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00002940 if (cbData!=2*lstrlenW(lpszData)+2) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002941 TRACE_(reg)("Len=%ld != strlen(%s)+1=%d!\n",
Alexandre Julliarda3960291999-02-26 11:11:13 +00002942 cbData,debugstr_w(lpszData),2*lstrlenW(lpszData)+2
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002943 );
Alexandre Julliarda3960291999-02-26 11:11:13 +00002944 cbData=2*lstrlenW(lpszData)+2;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002945 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00002946 ret=RegSetValueExW(xhkey,NULL,0,dwType,(LPBYTE)lpszData,cbData);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002947 if (hkey!=xhkey)
2948 RegCloseKey(xhkey);
2949 return ret;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002950}
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002951
2952
2953/******************************************************************************
2954 * RegSetValue32A [ADVAPI32.168]
2955 *
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002956 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002957DWORD WINAPI RegSetValueA( HKEY hkey, LPCSTR lpszSubKey, DWORD dwType,
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002958 LPCSTR lpszData, DWORD cbData )
2959{
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002960 DWORD ret;
2961 HKEY xhkey;
2962
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002963 TRACE_(reg)("(%x,%s,%ld,%s,%ld)\n",hkey,lpszSubKey,dwType,lpszData,cbData);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002964 if (lpszSubKey && *lpszSubKey) {
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00002965 ret=RegCreateKey16(hkey,lpszSubKey,&xhkey);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002966 if (ret!=ERROR_SUCCESS)
2967 return ret;
2968 } else
2969 xhkey=hkey;
2970
2971 if (dwType!=REG_SZ) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002972 TRACE_(reg)("dwType=%ld!\n",dwType);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002973 dwType=REG_SZ;
2974 }
2975 if (cbData!=strlen(lpszData)+1)
2976 cbData=strlen(lpszData)+1;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002977 ret=RegSetValueExA(xhkey,NULL,0,dwType,(LPBYTE)lpszData,cbData);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002978 if (xhkey!=hkey)
2979 RegCloseKey(xhkey);
2980 return ret;
2981}
2982
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002983
2984/******************************************************************************
2985 * RegSetValue16 [KERNEL.221] [SHELL.5]
2986 */
2987DWORD WINAPI RegSetValue16( HKEY hkey, LPCSTR lpszSubKey, DWORD dwType,
2988 LPCSTR lpszData, DWORD cbData )
2989{
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002990 TRACE_(reg)("(%x,%s,%ld,%s,%ld)\n",hkey,debugstr_a(lpszSubKey),dwType,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002991 debugstr_a(lpszData),cbData);
Alexandre Julliarda3960291999-02-26 11:11:13 +00002992 return RegSetValueA(hkey,lpszSubKey,dwType,lpszData,cbData);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002993}
2994
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002995
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002996/*
2997 * Key Enumeration
2998 *
2999 * Callpath:
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00003000 * RegEnumKey16 -> RegEnumKey32A -> RegEnumKeyEx32A \
Alexandre Julliard642d3131998-07-12 19:29:36 +00003001 * RegEnumKey32W -> RegEnumKeyEx32W
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003002 */
3003
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003004
3005/******************************************************************************
3006 * RegEnumKeyEx32W [ADVAPI32.139]
Alexandre Julliard642d3131998-07-12 19:29:36 +00003007 *
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 Julliarddadf78f1998-05-17 17:13:43 +00003017 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003018DWORD WINAPI RegEnumKeyExW( HKEY hkey, DWORD iSubkey, LPWSTR lpszName,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003019 LPDWORD lpcchName, LPDWORD lpdwReserved,
3020 LPWSTR lpszClass, LPDWORD lpcchClass,
3021 FILETIME *ft )
3022{
Huw D M Davies13d00c81999-10-31 17:40:21 +00003023 LPKEYSTRUCT lpkey,lpxkey;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003024
Huw D M Davies13d00c81999-10-31 17:40:21 +00003025 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 Julliarddadf78f1998-05-17 17:13:43 +00003028
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003029 lpkey = lookup_hkey( hkey );
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003030 if (!lpkey)
3031 return ERROR_INVALID_HANDLE;
3032
Huw D M Davies13d00c81999-10-31 17:40:21 +00003033 if (!lpcchName)
3034 return ERROR_INVALID_PARAMETER;
3035
3036 if (!lpkey->nextsub)
3037 return ERROR_NO_MORE_ITEMS;
3038 lpxkey=lpkey->nextsub;
Alexandre Julliard642d3131998-07-12 19:29:36 +00003039
3040 /* Traverse the subkeys */
Huw D M Davies13d00c81999-10-31 17:40:21 +00003041 while (iSubkey && lpxkey) {
3042 iSubkey--;
3043 lpxkey=lpxkey->next;
3044 }
Alexandre Julliard642d3131998-07-12 19:29:36 +00003045
Huw D M Davies13d00c81999-10-31 17:40:21 +00003046 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 Julliard642d3131998-07-12 19:29:36 +00003054
Huw D M Davies13d00c81999-10-31 17:40:21 +00003055 if (lpszClass) {
3056 /* FIXME: what should we write into it? */
3057 *lpszClass = 0;
3058 *lpcchClass = 2;
3059 }
3060 return ERROR_SUCCESS;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003061}
3062
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003063
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003064/******************************************************************************
Huw D M Davies13d00c81999-10-31 17:40:21 +00003065 * RegEnumKeyW [ADVAPI32.140]
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003066 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003067DWORD WINAPI RegEnumKeyW( HKEY hkey, DWORD iSubkey, LPWSTR lpszName,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003068 DWORD lpcchName )
3069{
Huw D M Davies13d00c81999-10-31 17:40:21 +00003070 DWORD ret;
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003071 TRACE_(reg)("(%x,%ld,%p,%ld)\n",hkey,iSubkey,lpszName,lpcchName);
Huw D M Davies13d00c81999-10-31 17:40:21 +00003072 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 Julliardc981d0b1996-03-31 16:40:13 +00003080}
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003081
3082
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003083/******************************************************************************
3084 * RegEnumKeyEx32A [ADVAPI32.138]
3085 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003086DWORD WINAPI RegEnumKeyExA( HKEY hkey, DWORD iSubkey, LPSTR lpszName,
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003087 LPDWORD lpcchName, LPDWORD lpdwReserved,
3088 LPSTR lpszClass, LPDWORD lpcchClass,
3089 FILETIME *ft )
3090{
Huw D M Davies13d00c81999-10-31 17:40:21 +00003091 DWORD ret;
3092 LPWSTR lpszNameW, lpszClassW;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003093
Huw D M Davies13d00c81999-10-31 17:40:21 +00003094 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 Julliardc981d0b1996-03-31 16:40:13 +00003097
Huw D M Davies13d00c81999-10-31 17:40:21 +00003098 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 Julliardc981d0b1996-03-31 16:40:13 +00003106 if (lpszClassW)
Huw D M Davies13d00c81999-10-31 17:40:21 +00003107 lstrcpyWtoA(lpszClass,lpszClassW);
3108 }
3109 if (lpszNameW)
3110 free(lpszNameW);
3111 if (lpszClassW)
3112 free(lpszClassW);
3113 return ret;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003114}
3115
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003116
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003117/******************************************************************************
Huw D M Davies13d00c81999-10-31 17:40:21 +00003118 * RegEnumKeyA [ADVAPI32.137]
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003119 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003120DWORD WINAPI RegEnumKeyA( HKEY hkey, DWORD iSubkey, LPSTR lpszName,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003121 DWORD lpcchName )
3122{
Huw D M Davies13d00c81999-10-31 17:40:21 +00003123 DWORD ret;
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003124 TRACE_(reg)("(%x,%ld,%p,%ld)\n",hkey,iSubkey,lpszName,lpcchName);
Huw D M Davies13d00c81999-10-31 17:40:21 +00003125 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 Julliardc981d0b1996-03-31 16:40:13 +00003134}
3135
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003136
3137/******************************************************************************
3138 * RegEnumKey16 [SHELL.7] [KERNEL.216]
3139 */
3140DWORD WINAPI RegEnumKey16( HKEY hkey, DWORD iSubkey, LPSTR lpszName,
3141 DWORD lpcchName )
3142{
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003143 TRACE_(reg)("(%x,%ld,%p,%ld)\n",hkey,iSubkey,lpszName,lpcchName);
Alexandre Julliarda3960291999-02-26 11:11:13 +00003144 return RegEnumKeyA( hkey, iSubkey, lpszName, lpcchName);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003145}
3146
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003147
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003148/*
3149 * Enumerate Registry Values
3150 *
3151 * Callpath:
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00003152 * RegEnumValue16 -> RegEnumValue32A -> RegEnumValue32W
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003153 */
3154
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003155
3156/******************************************************************************
3157 * RegEnumValue32W [ADVAPI32.142]
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003158 *
3159 * PARAMS
Alexandre Julliard642d3131998-07-12 19:29:36 +00003160 * hkey [I] Handle to key to query
3161 * iValue [I] Index of value to query
3162 * lpszValue [O] Value string
Juergen Schmiedf74fa4e1999-01-31 09:19:46 +00003163 * lpcchValue [I/O] Size of value buffer (in wchars)
Alexandre Julliard642d3131998-07-12 19:29:36 +00003164 * lpdReserved [I] Reserved
3165 * lpdwType [O] Type code
3166 * lpbData [O] Value data
Juergen Schmiedf74fa4e1999-01-31 09:19:46 +00003167 * lpcbData [I/O] Size of data buffer (in bytes)
John Richardson2bb013b1998-11-06 17:36:13 +00003168 *
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 Julliarddadf78f1998-05-17 17:13:43 +00003171 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003172DWORD WINAPI RegEnumValueW( HKEY hkey, DWORD iValue, LPWSTR lpszValue,
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003173 LPDWORD lpcchValue, LPDWORD lpdReserved,
3174 LPDWORD lpdwType, LPBYTE lpbData,
3175 LPDWORD lpcbData )
3176{
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003177 LPKEYSTRUCT lpkey;
3178 LPKEYVALUE val;
3179
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003180 TRACE_(reg)("(%x,%ld,%p,%p,%p,%p,%p,%p)\n",hkey,iValue,debugstr_w(lpszValue),
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003181 lpcchValue,lpdReserved,lpdwType,lpbData,lpcbData);
3182
Juergen Schmiedf74fa4e1999-01-31 09:19:46 +00003183 lpkey = lookup_hkey( hkey );
3184
3185 if (!lpcbData && lpbData)
3186 return ERROR_INVALID_PARAMETER;
3187
3188 if (!lpkey)
3189 return ERROR_INVALID_HANDLE;
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003190
Juergen Schmiedf74fa4e1999-01-31 09:19:46 +00003191 if (lpkey->nrofvalues <= iValue)
3192 return ERROR_NO_MORE_ITEMS;
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003193
Juergen Schmiedf74fa4e1999-01-31 09:19:46 +00003194 val = &(lpkey->values[iValue]);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003195
3196 if (val->name) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00003197 if (lstrlenW(val->name)+1>*lpcchValue) {
3198 *lpcchValue = lstrlenW(val->name)+1;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003199 return ERROR_MORE_DATA;
3200 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00003201 memcpy(lpszValue,val->name,2 * (lstrlenW(val->name)+1) );
3202 *lpcchValue=lstrlenW(val->name);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003203 } else {
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003204 *lpszValue = 0;
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00003205 *lpcchValue = 0;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003206 }
Alexandre Julliard642d3131998-07-12 19:29:36 +00003207
Juergen Schmiedf74fa4e1999-01-31 09:19:46 +00003208 /* Can be NULL if the type code is not required */
3209 if (lpdwType)
3210 *lpdwType = val->type;
Alexandre Julliard642d3131998-07-12 19:29:36 +00003211
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003212 if (lpbData) {
Marcus Meissnerfe9bdf91999-07-15 14:33:17 +00003213 if (val->len>*lpcbData) {
3214 *lpcbData = val->len;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003215 return ERROR_MORE_DATA;
Marcus Meissnerfe9bdf91999-07-15 14:33:17 +00003216 }
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003217 memcpy(lpbData,val->data,val->len);
3218 *lpcbData = val->len;
3219 }
Juergen Schmiedf74fa4e1999-01-31 09:19:46 +00003220
Sylvain St.Germaine5332221999-04-10 16:46:15 +00003221 debug_print_value ( val->data, val );
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003222 return ERROR_SUCCESS;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003223}
3224
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003225
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003226/******************************************************************************
3227 * RegEnumValue32A [ADVAPI32.141]
3228 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003229DWORD WINAPI RegEnumValueA( HKEY hkey, DWORD iValue, LPSTR lpszValue,
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003230 LPDWORD lpcchValue, LPDWORD lpdReserved,
3231 LPDWORD lpdwType, LPBYTE lpbData,
3232 LPDWORD lpcbData )
3233{
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003234 LPWSTR lpszValueW;
3235 LPBYTE lpbDataW;
3236 DWORD ret,lpcbDataW;
Alexandre Julliard642d3131998-07-12 19:29:36 +00003237 DWORD dwType;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003238
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003239 TRACE_(reg)("(%x,%ld,%p,%p,%p,%p,%p,%p)\n",hkey,iValue,lpszValue,lpcchValue,
Alexandre Julliard642d3131998-07-12 19:29:36 +00003240 lpdReserved,lpdwType,lpbData,lpcbData);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003241
3242 lpszValueW = (LPWSTR)xmalloc(*lpcchValue*2);
3243 if (lpbData) {
3244 lpbDataW = (LPBYTE)xmalloc(*lpcbData*2);
Uwe Bonnes87763441998-11-08 14:22:31 +00003245 lpcbDataW = *lpcbData;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003246 } else
3247 lpbDataW = NULL;
Alexandre Julliard642d3131998-07-12 19:29:36 +00003248
Alexandre Julliarda3960291999-02-26 11:11:13 +00003249 ret = RegEnumValueW( hkey, iValue, lpszValueW, lpcchValue,
Alexandre Julliard642d3131998-07-12 19:29:36 +00003250 lpdReserved, &dwType, lpbDataW, &lpcbDataW );
3251
3252 if (lpdwType)
3253 *lpdwType = dwType;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003254
3255 if (ret==ERROR_SUCCESS) {
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00003256 lstrcpyWtoA(lpszValue,lpszValueW);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003257 if (lpbData) {
Alexandre Julliard642d3131998-07-12 19:29:36 +00003258 if ((1<<dwType) & UNICONVMASK) {
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00003259 lstrcpyWtoA(lpbData,(LPWSTR)lpbDataW);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003260 } else {
Marcus Meissnerfe9bdf91999-07-15 14:33:17 +00003261 if (lpcbDataW > *lpcbData) {
3262 *lpcbData = lpcbDataW;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003263 ret = ERROR_MORE_DATA;
Marcus Meissnerfe9bdf91999-07-15 14:33:17 +00003264 } else
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003265 memcpy(lpbData,lpbDataW,lpcbDataW);
3266 }
3267 *lpcbData = lpcbDataW;
3268 }
3269 }
Alexandre Julliard642d3131998-07-12 19:29:36 +00003270 if (lpbDataW) free(lpbDataW);
3271 if (lpszValueW) free(lpszValueW);
3272 return ret;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003273}
3274
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003275
3276/******************************************************************************
3277 * RegEnumValue16 [KERNEL.223]
3278 */
3279DWORD WINAPI RegEnumValue16( HKEY hkey, DWORD iValue, LPSTR lpszValue,
3280 LPDWORD lpcchValue, LPDWORD lpdReserved,
3281 LPDWORD lpdwType, LPBYTE lpbData,
3282 LPDWORD lpcbData )
3283{
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003284 TRACE_(reg)("(%x,%ld,%p,%p,%p,%p,%p,%p)\n",hkey,iValue,lpszValue,lpcchValue,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003285 lpdReserved,lpdwType,lpbData,lpcbData);
Alexandre Julliarda3960291999-02-26 11:11:13 +00003286 return RegEnumValueA( hkey, iValue, lpszValue, lpcchValue, lpdReserved,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003287 lpdwType, lpbData, lpcbData );
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003288}
3289
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003290
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 Julliardc981d0b1996-03-31 16:40:13 +00003301 */
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003302DWORD WINAPI RegCloseKey( HKEY hkey )
3303{
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003304 TRACE_(reg)("(%x)\n",hkey);
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003305
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 Julliarddadf78f1998-05-17 17:13:43 +00003311 return remove_handle(hkey);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003312}
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003313
3314
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003315/*
3316 * Delete registry key
3317 *
3318 * Callpath:
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00003319 * RegDeleteKey16 -> RegDeleteKey32A -> RegDeleteKey32W
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003320 */
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003321
3322
3323/******************************************************************************
3324 * RegDeleteKey32W [ADVAPI32.134]
3325 *
3326 * PARAMS
Alexandre Julliard642d3131998-07-12 19:29:36 +00003327 * hkey [I] Handle to open key
3328 * lpszSubKey [I] Name of subkey to delete
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003329 *
3330 * RETURNS
3331 * Success: ERROR_SUCCESS
3332 * Failure: Error code
3333 */
Huw D M Daviesdf088c61999-07-10 11:41:24 +00003334DWORD WINAPI RegDeleteKeyW( HKEY hkey, LPCWSTR lpszSubKey )
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003335{
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003336 LPKEYSTRUCT *lplpPrevKey,lpNextKey,lpxkey;
3337 LPWSTR *wps;
3338 int wpc,i;
3339
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003340 TRACE_(reg)("(%x,%s)\n",hkey,debugstr_w(lpszSubKey));
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003341
3342 lpNextKey = lookup_hkey(hkey);
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003343 if (!lpNextKey)
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003344 return ERROR_INVALID_HANDLE;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003345
Alexandre Julliard642d3131998-07-12 19:29:36 +00003346 /* Subkey param cannot be NULL */
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003347 if (!lpszSubKey || !*lpszSubKey)
3348 return ERROR_BADKEY;
3349
Alexandre Julliard642d3131998-07-12 19:29:36 +00003350 /* We need to know the previous key in the hier. */
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003351 split_keypath(lpszSubKey,&wps,&wpc);
3352 i = 0;
3353 lpxkey = lpNextKey;
3354 while (i<wpc-1) {
3355 lpxkey=lpNextKey->nextsub;
3356 while (lpxkey) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003357 TRACE_(reg)(" Scanning [%s]\n",
Alexandre Julliarda845b881998-06-01 10:44:35 +00003358 debugstr_w(lpxkey->keyname));
Alexandre Julliarda3960291999-02-26 11:11:13 +00003359 if (!lstrcmpiW(wps[i],lpxkey->keyname))
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003360 break;
3361 lpxkey=lpxkey->next;
3362 }
3363 if (!lpxkey) {
3364 FREE_KEY_PATH;
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003365 TRACE_(reg)(" Not found.\n");
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003366 /* not found is success */
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003367 return ERROR_SUCCESS;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003368 }
3369 i++;
3370 lpNextKey = lpxkey;
3371 }
3372 lpxkey = lpNextKey->nextsub;
3373 lplpPrevKey = &(lpNextKey->nextsub);
3374 while (lpxkey) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003375 TRACE_(reg)(" Scanning [%s]\n",
Alexandre Julliarda845b881998-06-01 10:44:35 +00003376 debugstr_w(lpxkey->keyname));
Alexandre Julliarda3960291999-02-26 11:11:13 +00003377 if (!lstrcmpiW(wps[i],lpxkey->keyname))
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003378 break;
3379 lplpPrevKey = &(lpxkey->next);
3380 lpxkey = lpxkey->next;
3381 }
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003382
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00003383 if (!lpxkey) {
3384 FREE_KEY_PATH;
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003385 WARN_(reg)(" Not found.\n");
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003386 return ERROR_FILE_NOT_FOUND;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00003387 }
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003388
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00003389 if (lpxkey->nextsub) {
3390 FREE_KEY_PATH;
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003391 WARN_(reg)(" Not empty.\n");
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003392 return ERROR_CANTWRITE;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00003393 }
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003394 *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 Julliard06c275a1999-05-02 14:32:27 +00003402 TRACE_(reg)(" Done.\n");
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003403 return ERROR_SUCCESS;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003404}
3405
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003406
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003407/******************************************************************************
3408 * RegDeleteKey32A [ADVAPI32.133]
3409 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003410DWORD WINAPI RegDeleteKeyA( HKEY hkey, LPCSTR lpszSubKey )
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003411{
3412 LPWSTR lpszSubKeyW;
3413 DWORD ret;
3414
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003415 TRACE_(reg)("(%x,%s)\n",hkey,debugstr_a(lpszSubKey));
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003416 lpszSubKeyW = lpszSubKey?strdupA2W(lpszSubKey):NULL;
Alexandre Julliarda3960291999-02-26 11:11:13 +00003417 ret = RegDeleteKeyW( hkey, lpszSubKeyW );
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003418 if(lpszSubKeyW) free(lpszSubKeyW);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003419 return ret;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003420}
3421
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003422
3423/******************************************************************************
3424 * RegDeleteKey16 [SHELL.4] [KERNEL.219]
3425 */
3426DWORD WINAPI RegDeleteKey16( HKEY hkey, LPCSTR lpszSubKey )
3427{
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003428 TRACE_(reg)("(%x,%s)\n",hkey,debugstr_a(lpszSubKey));
Alexandre Julliarda3960291999-02-26 11:11:13 +00003429 return RegDeleteKeyA( hkey, lpszSubKey );
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003430}
3431
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003432
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003433/*
3434 * Delete registry value
3435 *
3436 * Callpath:
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00003437 * RegDeleteValue16 -> RegDeleteValue32A -> RegDeleteValue32W
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003438 */
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003439
3440
3441/******************************************************************************
3442 * RegDeleteValue32W [ADVAPI32.136]
3443 *
3444 * PARAMS
3445 * hkey [I]
3446 * lpszValue [I]
3447 *
3448 * RETURNS
3449 */
Huw D M Daviesdf088c61999-07-10 11:41:24 +00003450DWORD WINAPI RegDeleteValueW( HKEY hkey, LPCWSTR lpszValue )
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003451{
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003452 DWORD i;
3453 LPKEYSTRUCT lpkey;
3454 LPKEYVALUE val;
3455
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003456 TRACE_(reg)("(%x,%s)\n",hkey,debugstr_w(lpszValue));
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003457
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003458 lpkey = lookup_hkey( hkey );
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003459 if (!lpkey)
3460 return ERROR_INVALID_HANDLE;
3461
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003462 if (lpszValue) {
3463 for (i=0;i<lpkey->nrofvalues;i++)
Alexandre Julliard0e270f41996-08-24 18:26:35 +00003464 if ( lpkey->values[i].name &&
Alexandre Julliarda3960291999-02-26 11:11:13 +00003465 !lstrcmpiW(lpkey->values[i].name,lpszValue)
Alexandre Julliard0e270f41996-08-24 18:26:35 +00003466 )
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003467 break;
3468 } else {
3469 for (i=0;i<lpkey->nrofvalues;i++)
3470 if (lpkey->values[i].name==NULL)
3471 break;
3472 }
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003473
3474 if (i == lpkey->nrofvalues)
3475 return ERROR_FILE_NOT_FOUND;
3476
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003477 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 Julliarddadf78f1998-05-17 17:13:43 +00003490 return ERROR_SUCCESS;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003491}
3492
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003493
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003494/******************************************************************************
3495 * RegDeleteValue32A [ADVAPI32.135]
3496 */
Huw D M Daviesdf088c61999-07-10 11:41:24 +00003497DWORD WINAPI RegDeleteValueA( HKEY hkey, LPCSTR lpszValue )
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003498{
3499 LPWSTR lpszValueW;
3500 DWORD ret;
3501
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003502 TRACE_(reg)("(%x,%s)\n",hkey,debugstr_a(lpszValue));
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003503 lpszValueW = lpszValue?strdupA2W(lpszValue):NULL;
Alexandre Julliarda3960291999-02-26 11:11:13 +00003504 ret = RegDeleteValueW( hkey, lpszValueW );
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003505 if(lpszValueW) free(lpszValueW);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003506 return ret;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003507}
3508
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003509
3510/******************************************************************************
3511 * RegDeleteValue16 [KERNEL.222]
3512 */
3513DWORD WINAPI RegDeleteValue16( HKEY hkey, LPSTR lpszValue )
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003514{
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003515 TRACE_(reg)("(%x,%s)\n", hkey,debugstr_a(lpszValue));
Alexandre Julliarda3960291999-02-26 11:11:13 +00003516 return RegDeleteValueA( hkey, lpszValue );
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003517}
3518
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00003519
3520/******************************************************************************
3521 * RegFlushKey [KERNEL.227] [ADVAPI32.143]
Andreas Mohrd4b13da1999-08-07 14:17:10 +00003522 * 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 Julliard46ea8b31998-05-03 19:01:20 +00003529 *
3530 * PARAMS
3531 * hkey [I] Handle of key to write
3532 *
3533 * RETURNS
3534 * Success: ERROR_SUCCESS
3535 * Failure: Error code
3536 */
3537DWORD WINAPI RegFlushKey( HKEY hkey )
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003538{
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003539 LPKEYSTRUCT lpkey;
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003540
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003541 TRACE_(reg)("(%x)\n", hkey);
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003542
3543 lpkey = lookup_hkey( hkey );
3544 if (!lpkey)
Andreas Mohr743885a1999-02-13 12:40:22 +00003545 return ERROR_BADKEY;
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003546
Andreas Mohrd4b13da1999-08-07 14:17:10 +00003547 SHELL_SaveRegistryBranch(find_root_key(lpkey), TRUE);
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003548 return ERROR_SUCCESS;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003549}
3550
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00003551
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003552/* FIXME: lpcchXXXX ... is this counting in WCHARS or in BYTEs ?? */
3553
Alexandre Julliard642d3131998-07-12 19:29:36 +00003554
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003555/******************************************************************************
3556 * RegQueryInfoKey32W [ADVAPI32.153]
Alexandre Julliard642d3131998-07-12 19:29:36 +00003557 *
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 Richardson2bb013b1998-11-06 17:36:13 +00003571 * - 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 Julliarddadf78f1998-05-17 17:13:43 +00003576 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003577DWORD WINAPI RegQueryInfoKeyW( HKEY hkey, LPWSTR lpszClass,
Alexandre Julliard642d3131998-07-12 19:29:36 +00003578 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 Julliardc981d0b1996-03-31 16:40:13 +00003585 LPKEYSTRUCT lpkey,lpxkey;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003586 int nrofkeys,maxsubkey,maxclass,maxvname,maxvdata;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003587 int i;
3588
Marcus Meissner450bc791999-05-09 15:59:27 +00003589 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 Julliarddadf78f1998-05-17 17:13:43 +00003594 lpkey = lookup_hkey(hkey);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003595 if (!lpkey)
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003596 return ERROR_INVALID_HANDLE;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003597 if (lpszClass) {
John Richardson2bb013b1998-11-06 17:36:13 +00003598 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 Julliardc981d0b1996-03-31 16:40:13 +00003603 if (lpkey->class) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00003604 DWORD classLen = lstrlenW(lpkey->class);
John Richardson2bb013b1998-11-06 17:36:13 +00003605
3606 if (lpcchClass && classLen+1>*lpcchClass) {
3607 *lpcchClass=classLen+1;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003608 return ERROR_MORE_DATA;
3609 }
John Richardson2bb013b1998-11-06 17:36:13 +00003610 if (lpcchClass)
3611 *lpcchClass=classLen;
3612 memcpy(lpszClass,lpkey->class, classLen*2 + 2);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003613 } else {
3614 *lpszClass = 0;
John Richardson2bb013b1998-11-06 17:36:13 +00003615 if (lpcchClass)
3616 *lpcchClass = 0;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003617 }
3618 } else {
3619 if (lpcchClass)
Alexandre Julliarda3960291999-02-26 11:11:13 +00003620 *lpcchClass = lstrlenW(lpkey->class);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003621 }
3622 lpxkey=lpkey->nextsub;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003623 nrofkeys=maxsubkey=maxclass=maxvname=maxvdata=0;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003624 while (lpxkey) {
3625 nrofkeys++;
Alexandre Julliarda3960291999-02-26 11:11:13 +00003626 if (lstrlenW(lpxkey->keyname)>maxsubkey)
3627 maxsubkey=lstrlenW(lpxkey->keyname);
3628 if (lpxkey->class && lstrlenW(lpxkey->class)>maxclass)
3629 maxclass=lstrlenW(lpxkey->class);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003630 lpxkey=lpxkey->next;
3631 }
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003632 for (i=0;i<lpkey->nrofvalues;i++) {
3633 LPKEYVALUE val=lpkey->values+i;
3634
Alexandre Julliarda3960291999-02-26 11:11:13 +00003635 if (val->name && lstrlenW(val->name)>maxvname)
3636 maxvname=lstrlenW(val->name);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003637 if (val->len>maxvdata)
3638 maxvdata=val->len;
3639 }
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003640 if (!maxclass) maxclass = 1;
3641 if (!maxvname) maxvname = 1;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003642 if (lpcValues)
3643 *lpcValues = lpkey->nrofvalues;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003644 if (lpcSubKeys)
3645 *lpcSubKeys = nrofkeys;
3646 if (lpcchMaxSubkey)
John Richardson2bb013b1998-11-06 17:36:13 +00003647 *lpcchMaxSubkey = maxsubkey;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003648 if (lpcchMaxClass)
John Richardson2bb013b1998-11-06 17:36:13 +00003649 *lpcchMaxClass = maxclass;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003650 if (lpcchMaxValueName)
3651 *lpcchMaxValueName= maxvname;
3652 if (lpccbMaxValueData)
3653 *lpccbMaxValueData= maxvdata;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003654 return ERROR_SUCCESS;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003655}
3656
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003657
Alexandre Julliard642d3131998-07-12 19:29:36 +00003658/******************************************************************************
3659 * RegQueryInfoKey32A [ADVAPI32.152]
3660 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003661DWORD WINAPI RegQueryInfoKeyA( HKEY hkey, LPSTR lpszClass, LPDWORD lpcchClass,
Alexandre Julliard642d3131998-07-12 19:29:36 +00003662 LPDWORD lpdwReserved, LPDWORD lpcSubKeys,
3663 LPDWORD lpcchMaxSubkey, LPDWORD lpcchMaxClass,
3664 LPDWORD lpcValues, LPDWORD lpcchMaxValueName,
3665 LPDWORD lpccbMaxValueData,
3666 LPDWORD lpcbSecurityDescriptor, FILETIME *ft )
3667{
John Richardson2bb013b1998-11-06 17:36:13 +00003668 LPWSTR lpszClassW = NULL;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003669 DWORD ret;
3670
Marcus Meissner450bc791999-05-09 15:59:27 +00003671 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 Julliardc981d0b1996-03-31 16:40:13 +00003676 if (lpszClass) {
John Richardson2bb013b1998-11-06 17:36:13 +00003677 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 Julliardc981d0b1996-03-31 16:40:13 +00003685
3686 } else
3687 lpszClassW = NULL;
Alexandre Julliarda3960291999-02-26 11:11:13 +00003688 ret=RegQueryInfoKeyW(
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003689 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 Julliard641ee761997-08-04 16:34:36 +00003702 if (ret==ERROR_SUCCESS && lpszClass)
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00003703 lstrcpyWtoA(lpszClass,lpszClassW);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003704 if (lpszClassW)
3705 free(lpszClassW);
3706 return ret;
3707}
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003708
3709
3710/******************************************************************************
3711 * RegConnectRegistry32W [ADVAPI32.128]
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003712 *
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 Julliarddadf78f1998-05-17 17:13:43 +00003717 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003718LONG WINAPI RegConnectRegistryW( LPCWSTR lpMachineName, HKEY hKey,
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003719 LPHKEY phkResult )
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003720{
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003721 TRACE_(reg)("(%s,%x,%p): stub\n",debugstr_w(lpMachineName),hKey,phkResult);
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003722
3723 if (!lpMachineName || !*lpMachineName) {
3724 /* Use the local machine name */
3725 return RegOpenKey16( hKey, "", phkResult );
3726 }
3727
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003728 FIXME_(reg)("Cannot connect to %s\n",debugstr_w(lpMachineName));
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003729 return ERROR_BAD_NETPATH;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003730}
3731
3732
3733/******************************************************************************
3734 * RegConnectRegistry32A [ADVAPI32.127]
3735 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003736LONG WINAPI RegConnectRegistryA( LPCSTR machine, HKEY hkey, LPHKEY reskey )
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003737{
3738 DWORD ret;
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003739 LPWSTR machineW = strdupA2W(machine);
Alexandre Julliarda3960291999-02-26 11:11:13 +00003740 ret = RegConnectRegistryW( machineW, hkey, reskey );
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003741 free(machineW);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003742 return ret;
Alexandre Julliard01d63461997-01-20 19:43:45 +00003743}
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00003744
3745
3746/******************************************************************************
3747 * RegGetKeySecurity [ADVAPI32.144]
3748 * Retrieves a copy of security descriptor protecting the registry key
3749 *
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003750 * 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 Julliard46ea8b31998-05-03 19:01:20 +00003756 * RETURNS
3757 * Success: ERROR_SUCCESS
3758 * Failure: Error code
3759 */
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003760LONG WINAPI RegGetKeySecurity( HKEY hkey,
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00003761 SECURITY_INFORMATION SecurityInformation,
Juergen Schmied1ed51af1999-02-12 17:47:07 +00003762 PSECURITY_DESCRIPTOR pSecurityDescriptor,
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00003763 LPDWORD lpcbSecurityDescriptor )
3764{
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003765 LPKEYSTRUCT lpkey;
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003766
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003767 TRACE_(reg)("(%x,%ld,%p,%ld)\n",hkey,SecurityInformation,pSecurityDescriptor,
Alexandre Julliard642d3131998-07-12 19:29:36 +00003768 lpcbSecurityDescriptor?*lpcbSecurityDescriptor:0);
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003769
3770 lpkey = lookup_hkey( hkey );
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003771 if (!lpkey)
3772 return ERROR_INVALID_HANDLE;
3773
Alexandre Julliard642d3131998-07-12 19:29:36 +00003774 /* FIXME: Check for valid SecurityInformation values */
3775
Alexandre Julliardb24fc081999-02-25 16:36:07 +00003776 if (*lpcbSecurityDescriptor < sizeof(SECURITY_DESCRIPTOR))
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003777 return ERROR_INSUFFICIENT_BUFFER;
3778
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003779 FIXME_(reg)("(%x,%ld,%p,%ld): stub\n",hkey,SecurityInformation,
Alexandre Julliard642d3131998-07-12 19:29:36 +00003780 pSecurityDescriptor,lpcbSecurityDescriptor?*lpcbSecurityDescriptor:0);
3781
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00003782 return ERROR_SUCCESS;
3783}
3784
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003785
3786/******************************************************************************
3787 * RegLoadKey32W [ADVAPI32.???]
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003788 *
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 Julliarddadf78f1998-05-17 17:13:43 +00003793 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003794LONG WINAPI RegLoadKeyW( HKEY hkey, LPCWSTR lpszSubKey, LPCWSTR lpszFile )
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003795{
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003796 LPKEYSTRUCT lpkey;
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003797 TRACE_(reg)("(%x,%s,%s)\n",hkey,debugstr_w(lpszSubKey),debugstr_w(lpszFile));
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003798
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 Julliard06c275a1999-05-02 14:32:27 +00003807 FIXME_(reg)("(%x,%s,%s): stub\n",hkey,debugstr_w(lpszSubKey),
Alexandre Julliard642d3131998-07-12 19:29:36 +00003808 debugstr_w(lpszFile));
3809
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003810 return ERROR_SUCCESS;
3811}
3812
3813
3814/******************************************************************************
3815 * RegLoadKey32A [ADVAPI32.???]
3816 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003817LONG WINAPI RegLoadKeyA( HKEY hkey, LPCSTR lpszSubKey, LPCSTR lpszFile )
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003818{
3819 LONG ret;
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003820 LPWSTR lpszSubKeyW = strdupA2W(lpszSubKey);
3821 LPWSTR lpszFileW = strdupA2W(lpszFile);
Alexandre Julliarda3960291999-02-26 11:11:13 +00003822 ret = RegLoadKeyW( hkey, lpszSubKeyW, lpszFileW );
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003823 if(lpszFileW) free(lpszFileW);
3824 if(lpszSubKeyW) free(lpszSubKeyW);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003825 return ret;
3826}
3827
3828
3829/******************************************************************************
3830 * RegNotifyChangeKeyValue [ADVAPI32.???]
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003831 *
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 Julliarddadf78f1998-05-17 17:13:43 +00003838 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003839LONG WINAPI RegNotifyChangeKeyValue( HKEY hkey, BOOL fWatchSubTree,
3840 DWORD fdwNotifyFilter, HANDLE hEvent,
3841 BOOL fAsync )
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003842{
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003843 LPKEYSTRUCT lpkey;
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003844 TRACE_(reg)("(%x,%i,%ld,%x,%i)\n",hkey,fWatchSubTree,fdwNotifyFilter,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003845 hEvent,fAsync);
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003846
3847 lpkey = lookup_hkey( hkey );
3848 if (!lpkey)
3849 return ERROR_INVALID_HANDLE;
3850
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003851 FIXME_(reg)("(%x,%i,%ld,%x,%i): stub\n",hkey,fWatchSubTree,fdwNotifyFilter,
Alexandre Julliard642d3131998-07-12 19:29:36 +00003852 hEvent,fAsync);
3853
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003854 return ERROR_SUCCESS;
3855}
3856
Alexandre Julliarda845b881998-06-01 10:44:35 +00003857
3858/******************************************************************************
3859 * RegUnLoadKey32W [ADVAPI32.173]
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003860 *
3861 * PARAMS
3862 * hkey [I] Handle of open key
3863 * lpSubKey [I] Address of name of subkey to unload
Alexandre Julliarda845b881998-06-01 10:44:35 +00003864 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003865LONG WINAPI RegUnLoadKeyW( HKEY hkey, LPCWSTR lpSubKey )
Alexandre Julliarda845b881998-06-01 10:44:35 +00003866{
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003867 FIXME_(reg)("(%x,%s): stub\n",hkey, debugstr_w(lpSubKey));
Alexandre Julliarda845b881998-06-01 10:44:35 +00003868 return ERROR_SUCCESS;
3869}
3870
3871
3872/******************************************************************************
3873 * RegUnLoadKey32A [ADVAPI32.172]
3874 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003875LONG WINAPI RegUnLoadKeyA( HKEY hkey, LPCSTR lpSubKey )
Alexandre Julliarda845b881998-06-01 10:44:35 +00003876{
3877 LONG ret;
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003878 LPWSTR lpSubKeyW = strdupA2W(lpSubKey);
Alexandre Julliarda3960291999-02-26 11:11:13 +00003879 ret = RegUnLoadKeyW( hkey, lpSubKeyW );
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003880 if(lpSubKeyW) free(lpSubKeyW);
Alexandre Julliarda845b881998-06-01 10:44:35 +00003881 return ret;
3882}
3883
3884
3885/******************************************************************************
3886 * RegSetKeySecurity [ADVAPI32.167]
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003887 *
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 Julliarda845b881998-06-01 10:44:35 +00003892 */
3893LONG WINAPI RegSetKeySecurity( HKEY hkey, SECURITY_INFORMATION SecurityInfo,
Juergen Schmied1ed51af1999-02-12 17:47:07 +00003894 PSECURITY_DESCRIPTOR pSecurityDesc )
Alexandre Julliarda845b881998-06-01 10:44:35 +00003895{
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003896 LPKEYSTRUCT lpkey;
3897
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003898 TRACE_(reg)("(%x,%ld,%p)\n",hkey,SecurityInfo,pSecurityDesc);
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003899
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 Julliard06c275a1999-05-02 14:32:27 +00003916 FIXME_(reg)(":(%x,%ld,%p): stub\n",hkey,SecurityInfo,pSecurityDesc);
Alexandre Julliard642d3131998-07-12 19:29:36 +00003917
Alexandre Julliarda845b881998-06-01 10:44:35 +00003918 return ERROR_SUCCESS;
3919}
3920
3921
3922/******************************************************************************
3923 * RegSaveKey32W [ADVAPI32.166]
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003924 *
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 Julliarda845b881998-06-01 10:44:35 +00003929 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003930LONG WINAPI RegSaveKeyW( HKEY hkey, LPCWSTR lpFile,
Alexandre Julliarda845b881998-06-01 10:44:35 +00003931 LPSECURITY_ATTRIBUTES sa )
3932{
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003933 LPKEYSTRUCT lpkey;
3934
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003935 TRACE_(reg)("(%x,%s,%p)\n", hkey, debugstr_w(lpFile), sa);
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003936
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 Julliard06c275a1999-05-02 14:32:27 +00003945 FIXME_(reg)("(%x,%s,%p): stub\n", hkey, debugstr_w(lpFile), sa);
Alexandre Julliard642d3131998-07-12 19:29:36 +00003946
Alexandre Julliarda845b881998-06-01 10:44:35 +00003947 return ERROR_SUCCESS;
3948}
3949
3950
3951/******************************************************************************
3952 * RegSaveKey32A [ADVAPI32.165]
3953 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003954LONG WINAPI RegSaveKeyA( HKEY hkey, LPCSTR lpFile,
Alexandre Julliarda845b881998-06-01 10:44:35 +00003955 LPSECURITY_ATTRIBUTES sa )
3956{
3957 LONG ret;
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003958 LPWSTR lpFileW = strdupA2W(lpFile);
Alexandre Julliarda3960291999-02-26 11:11:13 +00003959 ret = RegSaveKeyW( hkey, lpFileW, sa );
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003960 free(lpFileW);
Alexandre Julliarda845b881998-06-01 10:44:35 +00003961 return ret;
3962}
3963
3964
3965/******************************************************************************
3966 * RegRestoreKey32W [ADVAPI32.164]
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003967 *
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 Julliarda845b881998-06-01 10:44:35 +00003972 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003973LONG WINAPI RegRestoreKeyW( HKEY hkey, LPCWSTR lpFile, DWORD dwFlags )
Alexandre Julliarda845b881998-06-01 10:44:35 +00003974{
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003975 LPKEYSTRUCT lpkey;
Alexandre Julliard642d3131998-07-12 19:29:36 +00003976
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003977 TRACE_(reg)("(%x,%s,%ld)\n",hkey,debugstr_w(lpFile),dwFlags);
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003978
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 Julliard06c275a1999-05-02 14:32:27 +00003987 FIXME_(reg)("(%x,%s,%ld): stub\n",hkey,debugstr_w(lpFile),dwFlags);
Alexandre Julliard642d3131998-07-12 19:29:36 +00003988
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003989 /* Check for file existence */
3990
Alexandre Julliarda845b881998-06-01 10:44:35 +00003991 return ERROR_SUCCESS;
3992}
3993
3994
3995/******************************************************************************
3996 * RegRestoreKey32A [ADVAPI32.163]
3997 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003998LONG WINAPI RegRestoreKeyA( HKEY hkey, LPCSTR lpFile, DWORD dwFlags )
Alexandre Julliarda845b881998-06-01 10:44:35 +00003999{
4000 LONG ret;
Alexandre Julliardf90efa91998-06-14 15:24:15 +00004001 LPWSTR lpFileW = strdupA2W(lpFile);
Alexandre Julliarda3960291999-02-26 11:11:13 +00004002 ret = RegRestoreKeyW( hkey, lpFileW, dwFlags );
Alexandre Julliardf90efa91998-06-14 15:24:15 +00004003 if(lpFileW) free(lpFileW);
Alexandre Julliarda845b881998-06-01 10:44:35 +00004004 return ret;
4005}
4006
4007
4008/******************************************************************************
4009 * RegReplaceKey32W [ADVAPI32.162]
Alexandre Julliardf90efa91998-06-14 15:24:15 +00004010 *
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 Julliarda845b881998-06-01 10:44:35 +00004016 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004017LONG WINAPI RegReplaceKeyW( HKEY hkey, LPCWSTR lpSubKey, LPCWSTR lpNewFile,
Alexandre Julliarda845b881998-06-01 10:44:35 +00004018 LPCWSTR lpOldFile )
4019{
Alexandre Julliardf90efa91998-06-14 15:24:15 +00004020 LPKEYSTRUCT lpkey;
4021
Alexandre Julliard06c275a1999-05-02 14:32:27 +00004022 TRACE_(reg)("(%x,%s,%s,%s)\n",hkey,debugstr_w(lpSubKey),
Alexandre Julliarda845b881998-06-01 10:44:35 +00004023 debugstr_w(lpNewFile),debugstr_w(lpOldFile));
Alexandre Julliardf90efa91998-06-14 15:24:15 +00004024
4025 lpkey = lookup_hkey( hkey );
4026 if (!lpkey)
4027 return ERROR_INVALID_HANDLE;
4028
Alexandre Julliard06c275a1999-05-02 14:32:27 +00004029 FIXME_(reg)("(%x,%s,%s,%s): stub\n", hkey, debugstr_w(lpSubKey),
Alexandre Julliard642d3131998-07-12 19:29:36 +00004030 debugstr_w(lpNewFile),debugstr_w(lpOldFile));
4031
Alexandre Julliarda845b881998-06-01 10:44:35 +00004032 return ERROR_SUCCESS;
4033}
4034
4035
4036/******************************************************************************
4037 * RegReplaceKey32A [ADVAPI32.161]
4038 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00004039LONG WINAPI RegReplaceKeyA( HKEY hkey, LPCSTR lpSubKey, LPCSTR lpNewFile,
Alexandre Julliarda845b881998-06-01 10:44:35 +00004040 LPCSTR lpOldFile )
4041{
4042 LONG ret;
Alexandre Julliardf90efa91998-06-14 15:24:15 +00004043 LPWSTR lpSubKeyW = strdupA2W(lpSubKey);
4044 LPWSTR lpNewFileW = strdupA2W(lpNewFile);
4045 LPWSTR lpOldFileW = strdupA2W(lpOldFile);
Alexandre Julliarda3960291999-02-26 11:11:13 +00004046 ret = RegReplaceKeyW( hkey, lpSubKeyW, lpNewFileW, lpOldFileW );
Alexandre Julliardf90efa91998-06-14 15:24:15 +00004047 free(lpOldFileW);
4048 free(lpNewFileW);
4049 free(lpSubKeyW);
Alexandre Julliarda845b881998-06-01 10:44:35 +00004050 return ret;
4051}
4052