blob: f2f1d7d45be9f0f7e61857e28a9a92ebe5c604f0 [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
22#include <stdlib.h>
Alexandre Julliardc981d0b1996-03-31 16:40:13 +000023#include <string.h>
24#include <unistd.h>
25#include <ctype.h>
Alexandre Julliard8664b891996-04-05 14:58:24 +000026#include <errno.h>
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000027#include <sys/errno.h>
Alexandre Julliardcdcdede1996-04-21 14:57:41 +000028#include <sys/types.h>
29#include <sys/fcntl.h>
30#include <sys/stat.h>
Alexandre Julliard0623a6f1998-01-18 18:01:49 +000031#include <assert.h>
Alexandre Julliardcdcdede1996-04-21 14:57:41 +000032#include <time.h>
Marcus Meissner04c3e1d1999-02-19 10:37:02 +000033#include "windef.h"
34#include "winbase.h"
35#include "wine/winbase16.h"
36#include "wine/winestring.h"
Alexandre Julliardc981d0b1996-03-31 16:40:13 +000037#include "winerror.h"
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +000038#include "file.h"
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +000039#include "heap.h"
Alexandre Julliard06c275a1999-05-02 14:32:27 +000040#include "debugtools.h"
Alexandre Julliardc981d0b1996-03-31 16:40:13 +000041#include "xmalloc.h"
Marcus Meissner6b9dd2e1999-03-18 17:39:57 +000042#include "options.h"
Alexandre Julliardc981d0b1996-03-31 16:40:13 +000043#include "winreg.h"
John Richardson2bb013b1998-11-06 17:36:13 +000044#include "winversion.h"
Alexandre Julliardc981d0b1996-03-31 16:40:13 +000045
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000046DECLARE_DEBUG_CHANNEL(reg)
47DECLARE_DEBUG_CHANNEL(string)
48
Juergen Schmiedebc2b771998-11-14 18:59:30 +000049static void REGISTRY_Init(void);
Alexandre Julliardcdcdede1996-04-21 14:57:41 +000050/* FIXME: following defines should be configured global ... */
Alexandre Julliardc981d0b1996-03-31 16:40:13 +000051
Alexandre Julliardcdcdede1996-04-21 14:57:41 +000052/* NOTE: do not append a /. linux' mkdir() WILL FAIL if you do that */
Sylvain St.Germaine5332221999-04-10 16:46:15 +000053#define WINE_PREFIX "/.wine"
Marcus Meissneradf8a0c1999-06-12 08:18:38 +000054#define SAVE_USERS_DEFAULT ETCDIR"/wine.userreg"
55#define SAVE_LOCAL_MACHINE_DEFAULT ETCDIR"/wine.systemreg"
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +000056
57/* relative in ~user/.wine/ : */
Sylvain St.Germaine5332221999-04-10 16:46:15 +000058#define SAVE_CURRENT_USER "user.reg"
59#define SAVE_LOCAL_USERS_DEFAULT "wine.userreg"
60#define SAVE_LOCAL_MACHINE "system.reg"
Alexandre Julliardcdcdede1996-04-21 14:57:41 +000061
Sylvain St.Germaine5332221999-04-10 16:46:15 +000062#define KEY_REGISTRY "Software\\The WINE team\\WINE\\Registry"
63#define VAL_SAVEUPDATED "SaveOnlyUpdatedKeys"
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +000064
Alexandre Julliardd90840e1996-06-11 16:02:08 +000065/* one value of a key */
66typedef struct tagKEYVALUE
67{
68 LPWSTR name; /* name of value (UNICODE) or NULL for win31 */
69 DWORD type; /* type of value */
Alexandre Julliarda69b88b1998-03-15 20:29:56 +000070 DWORD len; /* length of data in BYTEs */
Alexandre Julliardd90840e1996-06-11 16:02:08 +000071 DWORD lastmodified; /* time of seconds since 1.1.1970 */
72 LPBYTE data; /* content, may be strings, binaries, etc. */
73} KEYVALUE,*LPKEYVALUE;
74
75/* a registry key */
76typedef struct tagKEYSTRUCT
77{
78 LPWSTR keyname; /* name of THIS key (UNICODE) */
79 DWORD flags; /* flags. */
80 LPWSTR class;
81 /* values */
82 DWORD nrofvalues; /* nr of values in THIS key */
83 LPKEYVALUE values; /* values in THIS key */
84 /* key management pointers */
85 struct tagKEYSTRUCT *next; /* next key on same hierarchy */
86 struct tagKEYSTRUCT *nextsub; /* keys that hang below THIS key */
87} KEYSTRUCT, *LPKEYSTRUCT;
88
89
Alexandre Julliardcdcdede1996-04-21 14:57:41 +000090static KEYSTRUCT *key_classes_root=NULL; /* windows 3.1 global values */
Alexandre Julliardc981d0b1996-03-31 16:40:13 +000091static KEYSTRUCT *key_current_user=NULL; /* user specific values */
92static KEYSTRUCT *key_local_machine=NULL;/* machine specific values */
93static KEYSTRUCT *key_users=NULL; /* all users? */
94
95/* dynamic, not saved */
96static KEYSTRUCT *key_performance_data=NULL;
97static KEYSTRUCT *key_current_config=NULL;
98static KEYSTRUCT *key_dyn_data=NULL;
99
100/* what valuetypes do we need to convert? */
101#define UNICONVMASK ((1<<REG_SZ)|(1<<REG_MULTI_SZ)|(1<<REG_EXPAND_SZ))
102
Alexandre Julliarde658d821997-11-30 17:45:40 +0000103
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000104static struct openhandle {
105 LPKEYSTRUCT lpkey;
106 HKEY hkey;
107 REGSAM accessmask;
108} *openhandles=NULL;
109static int nrofopenhandles=0;
110/* Starts after 1 because 0,1 are reserved for Win16 */
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000111/* Note: Should always be even, as Win95 ADVAPI32.DLL reserves odd
112 HKEYs for remote registry access */
113static int currenthandle=2;
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000114
115
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000116/*
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000117 * QUESTION
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000118 * Are these doing the same as HEAP_strdupAtoW and HEAP_strdupWtoA?
119 * If so, can we remove them?
Alexandre Julliarda845b881998-06-01 10:44:35 +0000120 * ANSWER
121 * No, the memory handling functions are called very often in here,
122 * just replacing them by HeapAlloc(SystemHeap,...) makes registry
123 * loading 100 times slower. -MM
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000124 */
Alexandre Julliarde658d821997-11-30 17:45:40 +0000125static LPWSTR strdupA2W(LPCSTR src)
126{
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000127 if(src) {
Alexandre Julliarde658d821997-11-30 17:45:40 +0000128 LPWSTR dest=xmalloc(2*strlen(src)+2);
129 lstrcpyAtoW(dest,src);
130 return dest;
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000131 }
132 return NULL;
Alexandre Julliarde658d821997-11-30 17:45:40 +0000133}
134
135static LPWSTR strdupW(LPCWSTR a) {
136 LPWSTR b;
137 int len;
138
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000139 if(a) {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000140 len=sizeof(WCHAR)*(lstrlenW(a)+1);
Alexandre Julliarde658d821997-11-30 17:45:40 +0000141 b=(LPWSTR)xmalloc(len);
142 memcpy(b,a,len);
143 return b;
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000144 }
145 return NULL;
146}
147
148LPWSTR strcvtA2W(LPCSTR src, int nchars)
149
150{
151 LPWSTR dest = xmalloc (2 * nchars + 2);
152
153 lstrcpynAtoW(dest,src,nchars+1);
154 dest[nchars] = 0;
155 return dest;
Alexandre Julliarde658d821997-11-30 17:45:40 +0000156}
Juergen Schmied26cae9d1999-01-23 12:11:09 +0000157/*
158 * we need to convert A to W with '\0' in strings (MULTI_SZ)
159 */
160
Alexandre Julliarda3960291999-02-26 11:11:13 +0000161static LPWSTR lmemcpynAtoW( LPWSTR dst, LPCSTR src, INT n )
Juergen Schmied26cae9d1999-01-23 12:11:09 +0000162{ LPWSTR p = dst;
163
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000164 TRACE_(reg)("\"%s\" %i\n",src, n);
Juergen Schmied26cae9d1999-01-23 12:11:09 +0000165
166 while (n-- > 0) *p++ = (WCHAR)(unsigned char)*src++;
167
168 return dst;
169}
Alexandre Julliarda3960291999-02-26 11:11:13 +0000170static LPSTR lmemcpynWtoA( LPSTR dst, LPCWSTR src, INT n )
Juergen Schmied26cae9d1999-01-23 12:11:09 +0000171{ LPSTR p = dst;
172
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000173 TRACE_(string)("L\"%s\" %i\n",debugstr_w(src), n);
Juergen Schmied26cae9d1999-01-23 12:11:09 +0000174
175 while (n-- > 0) *p++ = (CHAR)*src++;
176
177 return dst;
178}
179
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000180static void debug_print_value (LPBYTE lpbData, LPKEYVALUE key)
181{
182 if (TRACE_ON(reg) && lpbData)
183 {
184 switch(key->type)
185 {
Noomen Hamzac4cd0bf1999-05-08 10:50:34 +0000186 case REG_EXPAND_SZ:
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000187 case REG_SZ:
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000188 TRACE_(reg)(" Value %s, Data(sz)=%s\n",
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000189 debugstr_w(key->name),
190 debugstr_w((LPCWSTR)lpbData));
191 break;
Juergen Schmied26cae9d1999-01-23 12:11:09 +0000192
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000193 case REG_DWORD:
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000194 TRACE_(reg)(" Value %s, Data(dword)=0x%08lx\n",
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000195 debugstr_w(key->name),
196 (DWORD)*lpbData);
197 break;
198
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000199 case REG_MULTI_SZ:
200 {
201 int i;
202 LPCWSTR ptr = (LPCWSTR)lpbData;
203 for (i=0;ptr[0];i++)
204 {
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000205 TRACE_(reg)(" Value %s, MULTI_SZ(%i=%s)\n",
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000206 debugstr_w(key->name),
207 i,
208 debugstr_w(ptr));
Juergen Schmied26cae9d1999-01-23 12:11:09 +0000209
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000210 ptr += lstrlenW(ptr)+1;
211 }
212 }
213 break;
214
Noomen Hamzac4cd0bf1999-05-08 10:50:34 +0000215 default:
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000216 {
217 char szTemp[100]; /* 3*32 + 3 + 1 */
218 int i;
219 for ( i = 0; i < key->len ; i++)
220 {
221 sprintf (&(szTemp[i*3]),"%02x ", lpbData[i]);
222 if (i>=31)
223 {
224 sprintf (&(szTemp[i*3+3]),"...");
225 break;
226 }
227 }
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000228 TRACE_(reg)(" Value %s, Data(raw)=(%s)\n",
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000229 debugstr_w(key->name),
230 szTemp);
231 }
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000232 } /* switch */
233 } /* if */
Juergen Schmied26cae9d1999-01-23 12:11:09 +0000234}
235
Alexandre Julliarde658d821997-11-30 17:45:40 +0000236
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000237/******************************************************************************
238 * is_standard_hkey [Internal]
239 * Determines if a hkey is a standard key
240 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000241static BOOL is_standard_hkey( HKEY hkey )
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000242{
243 switch(hkey) {
244 case 0x00000000:
245 case 0x00000001:
246 case HKEY_CLASSES_ROOT:
247 case HKEY_CURRENT_CONFIG:
248 case HKEY_CURRENT_USER:
249 case HKEY_LOCAL_MACHINE:
250 case HKEY_USERS:
251 case HKEY_PERFORMANCE_DATA:
252 case HKEY_DYN_DATA:
253 return TRUE;
254 default:
255 return FALSE;
256 }
257}
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000258
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000259/******************************************************************************
260 * add_handle [Internal]
261 */
262static void add_handle( HKEY hkey, LPKEYSTRUCT lpkey, REGSAM accessmask )
263{
264 int i;
265
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000266 TRACE_(reg)("(0x%x,%p,0x%lx)\n",hkey,lpkey,accessmask);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000267 /* Check for duplicates */
268 for (i=0;i<nrofopenhandles;i++) {
269 if (openhandles[i].lpkey==lpkey) {
270 /* This is not really an error - the user is allowed to create
271 two (or more) handles to the same key */
272 /*WARN(reg, "Adding key %p twice\n",lpkey);*/
273 }
274 if (openhandles[i].hkey==hkey) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000275 WARN_(reg)("Adding handle %x twice\n",hkey);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000276 }
277 }
278 openhandles=xrealloc( openhandles,
279 sizeof(struct openhandle)*(nrofopenhandles+1));
280
281 openhandles[i].lpkey = lpkey;
282 openhandles[i].hkey = hkey;
283 openhandles[i].accessmask = accessmask;
284 nrofopenhandles++;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000285}
286
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000287
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000288/******************************************************************************
289 * get_handle [Internal]
290 *
291 * RETURNS
292 * Success: Pointer to key
293 * Failure: NULL
294 */
295static LPKEYSTRUCT get_handle( HKEY hkey )
296{
297 int i;
298
299 for (i=0; i<nrofopenhandles; i++)
300 if (openhandles[i].hkey == hkey)
301 return openhandles[i].lpkey;
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000302 WARN_(reg)("Could not find handle 0x%x\n",hkey);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000303 return NULL;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000304}
305
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000306
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000307/******************************************************************************
308 * remove_handle [Internal]
309 *
310 * PARAMS
311 * hkey [I] Handle of key to remove
312 *
313 * RETURNS
314 * Success: ERROR_SUCCESS
315 * Failure: ERROR_INVALID_HANDLE
316 */
317static DWORD remove_handle( HKEY hkey )
318{
319 int i;
320
321 for (i=0;i<nrofopenhandles;i++)
322 if (openhandles[i].hkey==hkey)
323 break;
324
325 if (i == nrofopenhandles) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000326 WARN_(reg)("Could not find handle 0x%x\n",hkey);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000327 return ERROR_INVALID_HANDLE;
328 }
329
330 memcpy( openhandles+i,
331 openhandles+i+1,
332 sizeof(struct openhandle)*(nrofopenhandles-i-1)
333 );
334 openhandles=xrealloc(openhandles,sizeof(struct openhandle)*(nrofopenhandles-1));
335 nrofopenhandles--;
336 return ERROR_SUCCESS;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000337}
338
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000339/******************************************************************************
340 * lookup_hkey [Internal]
Alexandre Julliarda845b881998-06-01 10:44:35 +0000341 *
342 * Just as the name says. Creates the root keys on demand, so we can call the
343 * Reg* functions at any time.
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000344 *
345 * RETURNS
346 * Success: Pointer to key structure
347 * Failure: NULL
348 */
Alexandre Julliarda845b881998-06-01 10:44:35 +0000349#define ADD_ROOT_KEY(xx) \
350 xx = (LPKEYSTRUCT)xmalloc(sizeof(KEYSTRUCT));\
351 memset(xx,'\0',sizeof(KEYSTRUCT));\
352 xx->keyname= strdupA2W("<should_not_appear_anywhere>");
353
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000354static LPKEYSTRUCT lookup_hkey( HKEY hkey )
355{
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000356 switch (hkey) {
357 /* 0 and 1 are valid rootkeys in win16 shell.dll and are used by
358 * some programs. Do not remove those cases. -MM
359 */
360 case 0x00000000:
361 case 0x00000001:
362 case HKEY_CLASSES_ROOT:
363 {
364 if (!key_classes_root)
365 {
366 HKEY cl_r_hkey;
Alexandre Julliarda845b881998-06-01 10:44:35 +0000367
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000368 /* calls lookup_hkey recursively, TWICE */
369 if ( RegCreateKey16(
370 HKEY_LOCAL_MACHINE,
371 "SOFTWARE\\Classes",
372 &cl_r_hkey) != ERROR_SUCCESS)
373 {
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000374 ERR_(reg)("Could not create HKLM\\SOFTWARE\\Classes. This is impossible.\n");
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000375 exit(1);
376 }
Alexandre Julliarda845b881998-06-01 10:44:35 +0000377
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000378 key_classes_root = lookup_hkey(cl_r_hkey);
379 }
380 return key_classes_root;
381 }
382
383 case HKEY_CURRENT_USER:
384 if (!key_current_user) {
385 ADD_ROOT_KEY(key_current_user);
386 }
387 return key_current_user;
388
389 case HKEY_LOCAL_MACHINE:
390 if (!key_local_machine) {
391 ADD_ROOT_KEY(key_local_machine);
392 REGISTRY_Init();
393 }
394 return key_local_machine;
395
396 case HKEY_USERS:
397 if (!key_users) {
398 ADD_ROOT_KEY(key_users);
399 }
400 return key_users;
401
402 case HKEY_PERFORMANCE_DATA:
403 if (!key_performance_data) {
404 ADD_ROOT_KEY(key_performance_data);
405 }
406 return key_performance_data;
407
408 case HKEY_DYN_DATA:
409 if (!key_dyn_data) {
410 ADD_ROOT_KEY(key_dyn_data);
411 }
412 return key_dyn_data;
413
414 case HKEY_CURRENT_CONFIG:
415 if (!key_current_config) {
416 ADD_ROOT_KEY(key_current_config);
417 }
418 return key_current_config;
419
420 default:
421 return get_handle(hkey);
422
423 }
424 /*NOTREACHED*/
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000425}
Alexandre Julliarda845b881998-06-01 10:44:35 +0000426#undef ADD_ROOT_KEY
427/* so we don't accidently access them ... */
428#define key_current_config NULL NULL
429#define key_current_user NULL NULL
430#define key_users NULL NULL
431#define key_local_machine NULL NULL
432#define key_classes_root NULL NULL
433#define key_dyn_data NULL NULL
434#define key_performance_data NULL NULL
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000435
436/******************************************************************************
437 * split_keypath [Internal]
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000438 * splits the unicode string 'wp' into an array of strings.
439 * the array is allocated by this function.
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000440 * Free the array using FREE_KEY_PATH
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000441 *
442 * PARAMS
443 * wp [I] String to split up
444 * wpv [O] Array of pointers to strings
445 * wpc [O] Number of components
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000446 */
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000447static void split_keypath( LPCWSTR wp, LPWSTR **wpv, int *wpc)
448{
449 int i,j,len;
450 LPWSTR ws;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000451
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000452 TRACE_(reg)("(%s,%p,%p)\n",debugstr_w(wp),wpv,wpc);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000453
454 ws = HEAP_strdupW( SystemHeap, 0, wp );
455
456 /* We know we have at least one substring */
457 *wpc = 1;
458
459 /* Replace each backslash with NULL, and increment the count */
460 for (i=0;ws[i];i++) {
461 if (ws[i]=='\\') {
462 ws[i]=0;
463 (*wpc)++;
464 }
465 }
466
467 len = i;
468
469 /* Allocate the space for the array of pointers, leaving room for the
470 NULL at the end */
471 *wpv = (LPWSTR*)HeapAlloc( SystemHeap, 0, sizeof(LPWSTR)*(*wpc+2));
472 (*wpv)[0]= ws;
473
474 /* Assign each pointer to the appropriate character in the string */
475 j = 1;
476 for (i=1;i<len;i++)
477 if (ws[i-1]==0) {
478 (*wpv)[j++]=ws+i;
479 /* TRACE(reg, " Subitem %d = %s\n",j-1,debugstr_w((*wpv)[j-1])); */
480 }
481
482 (*wpv)[j]=NULL;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000483}
Alexandre Julliard9ea19e51997-01-01 17:29:55 +0000484#define FREE_KEY_PATH HeapFree(SystemHeap,0,wps[0]);HeapFree(SystemHeap,0,wps);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000485
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000486
487
488
489/******************************************************************************
Alexandre Julliarda845b881998-06-01 10:44:35 +0000490 * REGISTRY_Init [Internal]
491 * Registry initialisation, allocates some default keys.
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000492 */
Juergen Schmiedebc2b771998-11-14 18:59:30 +0000493static void REGISTRY_Init(void) {
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000494 HKEY hkey;
495 char buf[200];
Alexandre Julliard8bbf8181996-09-13 16:50:47 +0000496
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000497 TRACE_(reg)("(void)\n");
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000498
499 RegCreateKey16(HKEY_DYN_DATA,"PerfStats\\StatData",&hkey);
Alexandre Julliard8bbf8181996-09-13 16:50:47 +0000500 RegCloseKey(hkey);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000501
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000502 /* This was an Open, but since it is called before the real registries
503 are loaded, it was changed to a Create - MTB 980507*/
504 RegCreateKey16(HKEY_LOCAL_MACHINE,"HARDWARE\\DESCRIPTION\\System",&hkey);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000505 RegSetValueExA(hkey,"Identifier",0,REG_SZ,"SystemType WINE",strlen("SystemType WINE"));
Alexandre Julliard8bbf8181996-09-13 16:50:47 +0000506 RegCloseKey(hkey);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000507
Alexandre Julliard8bbf8181996-09-13 16:50:47 +0000508 /* \\SOFTWARE\\Microsoft\\Window NT\\CurrentVersion
509 * CurrentVersion
510 * CurrentBuildNumber
511 * CurrentType
512 * string RegisteredOwner
513 * string RegisteredOrganization
514 *
515 */
516 /* System\\CurrentControlSet\\Services\\SNMP\\Parameters\\RFC1156Agent
517 * string SysContact
518 * string SysLocation
519 * SysServices
520 */
521 if (-1!=gethostname(buf,200)) {
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000522 RegCreateKey16(HKEY_LOCAL_MACHINE,"System\\CurrentControlSet\\Control\\ComputerName\\ComputerName",&hkey);
523 RegSetValueEx16(hkey,"ComputerName",0,REG_SZ,buf,strlen(buf)+1);
524 RegCloseKey(hkey);
Alexandre Julliard8bbf8181996-09-13 16:50:47 +0000525 }
526}
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000527
528
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000529/************************ SAVE Registry Function ****************************/
530
531#define REGISTRY_SAVE_VERSION 0x00000001
532
533/* Registry saveformat:
534 * If you change it, increase above number by 1, which will flush
535 * old registry database files.
536 *
537 * Global:
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000538 * "WINE REGISTRY Version %d"
539 * subkeys....
540 * Subkeys:
541 * keyname
542 * valuename=lastmodified,type,data
543 * ...
544 * subkeys
545 * ...
546 * keyname,valuename,stringdata:
547 * the usual ascii characters from 0x00-0xff (well, not 0x00)
548 * and \uXXXX as UNICODE value XXXX with XXXX>0xff
549 * ( "=\\\t" escaped in \uXXXX form.)
550 * type,lastmodified:
551 * int
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000552 *
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000553 * FIXME: doesn't save 'class' (what does it mean anyway?), nor flags.
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000554 *
555 * [HKEY_CURRENT_USER\\Software\\The WINE team\\WINE\\Registry]
556 * SaveOnlyUpdatedKeys=yes
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000557 */
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000558
559/******************************************************************************
560 * _save_check_tainted [Internal]
561 */
562static int _save_check_tainted( LPKEYSTRUCT lpkey )
563{
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000564 int tainted;
565
566 if (!lpkey)
567 return 0;
568 if (lpkey->flags & REG_OPTION_TAINTED)
569 tainted = 1;
570 else
571 tainted = 0;
572 while (lpkey) {
573 if (_save_check_tainted(lpkey->nextsub)) {
574 lpkey->flags |= REG_OPTION_TAINTED;
575 tainted = 1;
576 }
577 lpkey = lpkey->next;
578 }
579 return tainted;
580}
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000581
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000582/******************************************************************************
583 * _save_USTRING [Internal]
584 */
585static void _save_USTRING( FILE *F, LPWSTR wstr, int escapeeq )
586{
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000587 LPWSTR s;
588 int doescape;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000589
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000590 if (wstr==NULL)
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000591 return;
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000592 s=wstr;
593 while (*s) {
594 doescape=0;
595 if (*s>0xff)
596 doescape = 1;
597 if (*s=='\n')
598 doescape = 1;
599 if (escapeeq && *s=='=')
600 doescape = 1;
601 if (*s=='\\')
Alexandre Julliard641ee761997-08-04 16:34:36 +0000602 fputc(*s,F); /* if \\ then put it twice. */
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000603 if (doescape)
604 fprintf(F,"\\u%04x",*((unsigned short*)s));
605 else
606 fputc(*s,F);
607 s++;
608 }
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000609}
610
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000611/******************************************************************************
612 * _savesubkey [Internal]
Juergen Schmiedf74fa4e1999-01-31 09:19:46 +0000613 *
614 * NOTES
615 * REG_MULTI_SZ is handled as binary (like in win95) (js)
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000616 */
617static int _savesubkey( FILE *F, LPKEYSTRUCT lpkey, int level, int all )
618{
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000619 LPKEYSTRUCT lpxkey;
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000620 int i,tabs,j;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000621
622 lpxkey = lpkey;
623 while (lpxkey) {
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000624 if ( !(lpxkey->flags & REG_OPTION_VOLATILE) &&
625 (all || (lpxkey->flags & REG_OPTION_TAINTED))
626 ) {
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000627 for (tabs=level;tabs--;)
628 fputc('\t',F);
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000629 _save_USTRING(F,lpxkey->keyname,1);
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000630 fputs("\n",F);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000631 for (i=0;i<lpxkey->nrofvalues;i++) {
632 LPKEYVALUE val=lpxkey->values+i;
633
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000634 for (tabs=level+1;tabs--;)
635 fputc('\t',F);
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000636 _save_USTRING(F,val->name,0);
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000637 fputc('=',F);
638 fprintf(F,"%ld,%ld,",val->type,val->lastmodified);
Juergen Schmiedf74fa4e1999-01-31 09:19:46 +0000639 if ( val->type == REG_SZ || val->type == REG_EXPAND_SZ )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000640 _save_USTRING(F,(LPWSTR)val->data,0);
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000641 else
642 for (j=0;j<val->len;j++)
643 fprintf(F,"%02x",*((unsigned char*)val->data+j));
644 fputs("\n",F);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000645 }
646 /* descend recursively */
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000647 if (!_savesubkey(F,lpxkey->nextsub,level+1,all))
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000648 return 0;
649 }
650 lpxkey=lpxkey->next;
651 }
652 return 1;
653}
654
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000655
656/******************************************************************************
657 * _savesubreg [Internal]
658 */
659static int _savesubreg( FILE *F, LPKEYSTRUCT lpkey, int all )
660{
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000661 fprintf(F,"WINE REGISTRY Version %d\n",REGISTRY_SAVE_VERSION);
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000662 _save_check_tainted(lpkey->nextsub);
663 return _savesubkey(F,lpkey->nextsub,0,all);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000664}
665
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000666
667/******************************************************************************
668 * _savereg [Internal]
669 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000670static BOOL _savereg( LPKEYSTRUCT lpkey, char *fn, int all )
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000671{
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000672 FILE *F;
673
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000674 F=fopen(fn,"w");
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000675 if (F==NULL) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000676 WARN_(reg)("Couldn't open %s for writing: %s\n",
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000677 fn,strerror(errno)
678 );
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000679 return FALSE;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000680 }
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000681 if (!_savesubreg(F,lpkey,all)) {
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000682 fclose(F);
683 unlink(fn);
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000684 WARN_(reg)("Failed to save keys, perhaps no more diskspace for %s?\n",fn);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000685 return FALSE;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000686 }
687 fclose(F);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +0000688 return TRUE;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000689}
690
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000691
692/******************************************************************************
693 * SHELL_SaveRegistry [Internal]
694 */
695void SHELL_SaveRegistry( void )
696{
Alexandre Julliard154c99b1999-04-25 12:41:36 +0000697 char *fn, *home, *tmp;
698 char buf[4];
699 HKEY hkey;
700 int all;
701 int usedCfgUser = 0;
702 int usedCfgLM = 0;
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000703
Alexandre Julliard06c275a1999-05-02 14:32:27 +0000704 TRACE_(reg)("(void)\n");
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000705
Alexandre Julliard154c99b1999-04-25 12:41:36 +0000706 all=0;
707 if (RegOpenKey16(HKEY_CURRENT_USER,KEY_REGISTRY,&hkey)!=ERROR_SUCCESS)
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000708 {
Alexandre Julliard154c99b1999-04-25 12:41:36 +0000709 strcpy(buf,"yes");
710 }
711 else
712 {
713 DWORD len,junk,type;
714
715 len=4;
716 if ((ERROR_SUCCESS!=RegQueryValueExA( hkey,
717 VAL_SAVEUPDATED,
718 &junk,
719 &type,
720 buf,
721 &len)) || (type!=REG_SZ))
722 {
723 strcpy(buf,"yes");
724 }
725 RegCloseKey(hkey);
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000726 }
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000727
Alexandre Julliard154c99b1999-04-25 12:41:36 +0000728 if (lstrcmpiA(buf,"yes")) all=1;
Nathan Zorichbd3771c1999-03-14 15:12:48 +0000729
Alexandre Julliard154c99b1999-04-25 12:41:36 +0000730 if (!(home = getenv( "HOME" )))
731 {
Patrik Stridvall1ed4ecf1999-06-26 14:58:24 +0000732 WARN_(reg)("Failed to get homedirectory of UID %ld.\n",(long) getuid());
Alexandre Julliard154c99b1999-04-25 12:41:36 +0000733 return;
734 }
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000735 /*
736 * Save HKEY_CURRENT_USER
737 * Try first saving according to the defined location in .winerc
738 */
Alexandre Julliard154c99b1999-04-25 12:41:36 +0000739 fn = xmalloc( MAX_PATHNAME_LEN );
740 if (PROFILE_GetWineIniString ( "Registry", "UserFileName", "", fn, MAX_PATHNAME_LEN - 1))
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000741 {
Alexandre Julliard154c99b1999-04-25 12:41:36 +0000742 _savereg(lookup_hkey(HKEY_CURRENT_USER),fn,all);
743 usedCfgUser = 1;
744 }
745 free (fn);
Alexandre Julliardb1bac321996-12-15 19:45:59 +0000746
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000747 if (usedCfgUser != 1)
748 {
Alexandre Julliard154c99b1999-04-25 12:41:36 +0000749 fn=(char*)xmalloc( strlen(home) + strlen(WINE_PREFIX) +
750 strlen(SAVE_CURRENT_USER) + 2 );
751 strcpy(fn,home);
752 strcat(fn,WINE_PREFIX);
753
754 /* create the directory. don't care about errorcodes. */
755 mkdir(fn,0755); /* drwxr-xr-x */
756 strcat(fn,"/"SAVE_CURRENT_USER);
Nathan Zorichbd3771c1999-03-14 15:12:48 +0000757
Alexandre Julliard154c99b1999-04-25 12:41:36 +0000758 tmp = (char*)xmalloc(strlen(fn)+strlen(".tmp")+1);
759 strcpy(tmp,fn);
760 strcat(tmp,".tmp");
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000761
Alexandre Julliard154c99b1999-04-25 12:41:36 +0000762 if (_savereg(lookup_hkey(HKEY_CURRENT_USER),tmp,all)) {
763 if (-1==rename(tmp,fn)) {
764 perror("rename tmp registry");
765 unlink(tmp);
766 }
767 }
768 free(tmp);
769 free(fn);
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000770 }
Nathan Zorichbd3771c1999-03-14 15:12:48 +0000771
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000772 /*
773 * Save HKEY_LOCAL_MACHINE
774 * Try first saving according to the defined location in .winerc
775 */
776 fn = xmalloc ( MAX_PATHNAME_LEN);
Alexandre Julliard154c99b1999-04-25 12:41:36 +0000777 if (PROFILE_GetWineIniString ( "Registry", "LocalMachineFileName", "", fn,
778 MAX_PATHNAME_LEN - 1))
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000779 {
Alexandre Julliard154c99b1999-04-25 12:41:36 +0000780 _savereg(lookup_hkey(HKEY_LOCAL_MACHINE), fn, all);
781 usedCfgLM = 1;
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000782 }
Alexandre Julliard154c99b1999-04-25 12:41:36 +0000783 free (fn);
Nathan Zorichbd3771c1999-03-14 15:12:48 +0000784
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000785 if ( usedCfgLM != 1)
786 {
Alexandre Julliard154c99b1999-04-25 12:41:36 +0000787 fn=(char*)xmalloc( strlen(home)+ strlen(WINE_PREFIX)+ strlen(SAVE_LOCAL_MACHINE)+2);
788 strcpy(fn,home);
789 strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_MACHINE);
790
791 tmp = (char*)xmalloc(strlen(fn)+strlen(".tmp")+1);
792 strcpy(tmp,fn);
793 strcat(tmp,".tmp");
794
795 if (_savereg(lookup_hkey(HKEY_LOCAL_MACHINE),tmp,all)) {
796 if (-1==rename(tmp,fn)) {
797 perror("rename tmp registry");
798 unlink(tmp);
799 }
800 }
801 free(tmp);
802 free(fn);
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000803 }
Nathan Zorichbd3771c1999-03-14 15:12:48 +0000804
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000805 /*
806 * Save HKEY_USERS
807 */
Alexandre Julliard154c99b1999-04-25 12:41:36 +0000808 fn=(char*)xmalloc( strlen(home)+ strlen(WINE_PREFIX)+ strlen(SAVE_LOCAL_USERS_DEFAULT)+2);
Nathan Zorichbd3771c1999-03-14 15:12:48 +0000809
Alexandre Julliard154c99b1999-04-25 12:41:36 +0000810 strcpy(fn,home);
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000811 strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_USERS_DEFAULT);
812
813 tmp = (char*)xmalloc(strlen(fn)+strlen(".tmp")+1);
814 strcpy(tmp,fn);strcat(tmp,".tmp");
815 if ( _savereg(lookup_hkey(HKEY_USERS),tmp,FALSE)) {
Alexandre Julliard154c99b1999-04-25 12:41:36 +0000816 if (-1==rename(tmp,fn)) {
817 perror("rename tmp registry");
818 unlink(tmp);
819 }
Sylvain St.Germaine5332221999-04-10 16:46:15 +0000820 }
821 free(tmp);
822 free(fn);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000823}
824
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000825
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000826/************************ LOAD Registry Function ****************************/
827
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000828
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000829
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000830/******************************************************************************
831 * _find_or_add_key [Internal]
832 */
833static LPKEYSTRUCT _find_or_add_key( LPKEYSTRUCT lpkey, LPWSTR keyname )
834{
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000835 LPKEYSTRUCT lpxkey,*lplpkey;
836
Alexandre Julliarddadf78f1998-05-17 17:13:43 +0000837 if ((!keyname) || (keyname[0]==0)) {
Alexandre Julliarda11d7b11998-03-01 20:05:02 +0000838 free(keyname);
839 return lpkey;
840 }
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000841 lplpkey= &(lpkey->nextsub);
842 lpxkey = *lplpkey;
843 while (lpxkey) {
Marcus Meissnerf2ef1451999-06-26 11:41:33 +0000844 if ( tolower(lpxkey->keyname[0])==tolower(keyname[0]) &&
Alexandre Julliarda3960291999-02-26 11:11:13 +0000845 !lstrcmpiW(lpxkey->keyname,keyname)
Alexandre Julliarda0d77311998-09-13 16:32:00 +0000846 )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000847 break;
848 lplpkey = &(lpxkey->next);
849 lpxkey = *lplpkey;
850 }
851 if (lpxkey==NULL) {
852 *lplpkey = (LPKEYSTRUCT)xmalloc(sizeof(KEYSTRUCT));
853 lpxkey = *lplpkey;
854 memset(lpxkey,'\0',sizeof(KEYSTRUCT));
855 lpxkey->keyname = keyname;
856 } else
857 free(keyname);
858 return lpxkey;
859}
860
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000861/******************************************************************************
862 * _find_or_add_value [Internal]
863 */
864static void _find_or_add_value( LPKEYSTRUCT lpkey, LPWSTR name, DWORD type,
865 LPBYTE data, DWORD len, DWORD lastmodified )
866{
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000867 LPKEYVALUE val=NULL;
868 int i;
869
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000870 if (name && !*name) {/* empty string equals default (NULL) value */
871 free(name);
872 name = NULL;
873 }
874
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000875 for (i=0;i<lpkey->nrofvalues;i++) {
876 val=lpkey->values+i;
877 if (name==NULL) {
878 if (val->name==NULL)
879 break;
880 } else {
Marcus Meissnerf2ef1451999-06-26 11:41:33 +0000881 if ( val->name!=NULL &&
882 tolower(val->name[0])==tolower(name[0]) &&
Alexandre Julliarda3960291999-02-26 11:11:13 +0000883 !lstrcmpiW(val->name,name)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000884 )
885 break;
886 }
887 }
888 if (i==lpkey->nrofvalues) {
889 lpkey->values = xrealloc(
890 lpkey->values,
891 (++lpkey->nrofvalues)*sizeof(KEYVALUE)
892 );
893 val=lpkey->values+i;
894 memset(val,'\0',sizeof(KEYVALUE));
895 val->name = name;
896 } else {
897 if (name)
898 free(name);
899 }
900 if (val->lastmodified<lastmodified) {
901 val->lastmodified=lastmodified;
902 val->type = type;
Noomen Hamza9adef531999-04-24 11:49:26 +0000903
904 if ((type == REG_SZ || type == REG_EXPAND_SZ) && !data){
905
906 data=xmalloc(sizeof(WCHAR));
907 memset(data,0,sizeof(WCHAR));
908 len =sizeof(WCHAR);
909 }
910
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +0000911 val->len = len;
912 if (val->data)
913 free(val->data);
914 val->data = data;
915 } else
916 free(data);
917}
918
919
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000920/******************************************************************************
921 * _wine_read_line [Internal]
922 *
923 * reads a line including dynamically enlarging the readbuffer and throwing
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000924 * away comments
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000925 */
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000926static int _wine_read_line( FILE *F, char **buf, int *len )
927{
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000928 char *s,*curread;
929 int mylen,curoff;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000930
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000931 curread = *buf;
932 mylen = *len;
933 **buf = '\0';
934 while (1) {
935 while (1) {
936 s=fgets(curread,mylen,F);
937 if (s==NULL)
938 return 0; /* EOF */
939 if (NULL==(s=strchr(curread,'\n'))) {
940 /* buffer wasn't large enough */
941 curoff = strlen(*buf);
942 *buf = xrealloc(*buf,*len*2);
943 curread = *buf + curoff;
944 mylen = *len; /* we filled up the buffer and
945 * got new '*len' bytes to fill
946 */
947 *len = *len * 2;
948 } else {
949 *s='\0';
950 break;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +0000951 }
952 }
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000953 /* throw away comments */
954 if (**buf=='#' || **buf==';') {
955 curread = *buf;
956 mylen = *len;
957 continue;
958 }
959 if (s) /* got end of line */
960 break;
961 }
962 return 1;
963}
964
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000965
966/******************************************************************************
967 * _wine_read_USTRING [Internal]
968 *
969 * converts a char* into a UNICODE string (up to a special char)
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000970 * and returns the position exactly after that string
971 */
Alexandre Julliardf90efa91998-06-14 15:24:15 +0000972static char* _wine_read_USTRING( char *buf, LPWSTR *str )
973{
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000974 char *s;
975 LPWSTR ws;
976
977 /* read up to "=" or "\0" or "\n" */
978 s = buf;
979 if (*s == '=') {
980 /* empty string is the win3.1 default value(NULL)*/
981 *str = NULL;
982 return s;
983 }
984 *str = (LPWSTR)xmalloc(2*strlen(buf)+2);
985 ws = *str;
986 while (*s && (*s!='\n') && (*s!='=')) {
987 if (*s!='\\')
988 *ws++=*((unsigned char*)s++);
989 else {
990 s++;
Alexandre Julliard638f1691999-01-17 16:32:32 +0000991 if (!*s) {
992 /* Dangling \ ... may only happen if a registry
993 * write was short. FIXME: What do to?
994 */
995 break;
996 }
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000997 if (*s=='\\') {
Alexandre Julliard84c70f51997-05-09 08:40:27 +0000998 *ws++='\\';
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000999 s++;
1000 continue;
1001 }
1002 if (*s!='u') {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001003 WARN_(reg)("Non unicode escape sequence \\%c found in |%s|\n",*s,buf);
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001004 *ws++='\\';
1005 *ws++=*s++;
1006 } else {
1007 char xbuf[5];
1008 int wc;
1009
1010 s++;
1011 memcpy(xbuf,s,4);xbuf[4]='\0';
1012 if (!sscanf(xbuf,"%x",&wc))
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001013 WARN_(reg)("Strange escape sequence %s found in |%s|\n",xbuf,buf);
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001014 s+=4;
1015 *ws++ =(unsigned short)wc;
1016 }
1017 }
1018 }
1019 *ws = 0;
1020 ws = *str;
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001021 if (*ws)
1022 *str = strdupW(*str);
1023 else
1024 *str = NULL;
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001025 free(ws);
1026 return s;
1027}
1028
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001029
1030/******************************************************************************
1031 * _wine_loadsubkey [Internal]
1032 *
1033 * NOTES
1034 * It seems like this is returning a boolean. Should it?
1035 *
1036 * RETURNS
1037 * Success: 1
1038 * Failure: 0
1039 */
1040static int _wine_loadsubkey( FILE *F, LPKEYSTRUCT lpkey, int level, char **buf,
1041 int *buflen, DWORD optflag )
1042{
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001043 LPKEYSTRUCT lpxkey;
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001044 int i;
1045 char *s;
1046 LPWSTR name;
1047
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001048 TRACE_(reg)("(%p,%p,%d,%s,%d,%lx)\n", F, lpkey, level, debugstr_a(*buf),
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001049 *buflen, optflag);
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001050
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001051 lpkey->flags |= optflag;
1052
1053 /* Good. We already got a line here ... so parse it */
1054 lpxkey = NULL;
1055 while (1) {
1056 i=0;s=*buf;
1057 while (*s=='\t') {
1058 s++;
1059 i++;
1060 }
1061 if (i>level) {
1062 if (lpxkey==NULL) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001063 WARN_(reg)("Got a subhierarchy without resp. key?\n");
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001064 return 0;
1065 }
1066 _wine_loadsubkey(F,lpxkey,level+1,buf,buflen,optflag);
1067 continue;
1068 }
1069
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001070 /* let the caller handle this line */
1071 if (i<level || **buf=='\0')
1072 return 1;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001073
1074 /* it can be: a value or a keyname. Parse the name first */
1075 s=_wine_read_USTRING(s,&name);
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001076
1077 /* switch() default: hack to avoid gotos */
1078 switch (0) {
1079 default:
1080 if (*s=='\0') {
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001081 lpxkey=_find_or_add_key(lpkey,name);
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001082 } else {
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001083 LPBYTE data;
1084 int len,lastmodified,type;
1085
1086 if (*s!='=') {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001087 WARN_(reg)("Unexpected character: %c\n",*s);
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001088 break;
1089 }
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001090 s++;
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001091 if (2!=sscanf(s,"%d,%d,",&type,&lastmodified)) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001092 WARN_(reg)("Haven't understood possible value in |%s|, skipping.\n",*buf);
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001093 break;
1094 }
1095 /* skip the 2 , */
1096 s=strchr(s,',');s++;
1097 s=strchr(s,',');s++;
Juergen Schmiedf74fa4e1999-01-31 09:19:46 +00001098 if (type == REG_SZ || type == REG_EXPAND_SZ) {
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001099 s=_wine_read_USTRING(s,(LPWSTR*)&data);
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001100 if (data)
Alexandre Julliarda3960291999-02-26 11:11:13 +00001101 len = lstrlenW((LPWSTR)data)*2+2;
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001102 else
1103 len = 0;
1104 } else {
1105 len=strlen(s)/2;
1106 data = (LPBYTE)xmalloc(len+1);
1107 for (i=0;i<len;i++) {
1108 data[i]=0;
1109 if (*s>='0' && *s<='9')
1110 data[i]=(*s-'0')<<4;
1111 if (*s>='a' && *s<='f')
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001112 data[i]=(*s-'a'+'\xa')<<4;
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001113 if (*s>='A' && *s<='F')
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001114 data[i]=(*s-'A'+'\xa')<<4;
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001115 s++;
1116 if (*s>='0' && *s<='9')
1117 data[i]|=*s-'0';
1118 if (*s>='a' && *s<='f')
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001119 data[i]|=*s-'a'+'\xa';
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001120 if (*s>='A' && *s<='F')
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001121 data[i]|=*s-'A'+'\xa';
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001122 s++;
1123 }
1124 }
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001125 _find_or_add_value(lpkey,name,type,data,len,lastmodified);
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001126 }
1127 }
1128 /* read the next line */
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001129 if (!_wine_read_line(F,buf,buflen))
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001130 return 1;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001131 }
1132 return 1;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00001133}
1134
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001135
1136/******************************************************************************
1137 * _wine_loadsubreg [Internal]
1138 */
1139static int _wine_loadsubreg( FILE *F, LPKEYSTRUCT lpkey, DWORD optflag )
1140{
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001141 int ver;
1142 char *buf;
1143 int buflen;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00001144
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001145 buf=xmalloc(10);buflen=10;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001146 if (!_wine_read_line(F,&buf,&buflen)) {
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001147 free(buf);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00001148 return 0;
1149 }
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001150 if (!sscanf(buf,"WINE REGISTRY Version %d",&ver)) {
1151 free(buf);
1152 return 0;
1153 }
1154 if (ver!=REGISTRY_SAVE_VERSION) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001155 TRACE_(reg)("Old format (%d) registry found, ignoring it. (buf was %s).\n",ver,buf);
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001156 free(buf);
1157 return 0;
1158 }
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001159 if (!_wine_read_line(F,&buf,&buflen)) {
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001160 free(buf);
1161 return 0;
1162 }
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001163 if (!_wine_loadsubkey(F,lpkey,0,&buf,&buflen,optflag)) {
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001164 free(buf);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00001165 return 0;
1166 }
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001167 free(buf);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00001168 return 1;
1169}
1170
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00001171
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001172/******************************************************************************
1173 * _wine_loadreg [Internal]
1174 */
1175static void _wine_loadreg( LPKEYSTRUCT lpkey, char *fn, DWORD optflag )
1176{
1177 FILE *F;
1178
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001179 TRACE_(reg)("(%p,%s,%lx)\n",lpkey,debugstr_a(fn),optflag);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001180
1181 F = fopen(fn,"rb");
1182 if (F==NULL) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001183 WARN_(reg)("Couldn't open %s for reading: %s\n",fn,strerror(errno) );
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001184 return;
1185 }
1186 if (!_wine_loadsubreg(F,lpkey,optflag)) {
1187 fclose(F);
1188 unlink(fn);
1189 return;
1190 }
1191 fclose(F);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00001192}
1193
Sylvain St.Germaine5332221999-04-10 16:46:15 +00001194/******************************************************************************
1195 * _flush_registry [Internal]
1196 *
1197 * This function allow to flush section of the internal registry. It is mainly
1198 * implements to fix a problem with the global HKU and the local HKU.
1199 * Those two files are read to build the HKU\.Default branch to finaly copy
1200 * this branch onto HKCU hive, once this is done, if we keep the HKU hive as is,
1201 * all the global HKU are saved onto the user's personal version of HKU hive.
1202 * which is bad...
1203 */
1204
1205 /* Forward declaration of recusive agent */
1206static void _flush_reg(LPKEYSTRUCT from);
1207
1208static void _flush_registry( LPKEYSTRUCT from )
1209{
1210 /* make sure we have something... */
1211 if (from == NULL)
1212 return;
1213
1214 /* Launch the recusive agent on sub branches */
1215 _flush_reg( from->nextsub );
1216 _flush_reg( from->next );
1217
1218 /* Initialize pointers */
1219 from->nextsub = NULL;
1220 from->next = NULL;
1221}
1222static void _flush_reg( LPKEYSTRUCT from )
1223{
1224 int j;
1225
1226 /* make sure we have something... */
1227 if (from == NULL)
1228 return;
1229
1230 /*
1231 * do the same for the child keys
1232 */
1233 if (from->nextsub != NULL)
1234 _flush_reg(from->nextsub);
1235
1236 /*
1237 * do the same for the sibling keys
1238 */
1239 if (from->next != NULL)
1240 _flush_reg(from->next);
1241
1242 /*
1243 * iterate through this key's values and delete them
1244 */
1245 for (j=0;j<from->nrofvalues;j++)
1246 {
1247 free( (from->values+j)->name);
1248 free( (from->values+j)->data);
1249 }
1250
1251 /*
1252 * free the structure
1253 */
1254 if ( from != NULL )
1255 free(from);
1256}
1257
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001258
1259/******************************************************************************
1260 * _copy_registry [Internal]
1261 */
1262static void _copy_registry( LPKEYSTRUCT from, LPKEYSTRUCT to )
1263{
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001264 LPKEYSTRUCT lpxkey;
1265 int j;
1266 LPKEYVALUE valfrom;
1267
1268 from=from->nextsub;
1269 while (from) {
1270 lpxkey = _find_or_add_key(to,strdupW(from->keyname));
1271
1272 for (j=0;j<from->nrofvalues;j++) {
1273 LPWSTR name;
1274 LPBYTE data;
1275
1276 valfrom = from->values+j;
1277 name=valfrom->name;
1278 if (name) name=strdupW(name);
Alexandre Julliarda11d7b11998-03-01 20:05:02 +00001279 data=(LPBYTE)xmalloc(valfrom->len);
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001280 memcpy(data,valfrom->data,valfrom->len);
1281
1282 _find_or_add_value(
1283 lpxkey,
1284 name,
1285 valfrom->type,
1286 data,
1287 valfrom->len,
1288 valfrom->lastmodified
1289 );
1290 }
1291 _copy_registry(from,lpxkey);
1292 from = from->next;
1293 }
1294}
1295
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001296
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001297/* WINDOWS 95 REGISTRY LOADER */
1298/*
1299 * Structure of a win95 registry database.
1300 * main header:
1301 * 0 : "CREG" - magic
1302 * 4 : DWORD version
1303 * 8 : DWORD offset_of_RGDB_part
Alexandre Julliard02e90081998-01-04 17:49:09 +00001304 * 0C..0F: ? (someone fill in please)
1305 * 10: WORD number of RGDB blocks
1306 * 12: WORD ?
1307 * 14: WORD always 0000?
1308 * 16: WORD always 0001?
1309 * 18..1F: ? (someone fill in please)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001310 *
1311 * 20: RGKN_section:
1312 * header:
1313 * 0 : "RGKN" - magic
Alexandre Julliard02e90081998-01-04 17:49:09 +00001314 * 4 : DWORD offset to first RGDB section
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001315 * 8 : DWORD offset to the root record
Alexandre Julliard02e90081998-01-04 17:49:09 +00001316 * C..0x1B: ? (fill in)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001317 * 0x20 ... offset_of_RGDB_part: Disk Key Entry structures
1318 *
1319 * Disk Key Entry Structure:
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001320 * 00: DWORD - Free entry indicator(?)
1321 * 04: DWORD - Hash = sum of bytes of keyname
1322 * 08: DWORD - Root key indicator? unknown, but usually 0xFFFFFFFF on win95 systems
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001323 * 0C: DWORD - disk address of PreviousLevel Key.
1324 * 10: DWORD - disk address of Next Sublevel Key.
1325 * 14: DWORD - disk address of Next Key (on same level).
1326 * DKEP>18: WORD - Nr, Low Significant part.
1327 * 1A: WORD - Nr, High Significant part.
1328 *
1329 * The disk address always points to the nr part of the previous key entry
1330 * of the referenced key. Don't ask me why, or even if I got this correct
1331 * from staring at 1kg of hexdumps. (DKEP)
1332 *
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001333 * The High significant part of the structure seems to equal the number
1334 * of the RGDB section. The low significant part is a unique ID within
1335 * that RGDB section
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001336 *
1337 * There are two minor corrections to the position of that structure.
1338 * 1. If the address is xxx014 or xxx018 it will be aligned to xxx01c AND
1339 * the DKE reread from there.
1340 * 2. If the address is xxxFFx it will be aligned to (xxx+1)000.
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001341 * CPS - I have not experienced the above phenomenon in my registry files
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001342 *
1343 * RGDB_section:
1344 * 00: "RGDB" - magic
Alexandre Julliard02e90081998-01-04 17:49:09 +00001345 * 04: DWORD offset to next RGDB section
1346 * 08: DWORD ?
1347 * 0C: WORD always 000d?
1348 * 0E: WORD RGDB block number
1349 * 10: DWORD ? (equals value at offset 4 - value at offset 8)
1350 * 14..1F: ?
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001351 * 20.....: disk keys
1352 *
1353 * disk key:
1354 * 00: DWORD nextkeyoffset - offset to the next disk key structure
1355 * 08: WORD nrLS - low significant part of NR
1356 * 0A: WORD nrHS - high significant part of NR
1357 * 0C: DWORD bytesused - bytes used in this structure.
1358 * 10: WORD name_len - length of name in bytes. without \0
1359 * 12: WORD nr_of_values - number of values.
1360 * 14: char name[name_len] - name string. No \0.
1361 * 14+name_len: disk values
1362 * nextkeyoffset: ... next disk key
1363 *
1364 * disk value:
1365 * 00: DWORD type - value type (hmm, could be WORD too)
1366 * 04: DWORD - unknown, usually 0
1367 * 08: WORD namelen - length of Name. 0 means name=NULL
1368 * 0C: WORD datalen - length of Data.
1369 * 10: char name[namelen] - name, no \0
1370 * 10+namelen: BYTE data[datalen] - data, without \0 if string
1371 * 10+namelen+datalen: next values or disk key
1372 *
1373 * Disk keys are layed out flat ... But, sometimes, nrLS and nrHS are both
1374 * 0xFFFF, which means skipping over nextkeyoffset bytes (including this
1375 * structure) and reading another RGDB_section.
1376 * repeat until end of file.
1377 *
Alexandre Julliard02e90081998-01-04 17:49:09 +00001378 * An interesting relationship exists in RGDB_section. The value at offset
1379 * 10 equals the value at offset 4 minus the value at offset 8. I have no
1380 * idea at the moment what this means. (Kevin Cozens)
1381 *
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001382 * FIXME: this description needs some serious help, yes.
1383 */
1384
1385struct _w95keyvalue {
1386 unsigned long type;
1387 unsigned short datalen;
1388 char *name;
1389 unsigned char *data;
1390 unsigned long x1;
1391 int lastmodified;
1392};
1393
1394struct _w95key {
1395 char *name;
1396 int nrofvals;
1397 struct _w95keyvalue *values;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001398 struct _w95key *prevlvl;
1399 struct _w95key *nextsub;
1400 struct _w95key *next;
1401};
1402
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001403
1404struct _w95_info {
1405 char *rgknbuffer;
1406 int rgknsize;
1407 char *rgdbbuffer;
1408 int rgdbsize;
1409 int depth;
1410 int lastmodified;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001411};
1412
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001413
1414/******************************************************************************
1415 * _w95_processKey [Internal]
1416 */
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001417static LPKEYSTRUCT _w95_processKey ( LPKEYSTRUCT lpkey,
1418 int nrLS, int nrMS, struct _w95_info *info )
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001419
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001420{
1421 /* Disk Key Header structure (RGDB part) */
Alexandre Julliarda11d7b11998-03-01 20:05:02 +00001422 struct dkh {
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001423 unsigned long nextkeyoff;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001424 unsigned short nrLS;
1425 unsigned short nrMS;
1426 unsigned long bytesused;
1427 unsigned short keynamelen;
1428 unsigned short values;
1429 unsigned long xx1;
1430 /* keyname */
1431 /* disk key values or nothing */
1432 };
1433 /* Disk Key Value structure */
1434 struct dkv {
1435 unsigned long type;
1436 unsigned long x1;
1437 unsigned short valnamelen;
1438 unsigned short valdatalen;
1439 /* valname, valdata */
1440 };
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001441
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001442
1443 struct dkh dkh;
1444 int bytesread = 0;
1445 char *rgdbdata = info->rgdbbuffer;
1446 int nbytes = info->rgdbsize;
1447 char *curdata = rgdbdata;
1448 char *end = rgdbdata + nbytes;
1449 int off_next_rgdb;
1450 char *next = rgdbdata;
1451 int nrgdb, i;
1452 LPKEYSTRUCT lpxkey;
1453
1454 do {
1455 curdata = next;
1456 if (strncmp(curdata, "RGDB", 4)) return (NULL);
1457
1458 memcpy(&off_next_rgdb,curdata+4,4);
1459 next = curdata + off_next_rgdb;
1460 nrgdb = (int) *((short *)curdata + 7);
1461
1462 } while (nrgdb != nrMS && (next < end));
1463
1464 /* curdata now points to the start of the right RGDB section */
1465 curdata += 0x20;
1466
1467#define XREAD(whereto,len) \
David Gay6f0056d1999-04-11 12:00:15 +00001468 if ((curdata + len) <= end) {\
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001469 memcpy(whereto,curdata,len);\
1470 curdata+=len;\
1471 bytesread+=len;\
1472 }
1473
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001474 while (curdata < next) {
Marcus Meissnerf4f17191998-10-17 12:10:19 +00001475 struct dkh *xdkh = (struct dkh*)curdata;
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001476
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001477 bytesread += sizeof(dkh); /* FIXME... nextkeyoff? */
1478 if (xdkh->nrLS == nrLS) {
1479 memcpy(&dkh,xdkh,sizeof(dkh));
1480 curdata += sizeof(dkh);
1481 break;
1482 }
1483 curdata += xdkh->nextkeyoff;
1484 };
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001485
1486 if (dkh.nrLS != nrLS) return (NULL);
1487
Alexandre Julliarda0d77311998-09-13 16:32:00 +00001488 if (nrgdb != dkh.nrMS)
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001489 return (NULL);
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001490
Alexandre Julliarda11d7b11998-03-01 20:05:02 +00001491 assert((dkh.keynamelen<2) || curdata[0]);
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001492 lpxkey=_find_or_add_key(lpkey,strcvtA2W(curdata, dkh.keynamelen));
1493 curdata += dkh.keynamelen;
1494
1495 for (i=0;i< dkh.values; i++) {
1496 struct dkv dkv;
1497 LPBYTE data;
1498 int len;
1499 LPWSTR name;
1500
1501 XREAD(&dkv,sizeof(dkv));
1502
1503 name = strcvtA2W(curdata, dkv.valnamelen);
1504 curdata += dkv.valnamelen;
1505
1506 if ((1 << dkv.type) & UNICONVMASK) {
1507 data = (LPBYTE) strcvtA2W(curdata, dkv.valdatalen);
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00001508 len = 2*(dkv.valdatalen + 1);
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001509 } else {
1510 /* I don't think we want to NULL terminate all data */
1511 data = xmalloc(dkv.valdatalen);
1512 memcpy (data, curdata, dkv.valdatalen);
1513 len = dkv.valdatalen;
1514 }
1515
1516 curdata += dkv.valdatalen;
1517
1518 _find_or_add_value(
1519 lpxkey,
1520 name,
1521 dkv.type,
1522 data,
1523 len,
1524 info->lastmodified
1525 );
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001526 }
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001527 return (lpxkey);
1528}
1529
Alexandre Julliardf90efa91998-06-14 15:24:15 +00001530/******************************************************************************
1531 * _w95_walkrgkn [Internal]
1532 */
1533static void _w95_walkrgkn( LPKEYSTRUCT prevkey, char *off,
1534 struct _w95_info *info )
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001535
1536{
1537 /* Disk Key Entry structure (RGKN part) */
1538 struct dke {
1539 unsigned long x1;
1540 unsigned long x2;
1541 unsigned long x3;/*usually 0xFFFFFFFF */
1542 unsigned long prevlvl;
1543 unsigned long nextsub;
1544 unsigned long next;
1545 unsigned short nrLS;
1546 unsigned short nrMS;
1547 } *dke = (struct dke *)off;
1548 LPKEYSTRUCT lpxkey;
1549
1550 if (dke == NULL) {
1551 dke = (struct dke *) ((char *)info->rgknbuffer);
1552 }
1553
1554 lpxkey = _w95_processKey(prevkey, dke->nrLS, dke->nrMS, info);
1555 /* XXX <-- This is a hack*/
1556 if (!lpxkey) {
1557 lpxkey = prevkey;
1558 }
1559
1560 if (dke->nextsub != -1 &&
1561 ((dke->nextsub - 0x20) < info->rgknsize)
1562 && (dke->nextsub > 0x20)) {
1563
1564 _w95_walkrgkn(lpxkey,
1565 info->rgknbuffer + dke->nextsub - 0x20,
1566 info);
1567 }
1568
1569 if (dke->next != -1 &&
1570 ((dke->next - 0x20) < info->rgknsize) &&
1571 (dke->next > 0x20)) {
1572 _w95_walkrgkn(prevkey,
1573 info->rgknbuffer + dke->next - 0x20,
1574 info);
1575 }
1576
1577 return;
1578}
1579
Alexandre Julliardf90efa91998-06-14 15:24:15 +00001580
1581/******************************************************************************
1582 * _w95_loadreg [Internal]
1583 */
1584static void _w95_loadreg( char* fn, LPKEYSTRUCT lpkey )
1585{
Alexandre Julliarda3960291999-02-26 11:11:13 +00001586 HFILE hfd;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001587 char magic[5];
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001588 unsigned long where,version,rgdbsection,end;
1589 struct _w95_info info;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001590 OFSTRUCT ofs;
Alexandre Julliard8bbf8181996-09-13 16:50:47 +00001591 BY_HANDLE_FILE_INFORMATION hfdinfo;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001592
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001593 TRACE_(reg)("Loading Win95 registry database '%s'\n",fn);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001594 hfd=OpenFile(fn,&ofs,OF_READ);
1595 if (hfd==HFILE_ERROR)
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001596 return;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001597 magic[4]=0;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001598 if (4!=_lread(hfd,magic,4))
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001599 return;
1600 if (strcmp(magic,"CREG")) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001601 WARN_(reg)("%s is not a w95 registry.\n",fn);
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001602 return;
1603 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00001604 if (4!=_lread(hfd,&version,4))
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001605 return;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001606 if (4!=_lread(hfd,&rgdbsection,4))
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001607 return;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001608 if (-1==_llseek(hfd,0x20,SEEK_SET))
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001609 return;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001610 if (4!=_lread(hfd,magic,4))
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001611 return;
1612 if (strcmp(magic,"RGKN")) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001613 WARN_(reg)("second IFF header not RGKN, but %s\n", magic);
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001614 return;
1615 }
1616
1617 /* STEP 1: Keylink structures */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001618 if (-1==_llseek(hfd,0x40,SEEK_SET))
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001619 return;
1620 where = 0x40;
1621 end = rgdbsection;
1622
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001623 info.rgknsize = end - where;
1624 info.rgknbuffer = (char*)xmalloc(info.rgknsize);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001625 if (info.rgknsize != _lread(hfd,info.rgknbuffer,info.rgknsize))
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001626 return;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001627
Alexandre Julliard8bbf8181996-09-13 16:50:47 +00001628 if (!GetFileInformationByHandle(hfd,&hfdinfo))
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001629 return;
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001630
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001631 end = hfdinfo.nFileSizeLow;
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001632 info.lastmodified = DOSFS_FileTimeToUnixTime(&hfdinfo.ftLastWriteTime,NULL);
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001633
Alexandre Julliarda3960291999-02-26 11:11:13 +00001634 if (-1==_llseek(hfd,rgdbsection,SEEK_SET))
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001635 return;
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001636
1637 info.rgdbbuffer = (char*)xmalloc(end-rgdbsection);
1638 info.rgdbsize = end - rgdbsection;
1639
Alexandre Julliarda3960291999-02-26 11:11:13 +00001640 if (info.rgdbsize !=_lread(hfd,info.rgdbbuffer,info.rgdbsize))
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001641 return;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001642 _lclose(hfd);
Alexandre Julliard02e90081998-01-04 17:49:09 +00001643
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001644 _w95_walkrgkn(lpkey, NULL, &info);
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001645
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001646 free (info.rgdbbuffer);
1647 free (info.rgknbuffer);
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001648}
1649
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001650
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001651/* WINDOWS 31 REGISTRY LOADER, supplied by Tor Sjøwall, tor@sn.no */
1652
1653/*
1654 reghack - windows 3.11 registry data format demo program.
1655
1656 The reg.dat file has 3 parts, a header, a table of 8-byte entries that is
1657 a combined hash table and tree description, and finally a text table.
1658
1659 The header is obvious from the struct header. The taboff1 and taboff2
1660 fields are always 0x20, and their usage is unknown.
1661
1662 The 8-byte entry table has various entry types.
1663
1664 tabent[0] is a root index. The second word has the index of the root of
1665 the directory.
1666 tabent[1..hashsize] is a hash table. The first word in the hash entry is
1667 the index of the key/value that has that hash. Data with the same
1668 hash value are on a circular list. The other three words in the
1669 hash entry are always zero.
1670 tabent[hashsize..tabcnt] is the tree structure. There are two kinds of
1671 entry: dirent and keyent/valent. They are identified by context.
1672 tabent[freeidx] is the first free entry. The first word in a free entry
1673 is the index of the next free entry. The last has 0 as a link.
1674 The other three words in the free list are probably irrelevant.
1675
1676 Entries in text table are preceeded by a word at offset-2. This word
1677 has the value (2*index)+1, where index is the referring keyent/valent
1678 entry in the table. I have no suggestion for the 2* and the +1.
1679 Following the word, there are N bytes of data, as per the keyent/valent
1680 entry length. The offset of the keyent/valent entry is from the start
1681 of the text table to the first data byte.
1682
1683 This information is not available from Microsoft. The data format is
1684 deduced from the reg.dat file by me. Mistakes may
1685 have been made. I claim no rights and give no guarantees for this program.
1686
1687 Tor Sjøwall, tor@sn.no
1688*/
1689
1690/* reg.dat header format */
1691struct _w31_header {
1692 char cookie[8]; /* 'SHCC3.10' */
1693 unsigned long taboff1; /* offset of hash table (??) = 0x20 */
1694 unsigned long taboff2; /* offset of index table (??) = 0x20 */
1695 unsigned long tabcnt; /* number of entries in index table */
1696 unsigned long textoff; /* offset of text part */
1697 unsigned long textsize; /* byte size of text part */
1698 unsigned short hashsize; /* hash size */
1699 unsigned short freeidx; /* free index */
1700};
1701
1702/* generic format of table entries */
1703struct _w31_tabent {
1704 unsigned short w0, w1, w2, w3;
1705};
1706
1707/* directory tabent: */
1708struct _w31_dirent {
1709 unsigned short sibling_idx; /* table index of sibling dirent */
1710 unsigned short child_idx; /* table index of child dirent */
1711 unsigned short key_idx; /* table index of key keyent */
1712 unsigned short value_idx; /* table index of value valent */
1713};
1714
1715/* key tabent: */
1716struct _w31_keyent {
1717 unsigned short hash_idx; /* hash chain index for string */
1718 unsigned short refcnt; /* reference count */
1719 unsigned short length; /* length of string */
1720 unsigned short string_off; /* offset of string in text table */
1721};
1722
1723/* value tabent: */
1724struct _w31_valent {
1725 unsigned short hash_idx; /* hash chain index for string */
1726 unsigned short refcnt; /* reference count */
1727 unsigned short length; /* length of string */
1728 unsigned short string_off; /* offset of string in text table */
1729};
1730
1731/* recursive helper function to display a directory tree */
1732void
1733__w31_dumptree( unsigned short idx,
1734 unsigned char *txt,
1735 struct _w31_tabent *tab,
1736 struct _w31_header *head,
1737 LPKEYSTRUCT lpkey,
1738 time_t lastmodified,
1739 int level
1740) {
1741 struct _w31_dirent *dir;
1742 struct _w31_keyent *key;
1743 struct _w31_valent *val;
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00001744 LPKEYSTRUCT xlpkey = NULL;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001745 LPWSTR name,value;
1746 static char tail[400];
1747
1748 while (idx!=0) {
1749 dir=(struct _w31_dirent*)&tab[idx];
1750
1751 if (dir->key_idx) {
1752 key = (struct _w31_keyent*)&tab[dir->key_idx];
1753
1754 memcpy(tail,&txt[key->string_off],key->length);
1755 tail[key->length]='\0';
1756 /* all toplevel entries AND the entries in the
1757 * toplevel subdirectory belong to \SOFTWARE\Classes
1758 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001759 if (!level && !lstrcmpA(tail,".classes")) {
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001760 __w31_dumptree(dir->child_idx,txt,tab,head,lpkey,lastmodified,level+1);
1761 idx=dir->sibling_idx;
1762 continue;
1763 }
Alexandre Julliarde658d821997-11-30 17:45:40 +00001764 name=strdupA2W(tail);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001765
1766 xlpkey=_find_or_add_key(lpkey,name);
1767
1768 /* only add if leaf node or valued node */
1769 if (dir->value_idx!=0||dir->child_idx==0) {
1770 if (dir->value_idx) {
1771 val=(struct _w31_valent*)&tab[dir->value_idx];
1772 memcpy(tail,&txt[val->string_off],val->length);
1773 tail[val->length]='\0';
Alexandre Julliarde658d821997-11-30 17:45:40 +00001774 value=strdupA2W(tail);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001775 _find_or_add_value(xlpkey,NULL,REG_SZ,(LPBYTE)value,lstrlenW(value)*2+2,lastmodified);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001776 }
1777 }
1778 } else {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001779 TRACE_(reg)("strange: no directory key name, idx=%04x\n", idx);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001780 }
1781 __w31_dumptree(dir->child_idx,txt,tab,head,xlpkey,lastmodified,level+1);
1782 idx=dir->sibling_idx;
1783 }
1784}
1785
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001786
1787/******************************************************************************
1788 * _w31_loadreg [Internal]
1789 */
Juergen Schmiedebc2b771998-11-14 18:59:30 +00001790void _w31_loadreg(void) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001791 HFILE hf;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001792 struct _w31_header head;
1793 struct _w31_tabent *tab;
1794 unsigned char *txt;
1795 int len;
1796 OFSTRUCT ofs;
1797 BY_HANDLE_FILE_INFORMATION hfinfo;
1798 time_t lastmodified;
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001799 LPKEYSTRUCT lpkey;
1800
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001801 TRACE_(reg)("(void)\n");
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001802
Alexandre Julliarda3960291999-02-26 11:11:13 +00001803 hf = OpenFile("reg.dat",&ofs,OF_READ);
1804 if (hf==HFILE_ERROR)
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001805 return;
1806
1807 /* read & dump header */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001808 if (sizeof(head)!=_lread(hf,&head,sizeof(head))) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001809 ERR_(reg)("reg.dat is too short.\n");
Alexandre Julliarda3960291999-02-26 11:11:13 +00001810 _lclose(hf);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001811 return;
1812 }
1813 if (memcmp(head.cookie, "SHCC3.10", sizeof(head.cookie))!=0) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001814 ERR_(reg)("reg.dat has bad signature.\n");
Alexandre Julliarda3960291999-02-26 11:11:13 +00001815 _lclose(hf);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001816 return;
1817 }
1818
1819 len = head.tabcnt * sizeof(struct _w31_tabent);
1820 /* read and dump index table */
1821 tab = xmalloc(len);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001822 if (len!=_lread(hf,tab,len)) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001823 ERR_(reg)("couldn't read %d bytes.\n",len);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001824 free(tab);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001825 _lclose(hf);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001826 return;
1827 }
1828
1829 /* read text */
1830 txt = xmalloc(head.textsize);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001831 if (-1==_llseek(hf,head.textoff,SEEK_SET)) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001832 ERR_(reg)("couldn't seek to textblock.\n");
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001833 free(tab);
1834 free(txt);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001835 _lclose(hf);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001836 return;
1837 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00001838 if (head.textsize!=_lread(hf,txt,head.textsize)) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001839 ERR_(reg)("textblock too short (%d instead of %ld).\n",len,head.textsize);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001840 free(tab);
1841 free(txt);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001842 _lclose(hf);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001843 return;
1844 }
1845
1846 if (!GetFileInformationByHandle(hf,&hfinfo)) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001847 ERR_(reg)("GetFileInformationByHandle failed?.\n");
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001848 free(tab);
1849 free(txt);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001850 _lclose(hf);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001851 return;
1852 }
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001853 lastmodified = DOSFS_FileTimeToUnixTime(&hfinfo.ftLastWriteTime,NULL);
Alexandre Julliarda845b881998-06-01 10:44:35 +00001854 lpkey = lookup_hkey(HKEY_CLASSES_ROOT);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001855 __w31_dumptree(tab[0].w1,txt,tab,&head,lpkey,lastmodified,0);
1856 free(tab);
1857 free(txt);
Alexandre Julliarda3960291999-02-26 11:11:13 +00001858 _lclose(hf);
Alexandre Julliardda0cfb31996-12-01 17:17:47 +00001859 return;
1860}
1861
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00001862
1863/**********************************************************************************
1864 * SHELL_LoadRegistry [Internal]
1865 */
1866void SHELL_LoadRegistry( void )
1867{
Alexandre Julliard154c99b1999-04-25 12:41:36 +00001868 char *fn, *home;
Sylvain St.Germaine5332221999-04-10 16:46:15 +00001869 LPKEYSTRUCT lpkey, HKCU, HKU, HKLM;
1870 HKEY hkey;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001871
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001872 TRACE_(reg)("(void)\n");
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001873
Sylvain St.Germaine5332221999-04-10 16:46:15 +00001874 HKCU = lookup_hkey(HKEY_CURRENT_USER);
1875 HKU = lookup_hkey(HKEY_USERS);
1876 HKLM = lookup_hkey(HKEY_LOCAL_MACHINE);
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001877
Sylvain St.Germaine5332221999-04-10 16:46:15 +00001878 /* Load windows 3.1 entries */
1879 _w31_loadreg();
1880 /* Load windows 95 entries */
1881 _w95_loadreg("C:\\system.1st", HKLM);
1882 _w95_loadreg("system.dat", HKLM);
1883 _w95_loadreg("user.dat", HKU);
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001884
Sylvain St.Germaine5332221999-04-10 16:46:15 +00001885 /*
Marcus Meissneradf8a0c1999-06-12 08:18:38 +00001886 * Load the global HKU hive directly from sysconfdir
Sylvain St.Germaine5332221999-04-10 16:46:15 +00001887 */
1888 _wine_loadreg( HKU, SAVE_USERS_DEFAULT, 0);
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001889
Sylvain St.Germaine5332221999-04-10 16:46:15 +00001890 /*
Marcus Meissneradf8a0c1999-06-12 08:18:38 +00001891 * Load the global machine defaults directly form sysconfdir
Sylvain St.Germaine5332221999-04-10 16:46:15 +00001892 */
1893 _wine_loadreg( HKLM, SAVE_LOCAL_MACHINE_DEFAULT, 0);
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001894
Sylvain St.Germaine5332221999-04-10 16:46:15 +00001895 /*
1896 * Load the user saved registries
1897 */
Alexandre Julliard154c99b1999-04-25 12:41:36 +00001898 if ((home = getenv( "HOME" )))
Sylvain St.Germaine5332221999-04-10 16:46:15 +00001899 {
1900 /*
1901 * Load user's personal versions of global HKU/.Default keys
1902 */
1903 fn=(char*)xmalloc(
Alexandre Julliard154c99b1999-04-25 12:41:36 +00001904 strlen(home)+
Sylvain St.Germaine5332221999-04-10 16:46:15 +00001905 strlen(WINE_PREFIX)+
1906 strlen(SAVE_LOCAL_USERS_DEFAULT)+2);
Nathan Zorichbd3771c1999-03-14 15:12:48 +00001907
Alexandre Julliard154c99b1999-04-25 12:41:36 +00001908 strcpy(fn, home);
Sylvain St.Germaine5332221999-04-10 16:46:15 +00001909 strcat(fn, WINE_PREFIX"/"SAVE_LOCAL_USERS_DEFAULT);
1910 _wine_loadreg(HKU, fn, REG_OPTION_TAINTED);
1911 free(fn);
Nathan Zorichbd3771c1999-03-14 15:12:48 +00001912
Sylvain St.Germaine5332221999-04-10 16:46:15 +00001913 /*
1914 * Load HKCU, attempt to get the registry location from the config
1915 * file first, if exist, load and keep going.
1916 */
1917 fn = xmalloc( MAX_PATHNAME_LEN );
1918 if ( PROFILE_GetWineIniString(
1919 "Registry",
1920 "UserFileName",
1921 "",
1922 fn,
1923 MAX_PATHNAME_LEN - 1))
1924 {
1925 _wine_loadreg(HKCU,fn,0);
1926 }
1927 free (fn);
Nathan Zorichbd3771c1999-03-14 15:12:48 +00001928
Sylvain St.Germaine5332221999-04-10 16:46:15 +00001929 fn=(char*)xmalloc(
Alexandre Julliard154c99b1999-04-25 12:41:36 +00001930 strlen(home)+
Sylvain St.Germaine5332221999-04-10 16:46:15 +00001931 strlen(WINE_PREFIX)+
1932 strlen(SAVE_CURRENT_USER)+2);
Nathan Zorichbd3771c1999-03-14 15:12:48 +00001933
Alexandre Julliard154c99b1999-04-25 12:41:36 +00001934 strcpy(fn, home);
Sylvain St.Germaine5332221999-04-10 16:46:15 +00001935 strcat(fn, WINE_PREFIX"/"SAVE_CURRENT_USER);
1936 _wine_loadreg(HKCU, fn, REG_OPTION_TAINTED);
1937 free(fn);
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001938
Sylvain St.Germaine5332221999-04-10 16:46:15 +00001939 /*
1940 * Load HKLM, attempt to get the registry location from the config
1941 * file first, if exist, load and keep going.
1942 */
1943 fn = xmalloc ( MAX_PATHNAME_LEN);
1944 if ( PROFILE_GetWineIniString(
1945 "Registry",
1946 "LocalMachineFileName",
1947 "",
1948 fn,
1949 MAX_PATHNAME_LEN - 1))
1950 {
Alexandre Julliard154c99b1999-04-25 12:41:36 +00001951 _wine_loadreg(HKLM, fn, 0);
1952 }
Sylvain St.Germaine5332221999-04-10 16:46:15 +00001953 free(fn);
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00001954
Sylvain St.Germaine5332221999-04-10 16:46:15 +00001955 fn=(char*)xmalloc(
Alexandre Julliard154c99b1999-04-25 12:41:36 +00001956 strlen(home)+
Sylvain St.Germaine5332221999-04-10 16:46:15 +00001957 strlen(WINE_PREFIX)+
1958 strlen(SAVE_LOCAL_MACHINE)+2);
1959
Alexandre Julliard154c99b1999-04-25 12:41:36 +00001960 strcpy(fn,home);
Sylvain St.Germaine5332221999-04-10 16:46:15 +00001961 strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_MACHINE);
1962 _wine_loadreg(HKLM, fn, REG_OPTION_TAINTED);
1963 free(fn);
1964 }
1965 else
1966 {
Patrik Stridvall1ed4ecf1999-06-26 14:58:24 +00001967 WARN_(reg)("Failed to get homedirectory of UID %ld.\n",(long) getuid());
Sylvain St.Germaine5332221999-04-10 16:46:15 +00001968 }
1969
1970 /*
1971 * Obtain the handle of the HKU\.Default key.
1972 * in order to copy HKU\.Default\* onto HKEY_CURRENT_USER
1973 */
1974 RegCreateKey16(HKEY_USERS,".Default",&hkey);
1975 lpkey = lookup_hkey(hkey);
1976 if(!lpkey)
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001977 WARN_(reg)("Could not create global user default key\n");
Sylvain St.Germaine5332221999-04-10 16:46:15 +00001978 else
1979 _copy_registry(lpkey, HKCU );
1980
1981 RegCloseKey(hkey);
1982
1983 /*
1984 * Since HKU is built from the global HKU and the local user HKU file we must
1985 * flush the HKU tree we have built at this point otherwise the part brought
1986 * in from the global HKU is saved into the local HKU. To avoid this
1987 * useless dupplication of HKU keys we reread the local HKU key.
1988 */
1989
1990 /* Allways flush the HKU hive and reload it only with user's personal HKU */
1991 _flush_registry(HKU);
1992
1993 /* Reload user's local HKU hive */
Alexandre Julliard154c99b1999-04-25 12:41:36 +00001994 if (home)
1995 {
1996 fn=(char*)xmalloc( strlen(home) + strlen(WINE_PREFIX)
1997 + strlen(SAVE_LOCAL_USERS_DEFAULT) + 2);
1998
1999 strcpy(fn,home);
2000 strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_USERS_DEFAULT);
Sylvain St.Germaine5332221999-04-10 16:46:15 +00002001
Alexandre Julliard154c99b1999-04-25 12:41:36 +00002002 _wine_loadreg( HKU, fn, REG_OPTION_TAINTED);
Sylvain St.Germaine5332221999-04-10 16:46:15 +00002003
Alexandre Julliard154c99b1999-04-25 12:41:36 +00002004 free(fn);
2005 }
Sylvain St.Germaine5332221999-04-10 16:46:15 +00002006
2007 /*
2008 * Make sure the update mode is there
2009 */
2010 if (ERROR_SUCCESS==RegCreateKey16(HKEY_CURRENT_USER,KEY_REGISTRY,&hkey))
2011 {
2012 DWORD junk,type,len;
2013 char data[5];
2014
2015 len=4;
2016 if (( RegQueryValueExA(
2017 hkey,
2018 VAL_SAVEUPDATED,
2019 &junk,
2020 &type,
2021 data,
2022 &len) != ERROR_SUCCESS) || (type != REG_SZ))
2023 {
2024 RegSetValueExA(hkey,VAL_SAVEUPDATED,0,REG_SZ,"yes",4);
2025 }
2026
2027 RegCloseKey(hkey);
2028 }
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002029}
2030
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002031
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00002032/********************* API FUNCTIONS ***************************************/
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002033/*
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00002034 * Open Keys.
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002035 *
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00002036 * All functions are stubs to RegOpenKeyEx32W where all the
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002037 * magic happens.
2038 *
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002039 * Callpath:
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00002040 * RegOpenKey16 -> RegOpenKey32A -> RegOpenKeyEx32A \
2041 * RegOpenKey32W -> RegOpenKeyEx32W
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002042 */
2043
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002044
2045/******************************************************************************
2046 * RegOpenKeyEx32W [ADVAPI32.150]
2047 * Opens the specified key
2048 *
2049 * Unlike RegCreateKeyEx, this does not create the key if it does not exist.
2050 *
2051 * PARAMS
2052 * hkey [I] Handle of open key
2053 * lpszSubKey [I] Name of subkey to open
2054 * dwReserved [I] Reserved - must be zero
2055 * samDesired [I] Security access mask
2056 * retkey [O] Address of handle of open key
2057 *
2058 * RETURNS
2059 * Success: ERROR_SUCCESS
2060 * Failure: Error code
2061 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002062DWORD WINAPI RegOpenKeyExW( HKEY hkey, LPCWSTR lpszSubKey, DWORD dwReserved,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002063 REGSAM samDesired, LPHKEY retkey )
2064{
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002065 LPKEYSTRUCT lpNextKey,lpxkey;
2066 LPWSTR *wps;
2067 int wpc,i;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002068
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002069 TRACE_(reg)("(0x%x,%s,%ld,%lx,%p)\n", hkey,debugstr_w(lpszSubKey),dwReserved,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002070 samDesired,retkey);
2071
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002072 lpNextKey = lookup_hkey( hkey );
2073 if (!lpNextKey)
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002074 return ERROR_INVALID_HANDLE;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002075
2076 if (!lpszSubKey || !*lpszSubKey) {
2077 /* Either NULL or pointer to empty string, so return a new handle
2078 to the original hkey */
Alexandre Julliard85ed45e1998-08-22 19:03:56 +00002079 currenthandle += 2;
2080 add_handle(currenthandle,lpNextKey,samDesired);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002081 *retkey=currenthandle;
2082 return ERROR_SUCCESS;
2083 }
2084
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002085 if (lpszSubKey[0] == '\\') {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002086 WARN_(reg)("Subkey %s must not begin with backslash.\n",debugstr_w(lpszSubKey));
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002087 return ERROR_BAD_PATHNAME;
2088 }
2089
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002090 split_keypath(lpszSubKey,&wps,&wpc);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002091 i = 0;
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00002092 while ((i<wpc) && (wps[i][0]=='\0')) i++;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002093 lpxkey = lpNextKey;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002094
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002095 while (wps[i]) {
2096 lpxkey=lpNextKey->nextsub;
2097 while (lpxkey) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002098 if (!lstrcmpiW(wps[i],lpxkey->keyname)) {
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002099 break;
2100 }
2101 lpxkey=lpxkey->next;
2102 }
2103
2104 if (!lpxkey) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002105 TRACE_(reg)("Could not find subkey %s\n",debugstr_w(wps[i]));
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002106 FREE_KEY_PATH;
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002107 return ERROR_FILE_NOT_FOUND;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002108 }
2109 i++;
2110 lpNextKey = lpxkey;
2111 }
2112
Alexandre Julliard85ed45e1998-08-22 19:03:56 +00002113 currenthandle += 2;
2114 add_handle(currenthandle,lpxkey,samDesired);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002115 *retkey = currenthandle;
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002116 TRACE_(reg)(" Returning %x\n", currenthandle);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002117 FREE_KEY_PATH;
2118 return ERROR_SUCCESS;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002119}
2120
2121
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002122/******************************************************************************
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002123 * RegOpenKeyEx32A [ADVAPI32.149]
2124 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002125DWORD WINAPI RegOpenKeyExA( HKEY hkey, LPCSTR lpszSubKey, DWORD dwReserved,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002126 REGSAM samDesired, LPHKEY retkey )
2127{
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002128 LPWSTR lpszSubKeyW = strdupA2W(lpszSubKey);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002129 DWORD ret;
2130
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002131 TRACE_(reg)("(%x,%s,%ld,%lx,%p)\n",hkey,debugstr_a(lpszSubKey),dwReserved,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002132 samDesired,retkey);
Alexandre Julliarda3960291999-02-26 11:11:13 +00002133 ret = RegOpenKeyExW( hkey, lpszSubKeyW, dwReserved, samDesired, retkey );
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002134 free(lpszSubKeyW);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002135 return ret;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002136}
2137
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002138
2139/******************************************************************************
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002140 * RegOpenKey32W [ADVAPI32.151]
2141 *
2142 * PARAMS
2143 * hkey [I] Handle of open key
2144 * lpszSubKey [I] Address of name of subkey to open
2145 * retkey [O] Address of handle of open key
2146 *
2147 * RETURNS
2148 * Success: ERROR_SUCCESS
2149 * Failure: Error code
2150 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002151DWORD WINAPI RegOpenKeyW( HKEY hkey, LPCWSTR lpszSubKey, LPHKEY retkey )
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002152{
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002153 TRACE_(reg)("(%x,%s,%p)\n",hkey,debugstr_w(lpszSubKey),retkey);
Alexandre Julliarda3960291999-02-26 11:11:13 +00002154 return RegOpenKeyExW( hkey, lpszSubKey, 0, KEY_ALL_ACCESS, retkey );
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002155}
2156
2157
2158/******************************************************************************
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002159 * RegOpenKey32A [ADVAPI32.148]
2160 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002161DWORD WINAPI RegOpenKeyA( HKEY hkey, LPCSTR lpszSubKey, LPHKEY retkey )
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002162{
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002163 DWORD ret;
2164 LPWSTR lpszSubKeyW = strdupA2W(lpszSubKey);
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002165 TRACE_(reg)("(%x,%s,%p)\n",hkey,debugstr_a(lpszSubKey),retkey);
Alexandre Julliarda3960291999-02-26 11:11:13 +00002166 ret = RegOpenKeyW( hkey, lpszSubKeyW, retkey );
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002167 free(lpszSubKeyW);
2168 return ret;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002169}
2170
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002171
2172/******************************************************************************
2173 * RegOpenKey16 [SHELL.1] [KERNEL.217]
2174 */
2175DWORD WINAPI RegOpenKey16( HKEY hkey, LPCSTR lpszSubKey, LPHKEY retkey )
2176{
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002177 TRACE_(reg)("(%x,%s,%p)\n",hkey,debugstr_a(lpszSubKey),retkey);
Alexandre Julliarda3960291999-02-26 11:11:13 +00002178 return RegOpenKeyA( hkey, lpszSubKey, retkey );
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002179}
2180
2181
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002182/*
2183 * Create keys
2184 *
2185 * All those functions convert their respective
2186 * arguments and call RegCreateKeyExW at the end.
2187 *
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002188 * We stay away from the Ex functions as long as possible because there are
2189 * differences in the return values
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002190 *
2191 * Callpath:
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002192 * RegCreateKeyEx32A \
2193 * RegCreateKey16 -> RegCreateKey32A -> RegCreateKey32W -> RegCreateKeyEx32W
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002194 */
2195
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002196
2197/******************************************************************************
2198 * RegCreateKeyEx32W [ADVAPI32.131]
2199 *
2200 * PARAMS
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002201 * hkey [I] Handle of an open key
2202 * lpszSubKey [I] Address of subkey name
2203 * dwReserved [I] Reserved - must be 0
2204 * lpszClass [I] Address of class string
2205 * fdwOptions [I] Special options flag
2206 * samDesired [I] Desired security access
2207 * lpSecAttribs [I] Address of key security structure
2208 * retkey [O] Address of buffer for opened handle
2209 * lpDispos [O] Receives REG_CREATED_NEW_KEY or REG_OPENED_EXISTING_KEY
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002210 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002211DWORD WINAPI RegCreateKeyExW( HKEY hkey, LPCWSTR lpszSubKey,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002212 DWORD dwReserved, LPWSTR lpszClass,
2213 DWORD fdwOptions, REGSAM samDesired,
2214 LPSECURITY_ATTRIBUTES lpSecAttribs,
2215 LPHKEY retkey, LPDWORD lpDispos )
2216{
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002217 LPKEYSTRUCT *lplpPrevKey,lpNextKey,lpxkey;
2218 LPWSTR *wps;
2219 int wpc,i;
2220
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002221 TRACE_(reg)("(%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n", hkey,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002222 debugstr_w(lpszSubKey), dwReserved, debugstr_w(lpszClass),
2223 fdwOptions, samDesired, lpSecAttribs, retkey, lpDispos);
2224
2225 lpNextKey = lookup_hkey(hkey);
2226 if (!lpNextKey)
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002227 return ERROR_INVALID_HANDLE;
2228
2229 /* Check for valid options */
2230 switch(fdwOptions) {
2231 case REG_OPTION_NON_VOLATILE:
2232 case REG_OPTION_VOLATILE:
2233 case REG_OPTION_BACKUP_RESTORE:
2234 break;
2235 default:
2236 return ERROR_INVALID_PARAMETER;
2237 }
2238
2239 /* Sam has to be a combination of the following */
2240 if (!(samDesired &
2241 (KEY_ALL_ACCESS | KEY_CREATE_LINK | KEY_CREATE_SUB_KEY |
2242 KEY_ENUMERATE_SUB_KEYS | KEY_EXECUTE | KEY_NOTIFY |
2243 KEY_QUERY_VALUE | KEY_READ | KEY_SET_VALUE | KEY_WRITE)))
2244 return ERROR_INVALID_PARAMETER;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002245
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002246 if (!lpszSubKey || !*lpszSubKey) {
Alexandre Julliard85ed45e1998-08-22 19:03:56 +00002247 currenthandle += 2;
2248 add_handle(currenthandle,lpNextKey,samDesired);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002249 *retkey=currenthandle;
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002250 TRACE_(reg)("Returning %x\n", currenthandle);
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00002251 lpNextKey->flags|=REG_OPTION_TAINTED;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002252 return ERROR_SUCCESS;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002253 }
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002254
Alexandre Julliarda845b881998-06-01 10:44:35 +00002255 if (lpszSubKey[0] == '\\') {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002256 WARN_(reg)("Subkey %s must not begin with backslash.\n",debugstr_w(lpszSubKey));
Alexandre Julliarda845b881998-06-01 10:44:35 +00002257 return ERROR_BAD_PATHNAME;
2258 }
2259
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002260 split_keypath(lpszSubKey,&wps,&wpc);
2261 i = 0;
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00002262 while ((i<wpc) && (wps[i][0]=='\0')) i++;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002263 lpxkey = lpNextKey;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00002264 while (wps[i]) {
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002265 lpxkey=lpNextKey->nextsub;
2266 while (lpxkey) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002267 if (!lstrcmpiW(wps[i],lpxkey->keyname))
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002268 break;
2269 lpxkey=lpxkey->next;
2270 }
2271 if (!lpxkey)
2272 break;
2273 i++;
2274 lpNextKey = lpxkey;
2275 }
2276 if (lpxkey) {
Alexandre Julliard85ed45e1998-08-22 19:03:56 +00002277 currenthandle += 2;
2278 add_handle(currenthandle,lpxkey,samDesired);
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00002279 lpxkey->flags |= REG_OPTION_TAINTED;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002280 *retkey = currenthandle;
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002281 TRACE_(reg)("Returning %x\n", currenthandle);
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00002282 if (lpDispos)
2283 *lpDispos = REG_OPENED_EXISTING_KEY;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002284 FREE_KEY_PATH;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002285 return ERROR_SUCCESS;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002286 }
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002287
2288 /* Good. Now the hard part */
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00002289 while (wps[i]) {
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002290 lplpPrevKey = &(lpNextKey->nextsub);
2291 lpxkey = *lplpPrevKey;
2292 while (lpxkey) {
2293 lplpPrevKey = &(lpxkey->next);
2294 lpxkey = *lplpPrevKey;
2295 }
2296 *lplpPrevKey=malloc(sizeof(KEYSTRUCT));
2297 if (!*lplpPrevKey) {
2298 FREE_KEY_PATH;
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002299 TRACE_(reg)("Returning OUTOFMEMORY\n");
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002300 return ERROR_OUTOFMEMORY;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002301 }
2302 memset(*lplpPrevKey,'\0',sizeof(KEYSTRUCT));
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002303 TRACE_(reg)("Adding %s\n", debugstr_w(wps[i]));
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002304 (*lplpPrevKey)->keyname = strdupW(wps[i]);
2305 (*lplpPrevKey)->next = NULL;
2306 (*lplpPrevKey)->nextsub = NULL;
2307 (*lplpPrevKey)->values = NULL;
2308 (*lplpPrevKey)->nrofvalues = 0;
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00002309 (*lplpPrevKey)->flags = REG_OPTION_TAINTED;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002310 if (lpszClass)
2311 (*lplpPrevKey)->class = strdupW(lpszClass);
2312 else
2313 (*lplpPrevKey)->class = NULL;
2314 lpNextKey = *lplpPrevKey;
2315 i++;
2316 }
Alexandre Julliard85ed45e1998-08-22 19:03:56 +00002317 currenthandle += 2;
2318 add_handle(currenthandle,lpNextKey,samDesired);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002319
2320 /*FIXME: flag handling correct? */
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00002321 lpNextKey->flags= fdwOptions |REG_OPTION_TAINTED;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002322 if (lpszClass)
2323 lpNextKey->class = strdupW(lpszClass);
2324 else
2325 lpNextKey->class = NULL;
2326 *retkey = currenthandle;
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002327 TRACE_(reg)("Returning %x\n", currenthandle);
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00002328 if (lpDispos)
2329 *lpDispos = REG_CREATED_NEW_KEY;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002330 FREE_KEY_PATH;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002331 return ERROR_SUCCESS;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002332}
2333
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002334
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002335/******************************************************************************
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002336 * RegCreateKeyEx32A [ADVAPI32.130]
2337 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002338DWORD WINAPI RegCreateKeyExA( HKEY hkey, LPCSTR lpszSubKey, DWORD dwReserved,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002339 LPSTR lpszClass, DWORD fdwOptions,
2340 REGSAM samDesired,
2341 LPSECURITY_ATTRIBUTES lpSecAttribs,
2342 LPHKEY retkey, LPDWORD lpDispos )
2343{
2344 LPWSTR lpszSubKeyW, lpszClassW;
2345 DWORD ret;
2346
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002347 TRACE_(reg)("(%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n",hkey,debugstr_a(lpszSubKey),
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002348 dwReserved,debugstr_a(lpszClass),fdwOptions,samDesired,lpSecAttribs,
2349 retkey,lpDispos);
2350
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002351 lpszSubKeyW = lpszSubKey?strdupA2W(lpszSubKey):NULL;
2352 lpszClassW = lpszClass?strdupA2W(lpszClass):NULL;
2353
Alexandre Julliarda3960291999-02-26 11:11:13 +00002354 ret = RegCreateKeyExW( hkey, lpszSubKeyW, dwReserved, lpszClassW,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002355 fdwOptions, samDesired, lpSecAttribs, retkey,
2356 lpDispos );
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002357
2358 if(lpszSubKeyW) free(lpszSubKeyW);
2359 if(lpszClassW) free(lpszClassW);
2360
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002361 return ret;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002362}
2363
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002364
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002365/******************************************************************************
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002366 * RegCreateKey32W [ADVAPI32.132]
2367 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002368DWORD WINAPI RegCreateKeyW( HKEY hkey, LPCWSTR lpszSubKey, LPHKEY retkey )
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002369{
2370 DWORD junk;
2371 LPKEYSTRUCT lpNextKey;
2372
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002373 TRACE_(reg)("(%x,%s,%p)\n", hkey,debugstr_w(lpszSubKey),retkey);
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002374
2375 /* This check is here because the return value is different than the
2376 one from the Ex functions */
2377 lpNextKey = lookup_hkey(hkey);
2378 if (!lpNextKey)
2379 return ERROR_BADKEY;
2380
Alexandre Julliarda3960291999-02-26 11:11:13 +00002381 return RegCreateKeyExW( hkey, lpszSubKey, 0, NULL,
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002382 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
2383 retkey, &junk);
2384}
2385
2386
2387/******************************************************************************
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002388 * RegCreateKey32A [ADVAPI32.129]
2389 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002390DWORD WINAPI RegCreateKeyA( HKEY hkey, LPCSTR lpszSubKey, LPHKEY retkey )
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002391{
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002392 DWORD ret;
2393 LPWSTR lpszSubKeyW;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002394
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002395 TRACE_(reg)("(%x,%s,%p)\n",hkey,debugstr_a(lpszSubKey),retkey);
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002396 lpszSubKeyW = lpszSubKey?strdupA2W(lpszSubKey):NULL;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002397 ret = RegCreateKeyW( hkey, lpszSubKeyW, retkey );
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002398 if(lpszSubKeyW) free(lpszSubKeyW);
2399 return ret;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002400}
2401
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002402
2403/******************************************************************************
2404 * RegCreateKey16 [SHELL.2] [KERNEL.218]
2405 */
2406DWORD WINAPI RegCreateKey16( HKEY hkey, LPCSTR lpszSubKey, LPHKEY retkey )
2407{
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002408 TRACE_(reg)("(%x,%s,%p)\n",hkey,debugstr_a(lpszSubKey),retkey);
Alexandre Julliarda3960291999-02-26 11:11:13 +00002409 return RegCreateKeyA( hkey, lpszSubKey, retkey );
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002410}
2411
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002412
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002413/*
2414 * Query Value Functions
2415 * Win32 differs between keynames and valuenames.
2416 * multiple values may belong to one key, the special value
2417 * with name NULL is the default value used by the win31
2418 * compat functions.
2419 *
2420 * Callpath:
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00002421 * RegQueryValue16 -> RegQueryValue32A -> RegQueryValueEx32A \
Alexandre Julliard642d3131998-07-12 19:29:36 +00002422 * RegQueryValue32W -> RegQueryValueEx32W
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002423 */
2424
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002425
2426/******************************************************************************
2427 * RegQueryValueEx32W [ADVAPI32.158]
2428 * Retrieves type and data for a specified name associated with an open key
2429 *
2430 * PARAMS
2431 * hkey [I] Handle of key to query
2432 * lpValueName [I] Name of value to query
2433 * lpdwReserved [I] Reserved - must be NULL
2434 * lpdwType [O] Address of buffer for value type. If NULL, the type
2435 * is not required.
2436 * lpbData [O] Address of data buffer. If NULL, the actual data is
2437 * not required.
2438 * lpcbData [I/O] Address of data buffer size
2439 *
2440 * RETURNS
2441 * ERROR_SUCCESS: Success
Juergen Schmiedf74fa4e1999-01-31 09:19:46 +00002442 * ERROR_MORE_DATA: !!! if the specified buffer is not big enough to hold the data
2443 * buffer is left untouched. The MS-documentation is wrong (js) !!!
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002444 */
Huw D M Daviesdf088c61999-07-10 11:41:24 +00002445DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR lpValueName,
2446 LPDWORD lpdwReserved, LPDWORD lpdwType,
2447 LPBYTE lpbData, LPDWORD lpcbData )
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002448{
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002449 LPKEYSTRUCT lpkey;
2450 int i;
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002451 DWORD ret;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002452
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002453 TRACE_(reg)("(0x%x,%s,%p,%p,%p,%p=%ld)\n", hkey, debugstr_w(lpValueName),
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002454 lpdwReserved, lpdwType, lpbData, lpcbData, lpcbData?*lpcbData:0);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002455
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002456 lpkey = lookup_hkey(hkey);
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002457
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002458 if (!lpkey)
2459 return ERROR_INVALID_HANDLE;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002460
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002461 if ((lpbData && ! lpcbData) || lpdwReserved)
2462 return ERROR_INVALID_PARAMETER;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002463
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002464 /* An empty name string is equivalent to NULL */
2465 if (lpValueName && !*lpValueName)
2466 lpValueName = NULL;
2467
2468 if (lpValueName==NULL)
2469 { /* Use key's unnamed or default value, if any */
2470 for (i=0;i<lpkey->nrofvalues;i++)
2471 if (lpkey->values[i].name==NULL)
2472 break;
2473 }
2474 else
2475 { /* Search for the key name */
2476 for (i=0;i<lpkey->nrofvalues;i++)
Alexandre Julliarda3960291999-02-26 11:11:13 +00002477 if ( lpkey->values[i].name && !lstrcmpiW(lpValueName,lpkey->values[i].name))
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002478 break;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002479 }
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002480
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002481 if (i==lpkey->nrofvalues)
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002482 { TRACE_(reg)(" Key not found\n");
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002483 if (lpValueName==NULL)
2484 { /* Empty keyname not found */
2485 if (lpbData)
2486 { *(WCHAR*)lpbData = 0;
2487 *lpcbData = 2;
2488 }
2489 if (lpdwType)
2490 *lpdwType = REG_SZ;
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002491 TRACE_(reg)(" Returning an empty string\n");
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002492 return ERROR_SUCCESS;
2493 }
2494 return ERROR_FILE_NOT_FOUND;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002495 }
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002496
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002497 ret = ERROR_SUCCESS;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002498
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002499 if (lpdwType) /* type required ?*/
2500 *lpdwType = lpkey->values[i].type;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002501
Juergen Schmiedf74fa4e1999-01-31 09:19:46 +00002502 if (lpbData) /* data required ?*/
2503 { if (*lpcbData >= lpkey->values[i].len) /* buffer large enought ?*/
2504 memcpy(lpbData,lpkey->values[i].data,lpkey->values[i].len);
2505 else
2506 ret = ERROR_MORE_DATA;
2507 }
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002508
Juergen Schmiedf74fa4e1999-01-31 09:19:46 +00002509 if (lpcbData) /* size required ?*/
2510 { *lpcbData = lpkey->values[i].len;
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002511 }
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002512
Sylvain St.Germaine5332221999-04-10 16:46:15 +00002513 debug_print_value ( lpbData, &lpkey->values[i]);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002514
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002515 TRACE_(reg)(" (ret=%lx, type=%lx, len=%ld)\n", ret, lpdwType?*lpdwType:0,lpcbData?*lpcbData:0);
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002516
2517 return ret;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002518}
2519
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002520
2521/******************************************************************************
2522 * RegQueryValue32W [ADVAPI32.159]
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002523 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002524DWORD WINAPI RegQueryValueW( HKEY hkey, LPCWSTR lpszSubKey, LPWSTR lpszData,
Alexandre Julliardb24fc081999-02-25 16:36:07 +00002525 LPLONG lpcbData )
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002526{
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002527 HKEY xhkey;
2528 DWORD ret,lpdwType;
2529
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002530 TRACE_(reg)("(%x,%s,%p,%ld)\n",hkey,debugstr_w(lpszSubKey),lpszData,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002531 lpcbData?*lpcbData:0);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002532
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002533 /* Only open subkey, if we really do descend */
2534 if (lpszSubKey && *lpszSubKey) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002535 ret = RegOpenKeyW( hkey, lpszSubKey, &xhkey );
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002536 if (ret != ERROR_SUCCESS) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002537 WARN_(reg)("Could not open %s\n", debugstr_w(lpszSubKey));
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002538 return ret;
2539 }
2540 } else
2541 xhkey = hkey;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002542
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002543 lpdwType = REG_SZ;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002544 ret = RegQueryValueExW( xhkey, NULL, NULL, &lpdwType, (LPBYTE)lpszData,
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002545 lpcbData );
2546 if (xhkey != hkey)
2547 RegCloseKey(xhkey);
2548 return ret;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002549}
2550
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002551
2552/******************************************************************************
2553 * RegQueryValueEx32A [ADVAPI32.157]
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002554 *
2555 * NOTES:
2556 * the documantation is wrong: if the buffer is to small it remains untouched
2557 *
2558 * FIXME: check returnvalue (len) for an empty key
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002559 */
Huw D M Daviesdf088c61999-07-10 11:41:24 +00002560DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR lpszValueName,
2561 LPDWORD lpdwReserved, LPDWORD lpdwType,
2562 LPBYTE lpbData, LPDWORD lpcbData )
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002563{
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002564 LPWSTR lpszValueNameW;
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002565 LPBYTE mybuf = NULL;
2566 DWORD ret, mytype, mylen = 0;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002567
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002568 TRACE_(reg)("(%x,%s,%p,%p,%p,%p=%ld)\n", hkey,debugstr_a(lpszValueName),
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002569 lpdwReserved,lpdwType,lpbData,lpcbData,lpcbData?*lpcbData:0);
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00002570
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002571 if (!lpcbData && lpbData) /* buffer without size is illegal */
2572 { return ERROR_INVALID_PARAMETER;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002573 }
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002574
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002575 lpszValueNameW = lpszValueName ? strdupA2W(lpszValueName) : NULL;
2576
2577 /* get just the type first */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002578 ret = RegQueryValueExW( hkey, lpszValueNameW, lpdwReserved, &mytype, NULL, NULL );
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002579
2580 if ( ret != ERROR_SUCCESS ) /* failed ?? */
2581 { if(lpszValueNameW) free(lpszValueNameW);
2582 return ret;
2583 }
2584
2585 if (lpcbData) /* at least length requested? */
2586 { if (UNICONVMASK & (1<<(mytype))) /* string requested? */
Juergen Schmiedf74fa4e1999-01-31 09:19:46 +00002587 { if (lpbData ) /* value requested? */
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002588 { mylen = 2*( *lpcbData );
2589 mybuf = (LPBYTE)xmalloc( mylen );
2590 }
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002591
Alexandre Julliarda3960291999-02-26 11:11:13 +00002592 ret = RegQueryValueExW( hkey, lpszValueNameW, lpdwReserved, lpdwType, mybuf, &mylen );
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002593
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002594 if (ret == ERROR_SUCCESS )
2595 { if ( lpbData )
2596 { lmemcpynWtoA(lpbData, (LPWSTR)mybuf, mylen/2);
2597 }
2598 }
2599
2600 *lpcbData = mylen/2; /* size is in byte! */
2601 }
2602 else /* no strings, call it straight */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002603 { ret = RegQueryValueExW( hkey, lpszValueNameW, lpdwReserved, lpdwType, lpbData, lpcbData );
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002604 }
2605 }
2606
2607 if (lpdwType) /* type when requested */
2608 { *lpdwType = mytype;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002609 }
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002610
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002611 TRACE_(reg)(" (ret=%lx,type=%lx, len=%ld)\n", ret,mytype,lpcbData?*lpcbData:0);
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002612
2613 if(mybuf) free(mybuf);
2614 if(lpszValueNameW) free(lpszValueNameW);
2615 return ret;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002616}
2617
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00002618
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002619/******************************************************************************
2620 * RegQueryValueEx16 [KERNEL.225]
2621 */
2622DWORD WINAPI RegQueryValueEx16( HKEY hkey, LPSTR lpszValueName,
2623 LPDWORD lpdwReserved, LPDWORD lpdwType,
2624 LPBYTE lpbData, LPDWORD lpcbData )
2625{
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002626 TRACE_(reg)("(%x,%s,%p,%p,%p,%ld)\n",hkey,debugstr_a(lpszValueName),
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002627 lpdwReserved,lpdwType,lpbData,lpcbData?*lpcbData:0);
Alexandre Julliarda3960291999-02-26 11:11:13 +00002628 return RegQueryValueExA( hkey, lpszValueName, lpdwReserved, lpdwType,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002629 lpbData, lpcbData );
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002630}
2631
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002632
2633/******************************************************************************
2634 * RegQueryValue32A [ADVAPI32.156]
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002635 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002636DWORD WINAPI RegQueryValueA( HKEY hkey, LPCSTR lpszSubKey, LPSTR lpszData,
Alexandre Julliardb24fc081999-02-25 16:36:07 +00002637 LPLONG lpcbData )
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002638{
2639 HKEY xhkey;
2640 DWORD ret, dwType;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002641
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002642 TRACE_(reg)("(%x,%s,%p,%ld)\n",hkey,debugstr_a(lpszSubKey),lpszData,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002643 lpcbData?*lpcbData:0);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002644
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002645 if (lpszSubKey && *lpszSubKey) {
2646 ret = RegOpenKey16( hkey, lpszSubKey, &xhkey );
2647 if( ret != ERROR_SUCCESS )
2648 return ret;
2649 } else
2650 xhkey = hkey;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002651
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002652 dwType = REG_SZ;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002653 ret = RegQueryValueExA( xhkey, NULL,NULL, &dwType, (LPBYTE)lpszData,
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002654 lpcbData );
2655 if( xhkey != hkey )
2656 RegCloseKey( xhkey );
2657 return ret;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002658}
2659
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00002660
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002661/******************************************************************************
2662 * RegQueryValue16 [SHELL.6] [KERNEL.224]
2663 *
2664 * NOTES
2665 * Is this HACK still applicable?
2666 *
2667 * HACK
2668 * The 16bit RegQueryValue doesn't handle selectorblocks anyway, so we just
2669 * mask out the high 16 bit. This (not so much incidently) hopefully fixes
2670 * Aldus FH4)
2671 */
2672DWORD WINAPI RegQueryValue16( HKEY hkey, LPSTR lpszSubKey, LPSTR lpszData,
2673 LPDWORD lpcbData )
2674{
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002675 TRACE_(reg)("(%x,%s,%p,%ld)\n",hkey,debugstr_a(lpszSubKey),lpszData,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002676 lpcbData?*lpcbData:0);
2677
2678 if (lpcbData)
2679 *lpcbData &= 0xFFFF;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002680 return RegQueryValueA(hkey,lpszSubKey,lpszData,lpcbData);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002681}
2682
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002683
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002684/*
2685 * Setting values of Registry keys
2686 *
2687 * Callpath:
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00002688 * RegSetValue16 -> RegSetValue32A -> RegSetValueEx32A \
2689 * RegSetValue32W -> RegSetValueEx32W
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002690 */
2691
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002692
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002693/******************************************************************************
2694 * RegSetValueEx32W [ADVAPI32.170]
2695 * Sets the data and type of a value under a register key
2696 *
2697 * PARAMS
2698 * hkey [I] Handle of key to set value for
2699 * lpszValueName [I] Name of value to set
2700 * dwReserved [I] Reserved - must be zero
2701 * dwType [I] Flag for value type
2702 * lpbData [I] Address of value data
2703 * cbData [I] Size of value data
2704 *
2705 * RETURNS
2706 * Success: ERROR_SUCCESS
2707 * Failure: Error code
Juergen Schmiedf74fa4e1999-01-31 09:19:46 +00002708 *
2709 * NOTES
2710 * win95 does not care about cbData for REG_SZ and finds out the len by itself (js)
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002711 */
Huw D M Daviesdf088c61999-07-10 11:41:24 +00002712DWORD WINAPI RegSetValueExW( HKEY hkey, LPCWSTR lpszValueName,
2713 DWORD dwReserved, DWORD dwType,
2714 CONST BYTE *lpbData, DWORD cbData)
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002715{
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002716 LPKEYSTRUCT lpkey;
2717 int i;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002718
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002719 TRACE_(reg)("(%x,%s,%ld,%ld,%p,%ld)\n", hkey, debugstr_w(lpszValueName),
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002720 dwReserved, dwType, lpbData, cbData);
2721
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002722 lpkey = lookup_hkey( hkey );
2723
2724 if (!lpkey)
2725 return ERROR_INVALID_HANDLE;
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00002726
2727 lpkey->flags |= REG_OPTION_TAINTED;
2728
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002729 if (lpszValueName==NULL) {
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002730 /* Sets type and name for key's unnamed or default value */
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002731 for (i=0;i<lpkey->nrofvalues;i++)
2732 if (lpkey->values[i].name==NULL)
2733 break;
2734 } else {
2735 for (i=0;i<lpkey->nrofvalues;i++)
Alexandre Julliard0e270f41996-08-24 18:26:35 +00002736 if ( lpkey->values[i].name &&
Alexandre Julliarda3960291999-02-26 11:11:13 +00002737 !lstrcmpiW(lpszValueName,lpkey->values[i].name)
Alexandre Julliard0e270f41996-08-24 18:26:35 +00002738 )
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002739 break;
2740 }
2741 if (i==lpkey->nrofvalues) {
2742 lpkey->values = (LPKEYVALUE)xrealloc(
2743 lpkey->values,
2744 (lpkey->nrofvalues+1)*sizeof(KEYVALUE)
2745 );
2746 lpkey->nrofvalues++;
2747 memset(lpkey->values+i,'\0',sizeof(KEYVALUE));
2748 }
Marcus Meissnerf4f17191998-10-17 12:10:19 +00002749 if (lpkey->values[i].name==NULL) {
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002750 if (lpszValueName)
2751 lpkey->values[i].name = strdupW(lpszValueName);
2752 else
2753 lpkey->values[i].name = NULL;
Marcus Meissnerf4f17191998-10-17 12:10:19 +00002754 }
Juergen Schmiedf74fa4e1999-01-31 09:19:46 +00002755
2756 if (dwType == REG_SZ)
Alexandre Julliarda3960291999-02-26 11:11:13 +00002757 cbData = 2 * (lstrlenW ((LPCWSTR)lpbData) + 1);
Juergen Schmiedf74fa4e1999-01-31 09:19:46 +00002758
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002759 lpkey->values[i].len = cbData;
2760 lpkey->values[i].type = dwType;
2761 if (lpkey->values[i].data !=NULL)
2762 free(lpkey->values[i].data);
2763 lpkey->values[i].data = (LPBYTE)xmalloc(cbData);
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00002764 lpkey->values[i].lastmodified = time(NULL);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002765 memcpy(lpkey->values[i].data,lpbData,cbData);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002766 return ERROR_SUCCESS;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002767}
2768
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002769
2770/******************************************************************************
2771 * RegSetValueEx32A [ADVAPI32.169]
2772 *
Juergen Schmiedf74fa4e1999-01-31 09:19:46 +00002773 * NOTES
2774 * win95 does not care about cbData for REG_SZ and finds out the len by itself (js)
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002775 */
Huw D M Daviesdf088c61999-07-10 11:41:24 +00002776DWORD WINAPI RegSetValueExA( HKEY hkey, LPCSTR lpszValueName,
2777 DWORD dwReserved, DWORD dwType,
2778 CONST BYTE *lpbData, DWORD cbData )
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002779{
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002780 LPBYTE buf;
2781 LPWSTR lpszValueNameW;
2782 DWORD ret;
2783
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002784 if (!lpbData)
2785 return (ERROR_INVALID_PARAMETER);
2786
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002787 TRACE_(reg)("(%x,%s,%ld,%ld,%p,%ld)\n",hkey,debugstr_a(lpszValueName),
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002788 dwReserved,dwType,lpbData,cbData);
2789
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002790 if ((1<<dwType) & UNICONVMASK)
Juergen Schmiedf74fa4e1999-01-31 09:19:46 +00002791 { if (dwType == REG_SZ)
2792 cbData = strlen ((LPCSTR)lpbData)+1;
2793
2794 buf = (LPBYTE)xmalloc( cbData *2 );
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002795 lmemcpynAtoW ((LPVOID)buf, lpbData, cbData );
2796 cbData=2*cbData;
2797 }
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002798 else
Huw D M Daviesdf088c61999-07-10 11:41:24 +00002799 buf=(LPBYTE)lpbData;
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002800
2801 if (lpszValueName)
2802 lpszValueNameW = strdupA2W(lpszValueName);
2803 else
2804 lpszValueNameW = NULL;
2805
Alexandre Julliarda3960291999-02-26 11:11:13 +00002806 ret=RegSetValueExW(hkey,lpszValueNameW,dwReserved,dwType,buf,cbData);
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002807
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002808 if (lpszValueNameW)
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002809 free(lpszValueNameW);
2810
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002811 if (buf!=lpbData)
Juergen Schmied26cae9d1999-01-23 12:11:09 +00002812 free(buf);
2813
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002814 return ret;
2815}
2816
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002817
2818/******************************************************************************
2819 * RegSetValueEx16 [KERNEL.226]
2820 */
2821DWORD WINAPI RegSetValueEx16( HKEY hkey, LPSTR lpszValueName, DWORD dwReserved,
2822 DWORD dwType, LPBYTE lpbData, DWORD cbData )
2823{
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002824 TRACE_(reg)("(%x,%s,%ld,%ld,%p,%ld)\n",hkey,debugstr_a(lpszValueName),
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002825 dwReserved,dwType,lpbData,cbData);
Alexandre Julliarda3960291999-02-26 11:11:13 +00002826 return RegSetValueExA( hkey, lpszValueName, dwReserved, dwType, lpbData,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002827 cbData );
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002828}
2829
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002830
2831/******************************************************************************
2832 * RegSetValue32W [ADVAPI32.171]
2833 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002834DWORD WINAPI RegSetValueW( HKEY hkey, LPCWSTR lpszSubKey, DWORD dwType,
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002835 LPCWSTR lpszData, DWORD cbData )
2836{
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002837 HKEY xhkey;
2838 DWORD ret;
2839
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002840 TRACE_(reg)("(%x,%s,%ld,%s,%ld)\n",
Alexandre Julliarda845b881998-06-01 10:44:35 +00002841 hkey,debugstr_w(lpszSubKey),dwType,debugstr_w(lpszData),cbData
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002842 );
2843 if (lpszSubKey && *lpszSubKey) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00002844 ret=RegCreateKeyW(hkey,lpszSubKey,&xhkey);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002845 if (ret!=ERROR_SUCCESS)
2846 return ret;
2847 } else
2848 xhkey=hkey;
2849 if (dwType!=REG_SZ) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002850 TRACE_(reg)("dwType=%ld - Changing to REG_SZ\n",dwType);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002851 dwType=REG_SZ;
2852 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00002853 if (cbData!=2*lstrlenW(lpszData)+2) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002854 TRACE_(reg)("Len=%ld != strlen(%s)+1=%d!\n",
Alexandre Julliarda3960291999-02-26 11:11:13 +00002855 cbData,debugstr_w(lpszData),2*lstrlenW(lpszData)+2
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002856 );
Alexandre Julliarda3960291999-02-26 11:11:13 +00002857 cbData=2*lstrlenW(lpszData)+2;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002858 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00002859 ret=RegSetValueExW(xhkey,NULL,0,dwType,(LPBYTE)lpszData,cbData);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002860 if (hkey!=xhkey)
2861 RegCloseKey(xhkey);
2862 return ret;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002863}
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002864
2865
2866/******************************************************************************
2867 * RegSetValue32A [ADVAPI32.168]
2868 *
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002869 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002870DWORD WINAPI RegSetValueA( HKEY hkey, LPCSTR lpszSubKey, DWORD dwType,
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002871 LPCSTR lpszData, DWORD cbData )
2872{
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002873 DWORD ret;
2874 HKEY xhkey;
2875
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002876 TRACE_(reg)("(%x,%s,%ld,%s,%ld)\n",hkey,lpszSubKey,dwType,lpszData,cbData);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002877 if (lpszSubKey && *lpszSubKey) {
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00002878 ret=RegCreateKey16(hkey,lpszSubKey,&xhkey);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002879 if (ret!=ERROR_SUCCESS)
2880 return ret;
2881 } else
2882 xhkey=hkey;
2883
2884 if (dwType!=REG_SZ) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002885 TRACE_(reg)("dwType=%ld!\n",dwType);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002886 dwType=REG_SZ;
2887 }
2888 if (cbData!=strlen(lpszData)+1)
2889 cbData=strlen(lpszData)+1;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002890 ret=RegSetValueExA(xhkey,NULL,0,dwType,(LPBYTE)lpszData,cbData);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002891 if (xhkey!=hkey)
2892 RegCloseKey(xhkey);
2893 return ret;
2894}
2895
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002896
2897/******************************************************************************
2898 * RegSetValue16 [KERNEL.221] [SHELL.5]
2899 */
2900DWORD WINAPI RegSetValue16( HKEY hkey, LPCSTR lpszSubKey, DWORD dwType,
2901 LPCSTR lpszData, DWORD cbData )
2902{
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002903 TRACE_(reg)("(%x,%s,%ld,%s,%ld)\n",hkey,debugstr_a(lpszSubKey),dwType,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002904 debugstr_a(lpszData),cbData);
Alexandre Julliarda3960291999-02-26 11:11:13 +00002905 return RegSetValueA(hkey,lpszSubKey,dwType,lpszData,cbData);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002906}
2907
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002908
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002909/*
2910 * Key Enumeration
2911 *
2912 * Callpath:
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00002913 * RegEnumKey16 -> RegEnumKey32A -> RegEnumKeyEx32A \
Alexandre Julliard642d3131998-07-12 19:29:36 +00002914 * RegEnumKey32W -> RegEnumKeyEx32W
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002915 */
2916
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002917
2918/******************************************************************************
2919 * RegEnumKeyEx32W [ADVAPI32.139]
Alexandre Julliard642d3131998-07-12 19:29:36 +00002920 *
2921 * PARAMS
2922 * hkey [I] Handle to key to enumerate
2923 * iSubKey [I] Index of subkey to enumerate
2924 * lpszName [O] Buffer for subkey name
2925 * lpcchName [O] Size of subkey buffer
2926 * lpdwReserved [I] Reserved
2927 * lpszClass [O] Buffer for class string
2928 * lpcchClass [O] Size of class buffer
2929 * ft [O] Time key last written to
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002930 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002931DWORD WINAPI RegEnumKeyExW( HKEY hkey, DWORD iSubkey, LPWSTR lpszName,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002932 LPDWORD lpcchName, LPDWORD lpdwReserved,
2933 LPWSTR lpszClass, LPDWORD lpcchClass,
2934 FILETIME *ft )
2935{
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002936 LPKEYSTRUCT lpkey,lpxkey;
2937
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002938 TRACE_(reg)("(%x,%ld,%p,%ld,%p,%p,%p,%p)\n",hkey,iSubkey,lpszName,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002939 *lpcchName,lpdwReserved,lpszClass,lpcchClass,ft);
2940
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002941 lpkey = lookup_hkey( hkey );
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002942 if (!lpkey)
2943 return ERROR_INVALID_HANDLE;
2944
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002945 if (!lpkey->nextsub)
2946 return ERROR_NO_MORE_ITEMS;
2947 lpxkey=lpkey->nextsub;
Alexandre Julliard642d3131998-07-12 19:29:36 +00002948
2949 /* Traverse the subkeys */
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002950 while (iSubkey && lpxkey) {
2951 iSubkey--;
2952 lpxkey=lpxkey->next;
2953 }
Alexandre Julliard642d3131998-07-12 19:29:36 +00002954
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002955 if (iSubkey || !lpxkey)
2956 return ERROR_NO_MORE_ITEMS;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002957 if (lstrlenW(lpxkey->keyname)+1>*lpcchName)
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002958 return ERROR_MORE_DATA;
Alexandre Julliarda3960291999-02-26 11:11:13 +00002959 memcpy(lpszName,lpxkey->keyname,lstrlenW(lpxkey->keyname)*2+2);
Alexandre Julliard642d3131998-07-12 19:29:36 +00002960
2961 if (*lpcchName)
Alexandre Julliarda3960291999-02-26 11:11:13 +00002962 *lpcchName = lstrlenW(lpszName);
Alexandre Julliard642d3131998-07-12 19:29:36 +00002963
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002964 if (lpszClass) {
Alexandre Julliard642d3131998-07-12 19:29:36 +00002965 /* FIXME: what should we write into it? */
Alexandre Julliarda69b88b1998-03-15 20:29:56 +00002966 *lpszClass = 0;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002967 *lpcchClass = 2;
2968 }
2969 return ERROR_SUCCESS;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002970}
2971
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002972
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002973/******************************************************************************
2974 * RegEnumKey32W [ADVAPI32.140]
2975 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002976DWORD WINAPI RegEnumKeyW( HKEY hkey, DWORD iSubkey, LPWSTR lpszName,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002977 DWORD lpcchName )
2978{
2979 FILETIME ft;
2980
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002981 TRACE_(reg)("(%x,%ld,%p,%ld)\n",hkey,iSubkey,lpszName,lpcchName);
Alexandre Julliarda3960291999-02-26 11:11:13 +00002982 return RegEnumKeyExW(hkey,iSubkey,lpszName,&lpcchName,NULL,NULL,NULL,&ft);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002983}
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00002984
2985
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002986/******************************************************************************
2987 * RegEnumKeyEx32A [ADVAPI32.138]
2988 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00002989DWORD WINAPI RegEnumKeyExA( HKEY hkey, DWORD iSubkey, LPSTR lpszName,
Alexandre Julliardf90efa91998-06-14 15:24:15 +00002990 LPDWORD lpcchName, LPDWORD lpdwReserved,
2991 LPSTR lpszClass, LPDWORD lpcchClass,
2992 FILETIME *ft )
2993{
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002994 DWORD ret,lpcchNameW,lpcchClassW;
2995 LPWSTR lpszNameW,lpszClassW;
2996
2997
Alexandre Julliard06c275a1999-05-02 14:32:27 +00002998 TRACE_(reg)("(%x,%ld,%p,%ld,%p,%p,%p,%p)\n",
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00002999 hkey,iSubkey,lpszName,*lpcchName,lpdwReserved,lpszClass,lpcchClass,ft
3000 );
3001 if (lpszName) {
3002 lpszNameW = (LPWSTR)xmalloc(*lpcchName*2);
Uwe Bonnes87763441998-11-08 14:22:31 +00003003 lpcchNameW = *lpcchName;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003004 } else {
3005 lpszNameW = NULL;
3006 lpcchNameW = 0;
3007 }
3008 if (lpszClass) {
3009 lpszClassW = (LPWSTR)xmalloc(*lpcchClass*2);
Uwe Bonnes87763441998-11-08 14:22:31 +00003010 lpcchClassW = *lpcchClass;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003011 } else {
3012 lpszClassW =0;
3013 lpcchClassW=0;
3014 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00003015 ret=RegEnumKeyExW(
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003016 hkey,
3017 iSubkey,
3018 lpszNameW,
3019 &lpcchNameW,
3020 lpdwReserved,
3021 lpszClassW,
3022 &lpcchClassW,
3023 ft
3024 );
3025 if (ret==ERROR_SUCCESS) {
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00003026 lstrcpyWtoA(lpszName,lpszNameW);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003027 *lpcchName=strlen(lpszName);
3028 if (lpszClassW) {
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00003029 lstrcpyWtoA(lpszClass,lpszClassW);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003030 *lpcchClass=strlen(lpszClass);
3031 }
3032 }
3033 if (lpszNameW)
3034 free(lpszNameW);
3035 if (lpszClassW)
3036 free(lpszClassW);
3037 return ret;
3038}
3039
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003040
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003041/******************************************************************************
3042 * RegEnumKey32A [ADVAPI32.137]
3043 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003044DWORD WINAPI RegEnumKeyA( HKEY hkey, DWORD iSubkey, LPSTR lpszName,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003045 DWORD lpcchName )
3046{
3047 FILETIME ft;
3048
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003049 TRACE_(reg)("(%x,%ld,%p,%ld)\n",hkey,iSubkey,lpszName,lpcchName);
Alexandre Julliarda3960291999-02-26 11:11:13 +00003050 return RegEnumKeyExA( hkey, iSubkey, lpszName, &lpcchName, NULL, NULL,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003051 NULL, &ft );
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003052}
3053
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003054
3055/******************************************************************************
3056 * RegEnumKey16 [SHELL.7] [KERNEL.216]
3057 */
3058DWORD WINAPI RegEnumKey16( HKEY hkey, DWORD iSubkey, LPSTR lpszName,
3059 DWORD lpcchName )
3060{
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003061 TRACE_(reg)("(%x,%ld,%p,%ld)\n",hkey,iSubkey,lpszName,lpcchName);
Alexandre Julliarda3960291999-02-26 11:11:13 +00003062 return RegEnumKeyA( hkey, iSubkey, lpszName, lpcchName);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003063}
3064
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003065
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003066/*
3067 * Enumerate Registry Values
3068 *
3069 * Callpath:
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00003070 * RegEnumValue16 -> RegEnumValue32A -> RegEnumValue32W
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003071 */
3072
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003073
3074/******************************************************************************
3075 * RegEnumValue32W [ADVAPI32.142]
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003076 *
3077 * PARAMS
Alexandre Julliard642d3131998-07-12 19:29:36 +00003078 * hkey [I] Handle to key to query
3079 * iValue [I] Index of value to query
3080 * lpszValue [O] Value string
Juergen Schmiedf74fa4e1999-01-31 09:19:46 +00003081 * lpcchValue [I/O] Size of value buffer (in wchars)
Alexandre Julliard642d3131998-07-12 19:29:36 +00003082 * lpdReserved [I] Reserved
3083 * lpdwType [O] Type code
3084 * lpbData [O] Value data
Juergen Schmiedf74fa4e1999-01-31 09:19:46 +00003085 * lpcbData [I/O] Size of data buffer (in bytes)
John Richardson2bb013b1998-11-06 17:36:13 +00003086 *
3087 * Note: wide character functions that take and/or return "character counts"
3088 * use TCHAR (that is unsigned short or char) not byte counts.
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003089 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003090DWORD WINAPI RegEnumValueW( HKEY hkey, DWORD iValue, LPWSTR lpszValue,
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003091 LPDWORD lpcchValue, LPDWORD lpdReserved,
3092 LPDWORD lpdwType, LPBYTE lpbData,
3093 LPDWORD lpcbData )
3094{
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003095 LPKEYSTRUCT lpkey;
3096 LPKEYVALUE val;
3097
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003098 TRACE_(reg)("(%x,%ld,%p,%p,%p,%p,%p,%p)\n",hkey,iValue,debugstr_w(lpszValue),
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003099 lpcchValue,lpdReserved,lpdwType,lpbData,lpcbData);
3100
Juergen Schmiedf74fa4e1999-01-31 09:19:46 +00003101 lpkey = lookup_hkey( hkey );
3102
3103 if (!lpcbData && lpbData)
3104 return ERROR_INVALID_PARAMETER;
3105
3106 if (!lpkey)
3107 return ERROR_INVALID_HANDLE;
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003108
Juergen Schmiedf74fa4e1999-01-31 09:19:46 +00003109 if (lpkey->nrofvalues <= iValue)
3110 return ERROR_NO_MORE_ITEMS;
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003111
Juergen Schmiedf74fa4e1999-01-31 09:19:46 +00003112 val = &(lpkey->values[iValue]);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003113
3114 if (val->name) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00003115 if (lstrlenW(val->name)+1>*lpcchValue) {
3116 *lpcchValue = lstrlenW(val->name)+1;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003117 return ERROR_MORE_DATA;
3118 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00003119 memcpy(lpszValue,val->name,2 * (lstrlenW(val->name)+1) );
3120 *lpcchValue=lstrlenW(val->name);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003121 } else {
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003122 *lpszValue = 0;
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00003123 *lpcchValue = 0;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003124 }
Alexandre Julliard642d3131998-07-12 19:29:36 +00003125
Juergen Schmiedf74fa4e1999-01-31 09:19:46 +00003126 /* Can be NULL if the type code is not required */
3127 if (lpdwType)
3128 *lpdwType = val->type;
Alexandre Julliard642d3131998-07-12 19:29:36 +00003129
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003130 if (lpbData) {
3131 if (val->len>*lpcbData)
3132 return ERROR_MORE_DATA;
3133 memcpy(lpbData,val->data,val->len);
3134 *lpcbData = val->len;
3135 }
Juergen Schmiedf74fa4e1999-01-31 09:19:46 +00003136
Sylvain St.Germaine5332221999-04-10 16:46:15 +00003137 debug_print_value ( val->data, val );
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003138 return ERROR_SUCCESS;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003139}
3140
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003141
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003142/******************************************************************************
3143 * RegEnumValue32A [ADVAPI32.141]
3144 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003145DWORD WINAPI RegEnumValueA( HKEY hkey, DWORD iValue, LPSTR lpszValue,
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003146 LPDWORD lpcchValue, LPDWORD lpdReserved,
3147 LPDWORD lpdwType, LPBYTE lpbData,
3148 LPDWORD lpcbData )
3149{
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003150 LPWSTR lpszValueW;
3151 LPBYTE lpbDataW;
3152 DWORD ret,lpcbDataW;
Alexandre Julliard642d3131998-07-12 19:29:36 +00003153 DWORD dwType;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003154
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003155 TRACE_(reg)("(%x,%ld,%p,%p,%p,%p,%p,%p)\n",hkey,iValue,lpszValue,lpcchValue,
Alexandre Julliard642d3131998-07-12 19:29:36 +00003156 lpdReserved,lpdwType,lpbData,lpcbData);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003157
3158 lpszValueW = (LPWSTR)xmalloc(*lpcchValue*2);
3159 if (lpbData) {
3160 lpbDataW = (LPBYTE)xmalloc(*lpcbData*2);
Uwe Bonnes87763441998-11-08 14:22:31 +00003161 lpcbDataW = *lpcbData;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003162 } else
3163 lpbDataW = NULL;
Alexandre Julliard642d3131998-07-12 19:29:36 +00003164
Alexandre Julliarda3960291999-02-26 11:11:13 +00003165 ret = RegEnumValueW( hkey, iValue, lpszValueW, lpcchValue,
Alexandre Julliard642d3131998-07-12 19:29:36 +00003166 lpdReserved, &dwType, lpbDataW, &lpcbDataW );
3167
3168 if (lpdwType)
3169 *lpdwType = dwType;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003170
3171 if (ret==ERROR_SUCCESS) {
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00003172 lstrcpyWtoA(lpszValue,lpszValueW);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003173 if (lpbData) {
Alexandre Julliard642d3131998-07-12 19:29:36 +00003174 if ((1<<dwType) & UNICONVMASK) {
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00003175 lstrcpyWtoA(lpbData,(LPWSTR)lpbDataW);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003176 } else {
3177 if (lpcbDataW > *lpcbData)
3178 ret = ERROR_MORE_DATA;
3179 else
3180 memcpy(lpbData,lpbDataW,lpcbDataW);
3181 }
3182 *lpcbData = lpcbDataW;
3183 }
3184 }
Alexandre Julliard642d3131998-07-12 19:29:36 +00003185 if (lpbDataW) free(lpbDataW);
3186 if (lpszValueW) free(lpszValueW);
3187 return ret;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003188}
3189
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003190
3191/******************************************************************************
3192 * RegEnumValue16 [KERNEL.223]
3193 */
3194DWORD WINAPI RegEnumValue16( HKEY hkey, DWORD iValue, LPSTR lpszValue,
3195 LPDWORD lpcchValue, LPDWORD lpdReserved,
3196 LPDWORD lpdwType, LPBYTE lpbData,
3197 LPDWORD lpcbData )
3198{
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003199 TRACE_(reg)("(%x,%ld,%p,%p,%p,%p,%p,%p)\n",hkey,iValue,lpszValue,lpcchValue,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003200 lpdReserved,lpdwType,lpbData,lpcbData);
Alexandre Julliarda3960291999-02-26 11:11:13 +00003201 return RegEnumValueA( hkey, iValue, lpszValue, lpcchValue, lpdReserved,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003202 lpdwType, lpbData, lpcbData );
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003203}
3204
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003205
3206/******************************************************************************
3207 * RegCloseKey [SHELL.3] [KERNEL.220] [ADVAPI32.126]
3208 * Releases the handle of the specified key
3209 *
3210 * PARAMS
3211 * hkey [I] Handle of key to close
3212 *
3213 * RETURNS
3214 * Success: ERROR_SUCCESS
3215 * Failure: Error code
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003216 */
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003217DWORD WINAPI RegCloseKey( HKEY hkey )
3218{
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003219 TRACE_(reg)("(%x)\n",hkey);
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003220
3221 /* The standard handles are allowed to succeed, even though they are not
3222 closed */
3223 if (is_standard_hkey(hkey))
3224 return ERROR_SUCCESS;
3225
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003226 return remove_handle(hkey);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003227}
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003228
3229
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003230/*
3231 * Delete registry key
3232 *
3233 * Callpath:
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00003234 * RegDeleteKey16 -> RegDeleteKey32A -> RegDeleteKey32W
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003235 */
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003236
3237
3238/******************************************************************************
3239 * RegDeleteKey32W [ADVAPI32.134]
3240 *
3241 * PARAMS
Alexandre Julliard642d3131998-07-12 19:29:36 +00003242 * hkey [I] Handle to open key
3243 * lpszSubKey [I] Name of subkey to delete
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003244 *
3245 * RETURNS
3246 * Success: ERROR_SUCCESS
3247 * Failure: Error code
3248 */
Huw D M Daviesdf088c61999-07-10 11:41:24 +00003249DWORD WINAPI RegDeleteKeyW( HKEY hkey, LPCWSTR lpszSubKey )
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003250{
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003251 LPKEYSTRUCT *lplpPrevKey,lpNextKey,lpxkey;
3252 LPWSTR *wps;
3253 int wpc,i;
3254
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003255 TRACE_(reg)("(%x,%s)\n",hkey,debugstr_w(lpszSubKey));
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003256
3257 lpNextKey = lookup_hkey(hkey);
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003258 if (!lpNextKey)
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003259 return ERROR_INVALID_HANDLE;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003260
Alexandre Julliard642d3131998-07-12 19:29:36 +00003261 /* Subkey param cannot be NULL */
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003262 if (!lpszSubKey || !*lpszSubKey)
3263 return ERROR_BADKEY;
3264
Alexandre Julliard642d3131998-07-12 19:29:36 +00003265 /* We need to know the previous key in the hier. */
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003266 split_keypath(lpszSubKey,&wps,&wpc);
3267 i = 0;
3268 lpxkey = lpNextKey;
3269 while (i<wpc-1) {
3270 lpxkey=lpNextKey->nextsub;
3271 while (lpxkey) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003272 TRACE_(reg)(" Scanning [%s]\n",
Alexandre Julliarda845b881998-06-01 10:44:35 +00003273 debugstr_w(lpxkey->keyname));
Alexandre Julliarda3960291999-02-26 11:11:13 +00003274 if (!lstrcmpiW(wps[i],lpxkey->keyname))
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003275 break;
3276 lpxkey=lpxkey->next;
3277 }
3278 if (!lpxkey) {
3279 FREE_KEY_PATH;
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003280 TRACE_(reg)(" Not found.\n");
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003281 /* not found is success */
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003282 return ERROR_SUCCESS;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003283 }
3284 i++;
3285 lpNextKey = lpxkey;
3286 }
3287 lpxkey = lpNextKey->nextsub;
3288 lplpPrevKey = &(lpNextKey->nextsub);
3289 while (lpxkey) {
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003290 TRACE_(reg)(" Scanning [%s]\n",
Alexandre Julliarda845b881998-06-01 10:44:35 +00003291 debugstr_w(lpxkey->keyname));
Alexandre Julliarda3960291999-02-26 11:11:13 +00003292 if (!lstrcmpiW(wps[i],lpxkey->keyname))
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003293 break;
3294 lplpPrevKey = &(lpxkey->next);
3295 lpxkey = lpxkey->next;
3296 }
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003297
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00003298 if (!lpxkey) {
3299 FREE_KEY_PATH;
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003300 WARN_(reg)(" Not found.\n");
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003301 return ERROR_FILE_NOT_FOUND;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00003302 }
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003303
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00003304 if (lpxkey->nextsub) {
3305 FREE_KEY_PATH;
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003306 WARN_(reg)(" Not empty.\n");
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003307 return ERROR_CANTWRITE;
Alexandre Julliarda0b2b1d1997-11-16 17:38:29 +00003308 }
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003309 *lplpPrevKey = lpxkey->next;
3310 free(lpxkey->keyname);
3311 if (lpxkey->class)
3312 free(lpxkey->class);
3313 if (lpxkey->values)
3314 free(lpxkey->values);
3315 free(lpxkey);
3316 FREE_KEY_PATH;
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003317 TRACE_(reg)(" Done.\n");
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003318 return ERROR_SUCCESS;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003319}
3320
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003321
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003322/******************************************************************************
3323 * RegDeleteKey32A [ADVAPI32.133]
3324 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003325DWORD WINAPI RegDeleteKeyA( HKEY hkey, LPCSTR lpszSubKey )
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003326{
3327 LPWSTR lpszSubKeyW;
3328 DWORD ret;
3329
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003330 TRACE_(reg)("(%x,%s)\n",hkey,debugstr_a(lpszSubKey));
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003331 lpszSubKeyW = lpszSubKey?strdupA2W(lpszSubKey):NULL;
Alexandre Julliarda3960291999-02-26 11:11:13 +00003332 ret = RegDeleteKeyW( hkey, lpszSubKeyW );
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003333 if(lpszSubKeyW) free(lpszSubKeyW);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003334 return ret;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003335}
3336
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003337
3338/******************************************************************************
3339 * RegDeleteKey16 [SHELL.4] [KERNEL.219]
3340 */
3341DWORD WINAPI RegDeleteKey16( HKEY hkey, LPCSTR lpszSubKey )
3342{
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003343 TRACE_(reg)("(%x,%s)\n",hkey,debugstr_a(lpszSubKey));
Alexandre Julliarda3960291999-02-26 11:11:13 +00003344 return RegDeleteKeyA( hkey, lpszSubKey );
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003345}
3346
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003347
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003348/*
3349 * Delete registry value
3350 *
3351 * Callpath:
Alexandre Julliarde2bfa4c1996-05-16 18:21:06 +00003352 * RegDeleteValue16 -> RegDeleteValue32A -> RegDeleteValue32W
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003353 */
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003354
3355
3356/******************************************************************************
3357 * RegDeleteValue32W [ADVAPI32.136]
3358 *
3359 * PARAMS
3360 * hkey [I]
3361 * lpszValue [I]
3362 *
3363 * RETURNS
3364 */
Huw D M Daviesdf088c61999-07-10 11:41:24 +00003365DWORD WINAPI RegDeleteValueW( HKEY hkey, LPCWSTR lpszValue )
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003366{
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003367 DWORD i;
3368 LPKEYSTRUCT lpkey;
3369 LPKEYVALUE val;
3370
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003371 TRACE_(reg)("(%x,%s)\n",hkey,debugstr_w(lpszValue));
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003372
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003373 lpkey = lookup_hkey( hkey );
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003374 if (!lpkey)
3375 return ERROR_INVALID_HANDLE;
3376
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003377 if (lpszValue) {
3378 for (i=0;i<lpkey->nrofvalues;i++)
Alexandre Julliard0e270f41996-08-24 18:26:35 +00003379 if ( lpkey->values[i].name &&
Alexandre Julliarda3960291999-02-26 11:11:13 +00003380 !lstrcmpiW(lpkey->values[i].name,lpszValue)
Alexandre Julliard0e270f41996-08-24 18:26:35 +00003381 )
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003382 break;
3383 } else {
3384 for (i=0;i<lpkey->nrofvalues;i++)
3385 if (lpkey->values[i].name==NULL)
3386 break;
3387 }
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003388
3389 if (i == lpkey->nrofvalues)
3390 return ERROR_FILE_NOT_FOUND;
3391
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003392 val = lpkey->values+i;
3393 if (val->name) free(val->name);
3394 if (val->data) free(val->data);
3395 memcpy(
3396 lpkey->values+i,
3397 lpkey->values+i+1,
3398 sizeof(KEYVALUE)*(lpkey->nrofvalues-i-1)
3399 );
3400 lpkey->values = (LPKEYVALUE)xrealloc(
3401 lpkey->values,
3402 (lpkey->nrofvalues-1)*sizeof(KEYVALUE)
3403 );
3404 lpkey->nrofvalues--;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003405 return ERROR_SUCCESS;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003406}
3407
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003408
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003409/******************************************************************************
3410 * RegDeleteValue32A [ADVAPI32.135]
3411 */
Huw D M Daviesdf088c61999-07-10 11:41:24 +00003412DWORD WINAPI RegDeleteValueA( HKEY hkey, LPCSTR lpszValue )
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003413{
3414 LPWSTR lpszValueW;
3415 DWORD ret;
3416
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003417 TRACE_(reg)("(%x,%s)\n",hkey,debugstr_a(lpszValue));
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003418 lpszValueW = lpszValue?strdupA2W(lpszValue):NULL;
Alexandre Julliarda3960291999-02-26 11:11:13 +00003419 ret = RegDeleteValueW( hkey, lpszValueW );
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003420 if(lpszValueW) free(lpszValueW);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003421 return ret;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003422}
3423
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003424
3425/******************************************************************************
3426 * RegDeleteValue16 [KERNEL.222]
3427 */
3428DWORD WINAPI RegDeleteValue16( HKEY hkey, LPSTR lpszValue )
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003429{
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003430 TRACE_(reg)("(%x,%s)\n", hkey,debugstr_a(lpszValue));
Alexandre Julliarda3960291999-02-26 11:11:13 +00003431 return RegDeleteValueA( hkey, lpszValue );
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003432}
3433
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00003434
3435/******************************************************************************
3436 * RegFlushKey [KERNEL.227] [ADVAPI32.143]
3437 * Writes key to registry
3438 *
3439 * PARAMS
3440 * hkey [I] Handle of key to write
3441 *
3442 * RETURNS
3443 * Success: ERROR_SUCCESS
3444 * Failure: Error code
3445 */
3446DWORD WINAPI RegFlushKey( HKEY hkey )
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003447{
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003448 LPKEYSTRUCT lpkey;
Alexandre Julliarda3960291999-02-26 11:11:13 +00003449 BOOL ret;
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003450
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003451 TRACE_(reg)("(%x)\n", hkey);
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003452
3453 lpkey = lookup_hkey( hkey );
3454 if (!lpkey)
Andreas Mohr743885a1999-02-13 12:40:22 +00003455 return ERROR_BADKEY;
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003456
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003457 ERR_(reg)("What is the correct filename?\n");
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003458
3459 ret = _savereg( lpkey, "foo.bar", TRUE);
3460
3461 if( ret ) {
3462 return ERROR_SUCCESS;
3463 } else
3464 return ERROR_UNKNOWN; /* FIXME */
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003465}
3466
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00003467
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003468/* FIXME: lpcchXXXX ... is this counting in WCHARS or in BYTEs ?? */
3469
Alexandre Julliard642d3131998-07-12 19:29:36 +00003470
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003471/******************************************************************************
3472 * RegQueryInfoKey32W [ADVAPI32.153]
Alexandre Julliard642d3131998-07-12 19:29:36 +00003473 *
3474 * PARAMS
3475 * hkey [I] Handle to key to query
3476 * lpszClass [O] Buffer for class string
3477 * lpcchClass [O] Size of class string buffer
3478 * lpdwReserved [I] Reserved
3479 * lpcSubKeys [I] Buffer for number of subkeys
3480 * lpcchMaxSubKey [O] Buffer for longest subkey name length
3481 * lpcchMaxClass [O] Buffer for longest class string length
3482 * lpcValues [O] Buffer for number of value entries
3483 * lpcchMaxValueName [O] Buffer for longest value name length
3484 * lpccbMaxValueData [O] Buffer for longest value data length
3485 * lpcbSecurityDescriptor [O] Buffer for security descriptor length
3486 * ft
John Richardson2bb013b1998-11-06 17:36:13 +00003487 * - win95 allows lpszClass to be valid and lpcchClass to be NULL
3488 * - winnt returns ERROR_INVALID_PARAMETER if lpszClass is valid and
3489 * lpcchClass is NULL
3490 * - both allow lpszClass to be NULL and lpcchClass to be NULL
3491 * (it's hard to test validity, so test !NULL instead)
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003492 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003493DWORD WINAPI RegQueryInfoKeyW( HKEY hkey, LPWSTR lpszClass,
Alexandre Julliard642d3131998-07-12 19:29:36 +00003494 LPDWORD lpcchClass, LPDWORD lpdwReserved,
3495 LPDWORD lpcSubKeys, LPDWORD lpcchMaxSubkey,
3496 LPDWORD lpcchMaxClass, LPDWORD lpcValues,
3497 LPDWORD lpcchMaxValueName,
3498 LPDWORD lpccbMaxValueData,
3499 LPDWORD lpcbSecurityDescriptor, FILETIME *ft )
3500{
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003501 LPKEYSTRUCT lpkey,lpxkey;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003502 int nrofkeys,maxsubkey,maxclass,maxvname,maxvdata;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003503 int i;
3504
Marcus Meissner450bc791999-05-09 15:59:27 +00003505 TRACE_(reg)("(%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n",
3506 hkey, lpszClass, lpcchClass?*lpcchClass:0,lpdwReserved,
3507 lpcSubKeys,lpcchMaxSubkey,lpcValues,lpcchMaxValueName,
3508 lpccbMaxValueData,lpcbSecurityDescriptor,ft
3509 );
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003510 lpkey = lookup_hkey(hkey);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003511 if (!lpkey)
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003512 return ERROR_INVALID_HANDLE;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003513 if (lpszClass) {
John Richardson2bb013b1998-11-06 17:36:13 +00003514 if (VERSION_GetVersion() == NT40 && lpcchClass == NULL) {
3515 return ERROR_INVALID_PARAMETER;
3516 }
3517 /* either lpcchClass is valid or this is win95 and lpcchClass
3518 could be invalid */
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003519 if (lpkey->class) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00003520 DWORD classLen = lstrlenW(lpkey->class);
John Richardson2bb013b1998-11-06 17:36:13 +00003521
3522 if (lpcchClass && classLen+1>*lpcchClass) {
3523 *lpcchClass=classLen+1;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003524 return ERROR_MORE_DATA;
3525 }
John Richardson2bb013b1998-11-06 17:36:13 +00003526 if (lpcchClass)
3527 *lpcchClass=classLen;
3528 memcpy(lpszClass,lpkey->class, classLen*2 + 2);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003529 } else {
3530 *lpszClass = 0;
John Richardson2bb013b1998-11-06 17:36:13 +00003531 if (lpcchClass)
3532 *lpcchClass = 0;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003533 }
3534 } else {
3535 if (lpcchClass)
Alexandre Julliarda3960291999-02-26 11:11:13 +00003536 *lpcchClass = lstrlenW(lpkey->class);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003537 }
3538 lpxkey=lpkey->nextsub;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003539 nrofkeys=maxsubkey=maxclass=maxvname=maxvdata=0;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003540 while (lpxkey) {
3541 nrofkeys++;
Alexandre Julliarda3960291999-02-26 11:11:13 +00003542 if (lstrlenW(lpxkey->keyname)>maxsubkey)
3543 maxsubkey=lstrlenW(lpxkey->keyname);
3544 if (lpxkey->class && lstrlenW(lpxkey->class)>maxclass)
3545 maxclass=lstrlenW(lpxkey->class);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003546 lpxkey=lpxkey->next;
3547 }
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003548 for (i=0;i<lpkey->nrofvalues;i++) {
3549 LPKEYVALUE val=lpkey->values+i;
3550
Alexandre Julliarda3960291999-02-26 11:11:13 +00003551 if (val->name && lstrlenW(val->name)>maxvname)
3552 maxvname=lstrlenW(val->name);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003553 if (val->len>maxvdata)
3554 maxvdata=val->len;
3555 }
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003556 if (!maxclass) maxclass = 1;
3557 if (!maxvname) maxvname = 1;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003558 if (lpcValues)
3559 *lpcValues = lpkey->nrofvalues;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003560 if (lpcSubKeys)
3561 *lpcSubKeys = nrofkeys;
3562 if (lpcchMaxSubkey)
John Richardson2bb013b1998-11-06 17:36:13 +00003563 *lpcchMaxSubkey = maxsubkey;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003564 if (lpcchMaxClass)
John Richardson2bb013b1998-11-06 17:36:13 +00003565 *lpcchMaxClass = maxclass;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003566 if (lpcchMaxValueName)
3567 *lpcchMaxValueName= maxvname;
3568 if (lpccbMaxValueData)
3569 *lpccbMaxValueData= maxvdata;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003570 return ERROR_SUCCESS;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003571}
3572
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003573
Alexandre Julliard642d3131998-07-12 19:29:36 +00003574/******************************************************************************
3575 * RegQueryInfoKey32A [ADVAPI32.152]
3576 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003577DWORD WINAPI RegQueryInfoKeyA( HKEY hkey, LPSTR lpszClass, LPDWORD lpcchClass,
Alexandre Julliard642d3131998-07-12 19:29:36 +00003578 LPDWORD lpdwReserved, LPDWORD lpcSubKeys,
3579 LPDWORD lpcchMaxSubkey, LPDWORD lpcchMaxClass,
3580 LPDWORD lpcValues, LPDWORD lpcchMaxValueName,
3581 LPDWORD lpccbMaxValueData,
3582 LPDWORD lpcbSecurityDescriptor, FILETIME *ft )
3583{
John Richardson2bb013b1998-11-06 17:36:13 +00003584 LPWSTR lpszClassW = NULL;
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003585 DWORD ret;
3586
Marcus Meissner450bc791999-05-09 15:59:27 +00003587 TRACE_(reg)("(%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n",
3588 hkey, lpszClass, lpcchClass?*lpcchClass:0,lpdwReserved,
3589 lpcSubKeys,lpcchMaxSubkey,lpcValues,lpcchMaxValueName,
3590 lpccbMaxValueData,lpcbSecurityDescriptor,ft
3591 );
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003592 if (lpszClass) {
John Richardson2bb013b1998-11-06 17:36:13 +00003593 if (lpcchClass) {
3594 lpszClassW = (LPWSTR)xmalloc((*lpcchClass) * 2);
3595 } else if (VERSION_GetVersion() == WIN95) {
3596 /* win95 allows lpcchClass to be null */
3597 /* we don't know how big lpszClass is, would
3598 MAX_PATHNAME_LEN be the correct default? */
3599 lpszClassW = (LPWSTR)xmalloc(MAX_PATHNAME_LEN*2);
3600 }
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003601
3602 } else
3603 lpszClassW = NULL;
Alexandre Julliarda3960291999-02-26 11:11:13 +00003604 ret=RegQueryInfoKeyW(
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003605 hkey,
3606 lpszClassW,
3607 lpcchClass,
3608 lpdwReserved,
3609 lpcSubKeys,
3610 lpcchMaxSubkey,
3611 lpcchMaxClass,
3612 lpcValues,
3613 lpcchMaxValueName,
3614 lpccbMaxValueData,
3615 lpcbSecurityDescriptor,
3616 ft
3617 );
Alexandre Julliard641ee761997-08-04 16:34:36 +00003618 if (ret==ERROR_SUCCESS && lpszClass)
Alexandre Julliard7ebe1a41996-12-22 18:27:48 +00003619 lstrcpyWtoA(lpszClass,lpszClassW);
Alexandre Julliardc981d0b1996-03-31 16:40:13 +00003620 if (lpszClassW)
3621 free(lpszClassW);
3622 return ret;
3623}
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003624
3625
3626/******************************************************************************
3627 * RegConnectRegistry32W [ADVAPI32.128]
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003628 *
3629 * PARAMS
3630 * lpMachineName [I] Address of name of remote computer
3631 * hHey [I] Predefined registry handle
3632 * phkResult [I] Address of buffer for remote registry handle
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003633 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003634LONG WINAPI RegConnectRegistryW( LPCWSTR lpMachineName, HKEY hKey,
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003635 LPHKEY phkResult )
Alexandre Julliard670cdc41997-08-24 16:00:30 +00003636{
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003637 TRACE_(reg)("(%s,%x,%p): stub\n",debugstr_w(lpMachineName),hKey,phkResult);
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003638
3639 if (!lpMachineName || !*lpMachineName) {
3640 /* Use the local machine name */
3641 return RegOpenKey16( hKey, "", phkResult );
3642 }
3643
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003644 FIXME_(reg)("Cannot connect to %s\n",debugstr_w(lpMachineName));
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003645 return ERROR_BAD_NETPATH;
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003646}
3647
3648
3649/******************************************************************************
3650 * RegConnectRegistry32A [ADVAPI32.127]
3651 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003652LONG WINAPI RegConnectRegistryA( LPCSTR machine, HKEY hkey, LPHKEY reskey )
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003653{
3654 DWORD ret;
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003655 LPWSTR machineW = strdupA2W(machine);
Alexandre Julliarda3960291999-02-26 11:11:13 +00003656 ret = RegConnectRegistryW( machineW, hkey, reskey );
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003657 free(machineW);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003658 return ret;
Alexandre Julliard01d63461997-01-20 19:43:45 +00003659}
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00003660
3661
3662/******************************************************************************
3663 * RegGetKeySecurity [ADVAPI32.144]
3664 * Retrieves a copy of security descriptor protecting the registry key
3665 *
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003666 * PARAMS
3667 * hkey [I] Open handle of key to set
3668 * SecurityInformation [I] Descriptor contents
3669 * pSecurityDescriptor [O] Address of descriptor for key
3670 * lpcbSecurityDescriptor [I/O] Address of size of buffer and description
3671 *
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00003672 * RETURNS
3673 * Success: ERROR_SUCCESS
3674 * Failure: Error code
3675 */
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003676LONG WINAPI RegGetKeySecurity( HKEY hkey,
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00003677 SECURITY_INFORMATION SecurityInformation,
Juergen Schmied1ed51af1999-02-12 17:47:07 +00003678 PSECURITY_DESCRIPTOR pSecurityDescriptor,
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00003679 LPDWORD lpcbSecurityDescriptor )
3680{
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003681 LPKEYSTRUCT lpkey;
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003682
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003683 TRACE_(reg)("(%x,%ld,%p,%ld)\n",hkey,SecurityInformation,pSecurityDescriptor,
Alexandre Julliard642d3131998-07-12 19:29:36 +00003684 lpcbSecurityDescriptor?*lpcbSecurityDescriptor:0);
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003685
3686 lpkey = lookup_hkey( hkey );
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003687 if (!lpkey)
3688 return ERROR_INVALID_HANDLE;
3689
Alexandre Julliard642d3131998-07-12 19:29:36 +00003690 /* FIXME: Check for valid SecurityInformation values */
3691
Alexandre Julliardb24fc081999-02-25 16:36:07 +00003692 if (*lpcbSecurityDescriptor < sizeof(SECURITY_DESCRIPTOR))
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003693 return ERROR_INSUFFICIENT_BUFFER;
3694
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003695 FIXME_(reg)("(%x,%ld,%p,%ld): stub\n",hkey,SecurityInformation,
Alexandre Julliard642d3131998-07-12 19:29:36 +00003696 pSecurityDescriptor,lpcbSecurityDescriptor?*lpcbSecurityDescriptor:0);
3697
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00003698 return ERROR_SUCCESS;
3699}
3700
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003701
3702/******************************************************************************
3703 * RegLoadKey32W [ADVAPI32.???]
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003704 *
3705 * PARAMS
3706 * hkey [I] Handle of open key
3707 * lpszSubKey [I] Address of name of subkey
3708 * lpszFile [I] Address of filename for registry information
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003709 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003710LONG WINAPI RegLoadKeyW( HKEY hkey, LPCWSTR lpszSubKey, LPCWSTR lpszFile )
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003711{
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003712 LPKEYSTRUCT lpkey;
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003713 TRACE_(reg)("(%x,%s,%s)\n",hkey,debugstr_w(lpszSubKey),debugstr_w(lpszFile));
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003714
3715 /* Do this check before the hkey check */
3716 if (!lpszSubKey || !*lpszSubKey || !lpszFile || !*lpszFile)
3717 return ERROR_INVALID_PARAMETER;
3718
3719 lpkey = lookup_hkey( hkey );
3720 if (!lpkey)
3721 return ERROR_INVALID_HANDLE;
3722
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003723 FIXME_(reg)("(%x,%s,%s): stub\n",hkey,debugstr_w(lpszSubKey),
Alexandre Julliard642d3131998-07-12 19:29:36 +00003724 debugstr_w(lpszFile));
3725
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003726 return ERROR_SUCCESS;
3727}
3728
3729
3730/******************************************************************************
3731 * RegLoadKey32A [ADVAPI32.???]
3732 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003733LONG WINAPI RegLoadKeyA( HKEY hkey, LPCSTR lpszSubKey, LPCSTR lpszFile )
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003734{
3735 LONG ret;
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003736 LPWSTR lpszSubKeyW = strdupA2W(lpszSubKey);
3737 LPWSTR lpszFileW = strdupA2W(lpszFile);
Alexandre Julliarda3960291999-02-26 11:11:13 +00003738 ret = RegLoadKeyW( hkey, lpszSubKeyW, lpszFileW );
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003739 if(lpszFileW) free(lpszFileW);
3740 if(lpszSubKeyW) free(lpszSubKeyW);
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003741 return ret;
3742}
3743
3744
3745/******************************************************************************
3746 * RegNotifyChangeKeyValue [ADVAPI32.???]
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003747 *
3748 * PARAMS
3749 * hkey [I] Handle of key to watch
3750 * fWatchSubTree [I] Flag for subkey notification
3751 * fdwNotifyFilter [I] Changes to be reported
3752 * hEvent [I] Handle of signaled event
3753 * fAsync [I] Flag for asynchronous reporting
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003754 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003755LONG WINAPI RegNotifyChangeKeyValue( HKEY hkey, BOOL fWatchSubTree,
3756 DWORD fdwNotifyFilter, HANDLE hEvent,
3757 BOOL fAsync )
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003758{
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003759 LPKEYSTRUCT lpkey;
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003760 TRACE_(reg)("(%x,%i,%ld,%x,%i)\n",hkey,fWatchSubTree,fdwNotifyFilter,
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003761 hEvent,fAsync);
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003762
3763 lpkey = lookup_hkey( hkey );
3764 if (!lpkey)
3765 return ERROR_INVALID_HANDLE;
3766
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003767 FIXME_(reg)("(%x,%i,%ld,%x,%i): stub\n",hkey,fWatchSubTree,fdwNotifyFilter,
Alexandre Julliard642d3131998-07-12 19:29:36 +00003768 hEvent,fAsync);
3769
Alexandre Julliarddadf78f1998-05-17 17:13:43 +00003770 return ERROR_SUCCESS;
3771}
3772
Alexandre Julliarda845b881998-06-01 10:44:35 +00003773
3774/******************************************************************************
3775 * RegUnLoadKey32W [ADVAPI32.173]
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003776 *
3777 * PARAMS
3778 * hkey [I] Handle of open key
3779 * lpSubKey [I] Address of name of subkey to unload
Alexandre Julliarda845b881998-06-01 10:44:35 +00003780 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003781LONG WINAPI RegUnLoadKeyW( HKEY hkey, LPCWSTR lpSubKey )
Alexandre Julliarda845b881998-06-01 10:44:35 +00003782{
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003783 FIXME_(reg)("(%x,%s): stub\n",hkey, debugstr_w(lpSubKey));
Alexandre Julliarda845b881998-06-01 10:44:35 +00003784 return ERROR_SUCCESS;
3785}
3786
3787
3788/******************************************************************************
3789 * RegUnLoadKey32A [ADVAPI32.172]
3790 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003791LONG WINAPI RegUnLoadKeyA( HKEY hkey, LPCSTR lpSubKey )
Alexandre Julliarda845b881998-06-01 10:44:35 +00003792{
3793 LONG ret;
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003794 LPWSTR lpSubKeyW = strdupA2W(lpSubKey);
Alexandre Julliarda3960291999-02-26 11:11:13 +00003795 ret = RegUnLoadKeyW( hkey, lpSubKeyW );
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003796 if(lpSubKeyW) free(lpSubKeyW);
Alexandre Julliarda845b881998-06-01 10:44:35 +00003797 return ret;
3798}
3799
3800
3801/******************************************************************************
3802 * RegSetKeySecurity [ADVAPI32.167]
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003803 *
3804 * PARAMS
3805 * hkey [I] Open handle of key to set
3806 * SecurityInfo [I] Descriptor contents
3807 * pSecurityDesc [I] Address of descriptor for key
Alexandre Julliarda845b881998-06-01 10:44:35 +00003808 */
3809LONG WINAPI RegSetKeySecurity( HKEY hkey, SECURITY_INFORMATION SecurityInfo,
Juergen Schmied1ed51af1999-02-12 17:47:07 +00003810 PSECURITY_DESCRIPTOR pSecurityDesc )
Alexandre Julliarda845b881998-06-01 10:44:35 +00003811{
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003812 LPKEYSTRUCT lpkey;
3813
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003814 TRACE_(reg)("(%x,%ld,%p)\n",hkey,SecurityInfo,pSecurityDesc);
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003815
3816 /* It seems to perform this check before the hkey check */
3817 if ((SecurityInfo & OWNER_SECURITY_INFORMATION) ||
3818 (SecurityInfo & GROUP_SECURITY_INFORMATION) ||
3819 (SecurityInfo & DACL_SECURITY_INFORMATION) ||
3820 (SecurityInfo & SACL_SECURITY_INFORMATION)) {
3821 /* Param OK */
3822 } else
3823 return ERROR_INVALID_PARAMETER;
3824
3825 if (!pSecurityDesc)
3826 return ERROR_INVALID_PARAMETER;
3827
3828 lpkey = lookup_hkey( hkey );
3829 if (!lpkey)
3830 return ERROR_INVALID_HANDLE;
3831
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003832 FIXME_(reg)(":(%x,%ld,%p): stub\n",hkey,SecurityInfo,pSecurityDesc);
Alexandre Julliard642d3131998-07-12 19:29:36 +00003833
Alexandre Julliarda845b881998-06-01 10:44:35 +00003834 return ERROR_SUCCESS;
3835}
3836
3837
3838/******************************************************************************
3839 * RegSaveKey32W [ADVAPI32.166]
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003840 *
3841 * PARAMS
3842 * hkey [I] Handle of key where save begins
3843 * lpFile [I] Address of filename to save to
3844 * sa [I] Address of security structure
Alexandre Julliarda845b881998-06-01 10:44:35 +00003845 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003846LONG WINAPI RegSaveKeyW( HKEY hkey, LPCWSTR lpFile,
Alexandre Julliarda845b881998-06-01 10:44:35 +00003847 LPSECURITY_ATTRIBUTES sa )
3848{
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003849 LPKEYSTRUCT lpkey;
3850
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003851 TRACE_(reg)("(%x,%s,%p)\n", hkey, debugstr_w(lpFile), sa);
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003852
3853 /* It appears to do this check before the hkey check */
3854 if (!lpFile || !*lpFile)
3855 return ERROR_INVALID_PARAMETER;
3856
3857 lpkey = lookup_hkey( hkey );
3858 if (!lpkey)
3859 return ERROR_INVALID_HANDLE;
3860
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003861 FIXME_(reg)("(%x,%s,%p): stub\n", hkey, debugstr_w(lpFile), sa);
Alexandre Julliard642d3131998-07-12 19:29:36 +00003862
Alexandre Julliarda845b881998-06-01 10:44:35 +00003863 return ERROR_SUCCESS;
3864}
3865
3866
3867/******************************************************************************
3868 * RegSaveKey32A [ADVAPI32.165]
3869 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003870LONG WINAPI RegSaveKeyA( HKEY hkey, LPCSTR lpFile,
Alexandre Julliarda845b881998-06-01 10:44:35 +00003871 LPSECURITY_ATTRIBUTES sa )
3872{
3873 LONG ret;
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003874 LPWSTR lpFileW = strdupA2W(lpFile);
Alexandre Julliarda3960291999-02-26 11:11:13 +00003875 ret = RegSaveKeyW( hkey, lpFileW, sa );
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003876 free(lpFileW);
Alexandre Julliarda845b881998-06-01 10:44:35 +00003877 return ret;
3878}
3879
3880
3881/******************************************************************************
3882 * RegRestoreKey32W [ADVAPI32.164]
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003883 *
3884 * PARAMS
3885 * hkey [I] Handle of key where restore begins
3886 * lpFile [I] Address of filename containing saved tree
3887 * dwFlags [I] Optional flags
Alexandre Julliarda845b881998-06-01 10:44:35 +00003888 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003889LONG WINAPI RegRestoreKeyW( HKEY hkey, LPCWSTR lpFile, DWORD dwFlags )
Alexandre Julliarda845b881998-06-01 10:44:35 +00003890{
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003891 LPKEYSTRUCT lpkey;
Alexandre Julliard642d3131998-07-12 19:29:36 +00003892
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003893 TRACE_(reg)("(%x,%s,%ld)\n",hkey,debugstr_w(lpFile),dwFlags);
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003894
3895 /* It seems to do this check before the hkey check */
3896 if (!lpFile || !*lpFile)
3897 return ERROR_INVALID_PARAMETER;
3898
3899 lpkey = lookup_hkey( hkey );
3900 if (!lpkey)
3901 return ERROR_INVALID_HANDLE;
3902
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003903 FIXME_(reg)("(%x,%s,%ld): stub\n",hkey,debugstr_w(lpFile),dwFlags);
Alexandre Julliard642d3131998-07-12 19:29:36 +00003904
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003905 /* Check for file existence */
3906
Alexandre Julliarda845b881998-06-01 10:44:35 +00003907 return ERROR_SUCCESS;
3908}
3909
3910
3911/******************************************************************************
3912 * RegRestoreKey32A [ADVAPI32.163]
3913 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003914LONG WINAPI RegRestoreKeyA( HKEY hkey, LPCSTR lpFile, DWORD dwFlags )
Alexandre Julliarda845b881998-06-01 10:44:35 +00003915{
3916 LONG ret;
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003917 LPWSTR lpFileW = strdupA2W(lpFile);
Alexandre Julliarda3960291999-02-26 11:11:13 +00003918 ret = RegRestoreKeyW( hkey, lpFileW, dwFlags );
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003919 if(lpFileW) free(lpFileW);
Alexandre Julliarda845b881998-06-01 10:44:35 +00003920 return ret;
3921}
3922
3923
3924/******************************************************************************
3925 * RegReplaceKey32W [ADVAPI32.162]
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003926 *
3927 * PARAMS
3928 * hkey [I] Handle of open key
3929 * lpSubKey [I] Address of name of subkey
3930 * lpNewFile [I] Address of filename for file with new data
3931 * lpOldFile [I] Address of filename for backup file
Alexandre Julliarda845b881998-06-01 10:44:35 +00003932 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003933LONG WINAPI RegReplaceKeyW( HKEY hkey, LPCWSTR lpSubKey, LPCWSTR lpNewFile,
Alexandre Julliarda845b881998-06-01 10:44:35 +00003934 LPCWSTR lpOldFile )
3935{
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003936 LPKEYSTRUCT lpkey;
3937
Alexandre Julliard06c275a1999-05-02 14:32:27 +00003938 TRACE_(reg)("(%x,%s,%s,%s)\n",hkey,debugstr_w(lpSubKey),
Alexandre Julliarda845b881998-06-01 10:44:35 +00003939 debugstr_w(lpNewFile),debugstr_w(lpOldFile));
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003940
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,%s,%s): stub\n", hkey, debugstr_w(lpSubKey),
Alexandre Julliard642d3131998-07-12 19:29:36 +00003946 debugstr_w(lpNewFile),debugstr_w(lpOldFile));
3947
Alexandre Julliarda845b881998-06-01 10:44:35 +00003948 return ERROR_SUCCESS;
3949}
3950
3951
3952/******************************************************************************
3953 * RegReplaceKey32A [ADVAPI32.161]
3954 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00003955LONG WINAPI RegReplaceKeyA( HKEY hkey, LPCSTR lpSubKey, LPCSTR lpNewFile,
Alexandre Julliarda845b881998-06-01 10:44:35 +00003956 LPCSTR lpOldFile )
3957{
3958 LONG ret;
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003959 LPWSTR lpSubKeyW = strdupA2W(lpSubKey);
3960 LPWSTR lpNewFileW = strdupA2W(lpNewFile);
3961 LPWSTR lpOldFileW = strdupA2W(lpOldFile);
Alexandre Julliarda3960291999-02-26 11:11:13 +00003962 ret = RegReplaceKeyW( hkey, lpSubKeyW, lpNewFileW, lpOldFileW );
Alexandre Julliardf90efa91998-06-14 15:24:15 +00003963 free(lpOldFileW);
3964 free(lpNewFileW);
3965 free(lpSubKeyW);
Alexandre Julliarda845b881998-06-01 10:44:35 +00003966 return ret;
3967}
3968