r19991: Sorry for this 2000-liner...
[tprouty/samba.git] / source3 / rpc_server / srv_winreg_nt.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  * 
5  *  Copyright (C) Gerald Carter                 2002-2006.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  *  
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *  
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21
22 /* Implementation of registry functions. */
23
24 #include "includes.h"
25 #include "regfio.h"
26
27 #undef DBGC_CLASS
28 #define DBGC_CLASS DBGC_RPC_SRV
29
30 static struct generic_mapping reg_generic_map = 
31         { REG_KEY_READ, REG_KEY_WRITE, REG_KEY_EXECUTE, REG_KEY_ALL };
32
33 /******************************************************************
34  free() function for struct regkey_info
35  *****************************************************************/
36  
37 static void free_regkey(void *ptr)
38 {
39         struct registry_key *key = (struct registry_key *)ptr;
40         TALLOC_FREE(key);
41 }
42
43 /******************************************************************
44  Find a registry key handle and return a REGISTRY_KEY
45  *****************************************************************/
46
47 static struct registry_key *find_regkey_by_hnd(pipes_struct *p,
48                                                POLICY_HND *hnd)
49 {
50         struct registry_key *regkey = NULL;
51
52         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&regkey)) {
53                 DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: "));
54                 return NULL;
55         }
56
57         return regkey;
58 }
59
60 /*******************************************************************
61  Function for open a new registry handle and creating a handle 
62  Note that P should be valid & hnd should already have space
63  
64  When we open a key, we store the full path to the key as 
65  HK[LM|U]\<key>\<key>\...
66  *******************************************************************/
67  
68 static WERROR open_registry_key( pipes_struct *p, POLICY_HND *hnd, 
69                                  struct registry_key *parent,
70                                  const char *subkeyname,
71                                  uint32 access_desired  )
72 {
73         WERROR result = WERR_OK;
74         struct registry_key *key;
75
76         /* now do the internal open */
77
78         if (parent == NULL) {
79                 result = reg_openhive(NULL, subkeyname, access_desired,
80                                       p->pipe_user.nt_user_token, &key);
81         }
82         else {
83                 result = reg_openkey(NULL, parent, subkeyname, access_desired,
84                                      &key);
85         }
86
87         if ( !W_ERROR_IS_OK(result) ) {
88                 return result;
89         }
90         
91         if ( !create_policy_hnd( p, hnd, free_regkey, key ) ) {
92                 return WERR_BADFILE; 
93         }
94         
95         return WERR_OK;;
96 }
97
98 /*******************************************************************
99  Function for open a new registry handle and creating a handle 
100  Note that P should be valid & hnd should already have space
101  *******************************************************************/
102
103 static BOOL close_registry_key(pipes_struct *p, POLICY_HND *hnd)
104 {
105         struct registry_key *regkey = find_regkey_by_hnd(p, hnd);
106         
107         if ( !regkey ) {
108                 DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n",
109                          OUR_HANDLE(hnd)));
110                 return False;
111         }
112         
113         close_policy_hnd(p, hnd);
114         
115         return True;
116 }
117
118 /********************************************************************
119  reg_close
120  ********************************************************************/
121
122 WERROR _winreg_CloseKey(pipes_struct *p, struct policy_handle *handle)
123 {
124         /* close the policy handle */
125
126         if (!close_registry_key(p, handle))
127                 return WERR_BADFID; 
128
129         return WERR_OK;
130 }
131
132 /*******************************************************************
133  ********************************************************************/
134
135 WERROR _winreg_OpenHKLM(pipes_struct *p, uint16_t *system_name, uint32_t access_mask, struct policy_handle *handle)
136 {
137         return open_registry_key(p, handle, NULL, KEY_HKLM, access_mask);
138 }
139
140 /*******************************************************************
141  ********************************************************************/
142
143 WERROR _winreg_OpenHKPD(pipes_struct *p, uint16_t *system_name,
144                         uint32_t access_mask, struct policy_handle *handle)
145 {
146         return open_registry_key(p, handle, NULL, KEY_HKPD, access_mask);
147 }
148
149 /*******************************************************************
150  ********************************************************************/
151
152 WERROR _winreg_OpenHKPT(pipes_struct *p, uint16_t *system_name,
153                         uint32_t access_mask, struct policy_handle *handle)
154 {
155         return open_registry_key(p, handle, NULL, KEY_HKPT, access_mask);
156 }
157
158 /*******************************************************************
159  ********************************************************************/
160
161 WERROR _winreg_OpenHKCR(pipes_struct *p, uint16_t *system_name,
162                         uint32_t access_mask, struct policy_handle *handle)
163 {
164         return open_registry_key(p, handle, NULL, KEY_HKCR, access_mask);
165 }
166
167 /*******************************************************************
168  ********************************************************************/
169
170 WERROR _winreg_OpenHKU(pipes_struct *p, uint16_t *system_name,
171                        uint32_t access_mask, struct policy_handle *handle)
172 {
173         return open_registry_key(p, handle, NULL, KEY_HKU, access_mask);
174 }
175
176 /*******************************************************************
177  ********************************************************************/
178
179 WERROR _winreg_OpenHKCU(pipes_struct *p, uint16_t *system_name,
180                         uint32_t access_mask, struct policy_handle *handle)
181 {
182         return open_registry_key(p, handle, NULL, KEY_HKCU, access_mask);
183 }
184
185 /*******************************************************************
186  ********************************************************************/
187
188 WERROR _winreg_OpenHKCC(pipes_struct *p, uint16_t *system_name,
189                         uint32_t access_mask, struct policy_handle *handle)
190 {
191         return open_registry_key(p, handle, NULL, KEY_HKCC, access_mask);
192 }
193
194 /*******************************************************************
195  ********************************************************************/
196
197 WERROR _winreg_OpenHKDD(pipes_struct *p, uint16_t *system_name,
198                         uint32_t access_mask, struct policy_handle *handle)
199 {
200         return open_registry_key(p, handle, NULL, KEY_HKDD, access_mask);
201 }
202
203 /*******************************************************************
204  ********************************************************************/
205
206 WERROR _winreg_OpenHKPN(pipes_struct *p, uint16_t *system_name,
207                         uint32_t access_mask, struct policy_handle *handle)
208 {
209         return open_registry_key(p, handle, NULL, KEY_HKPN, access_mask);
210 }
211
212 /*******************************************************************
213  reg_reply_open_entry
214  ********************************************************************/
215
216 WERROR _winreg_OpenKey(pipes_struct *p, struct policy_handle *parent_handle,
217                        struct winreg_String keyname, uint32_t unknown,
218                        uint32_t access_mask, struct policy_handle *handle)
219 {
220         struct registry_key *parent = find_regkey_by_hnd(p, parent_handle );
221
222         if ( !parent )
223                 return WERR_BADFID;
224
225         return open_registry_key(p, handle, parent, keyname.name, access_mask);
226 }
227
228 /*******************************************************************
229  reg_reply_info
230  ********************************************************************/
231
232 WERROR _winreg_QueryValue(pipes_struct *p, struct policy_handle *handle,
233                           struct winreg_String value_name,
234                           enum winreg_Type *type, uint8_t *data,
235                           uint32_t *data_size, uint32_t *value_length)
236 {
237         WERROR        status = WERR_BADFILE;
238         struct registry_key *regkey = find_regkey_by_hnd( p, handle );
239         prs_struct    prs_hkpd;
240
241         uint8_t *outbuf;
242         uint32_t outbuf_size;
243
244         DATA_BLOB val_blob;
245         BOOL free_buf = False;
246         BOOL free_prs = False;
247
248         if ( !regkey )
249                 return WERR_BADFID;
250
251         *value_length = *type = 0;
252         
253         DEBUG(7,("_reg_info: policy key name = [%s]\n", regkey->key->name));
254         DEBUG(7,("_reg_info: policy key type = [%08x]\n", regkey->key->type));
255         
256         /* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */
257         if(regkey->key->type == REG_KEY_HKPD) 
258         {
259                 if(strequal(value_name.name, "Global")) {
260                         prs_init(&prs_hkpd, *data_size, p->mem_ctx, MARSHALL);
261                         status = reg_perfcount_get_hkpd(
262                                 &prs_hkpd, *data_size, &outbuf_size, NULL);
263                         outbuf = (uint8_t *)prs_hkpd.data_p;
264                         free_prs = True;
265                 }
266                 else if(strequal(value_name.name, "Counter 009")) {
267                         outbuf_size = reg_perfcount_get_counter_names(
268                                 reg_perfcount_get_base_index(),
269                                 (char **)(void *)&outbuf);
270                         free_buf = True;
271                 }
272                 else if(strequal(value_name.name, "Explain 009")) {
273                         outbuf_size = reg_perfcount_get_counter_help(
274                                 reg_perfcount_get_base_index(),
275                                 (char **)(void *)&outbuf);
276                         free_buf = True;
277                 }
278                 else if(isdigit(value_name.name[0])) {
279                         /* we probably have a request for a specific object
280                          * here */
281                         prs_init(&prs_hkpd, *data_size, p->mem_ctx, MARSHALL);
282                         status = reg_perfcount_get_hkpd(
283                                 &prs_hkpd, *data_size, &outbuf_size,
284                                 value_name.name);
285                         outbuf = (uint8_t *)prs_hkpd.data_p;
286                         free_prs = True;
287                 }
288                 else {
289                         DEBUG(3,("Unsupported key name [%s] for HKPD.\n",
290                                  value_name.name));
291                         return WERR_BADFILE;
292                 }
293
294                 *type = REG_BINARY;
295         }
296         else {
297                 struct registry_value *val;
298
299                 status = reg_queryvalue(p->mem_ctx, regkey, value_name.name,
300                                         &val);
301                 if (!W_ERROR_IS_OK(status)) {
302                         if (data_size) {
303                                 *data_size = 0;
304                         }
305                         if (value_length) {
306                                 *value_length = 0;
307                         }
308                         return status;
309                 }
310
311                 status = registry_push_value(p->mem_ctx, val, &val_blob);
312                 if (!W_ERROR_IS_OK(status)) {
313                         return status;
314                 }
315
316                 outbuf = val_blob.data;
317                 outbuf_size = val_blob.length;
318                 *type = val->type;
319         }
320
321         *value_length = outbuf_size;
322
323         if ( *data_size == 0 || !data ) {
324                 status = WERR_OK;
325         } else if ( *value_length > *data_size ) {
326                 status = WERR_MORE_DATA;
327         } else {
328                 memcpy( data, outbuf, *value_length );
329                 status = WERR_OK;
330         }
331
332         *data_size = *value_length;
333
334         if (free_prs) prs_mem_free(&prs_hkpd);
335         if (free_buf) SAFE_FREE(outbuf);
336
337         return status;
338 }
339
340 /*****************************************************************************
341  Implementation of REG_QUERY_KEY
342  ****************************************************************************/
343
344 WERROR _winreg_QueryInfoKey(pipes_struct *p, struct policy_handle *handle, 
345                             struct winreg_String *classname, 
346                             uint32_t *num_subkeys, uint32_t *max_subkeylen, 
347                             uint32_t *max_subkeysize, 
348                             uint32_t *num_values, uint32_t *max_valnamelen, 
349                             uint32_t *max_valbufsize, 
350                             uint32_t *secdescsize, NTTIME *last_changed_time)
351 {
352         WERROR  status = WERR_OK;
353         struct registry_key *regkey = find_regkey_by_hnd( p, handle );
354         
355         if ( !regkey )
356                 return WERR_BADFID;
357
358         classname->name = NULL;
359
360         status = reg_queryinfokey(regkey, num_subkeys, max_subkeylen,
361                                   max_subkeysize, num_values, max_valnamelen,
362                                   max_valbufsize, secdescsize,
363                                   last_changed_time);
364         if (!W_ERROR_IS_OK(status)) {
365                 return status;
366         }
367
368         /*
369          * These calculations account for the registry buffers being
370          * UTF-16. They are inexact at best, but so far they worked.
371          */
372
373         *max_subkeylen *= 2;
374
375         *max_valnamelen += 1;
376         *max_valnamelen *= 2;
377         
378         return WERR_OK;
379 }
380
381
382 /*****************************************************************************
383  Implementation of REG_GETVERSION
384  ****************************************************************************/
385  
386 WERROR _winreg_GetVersion(pipes_struct *p, struct policy_handle *handle, uint32_t *version)
387 {
388         struct registry_key *regkey = find_regkey_by_hnd( p, handle );
389         
390         if ( !regkey )
391                 return WERR_BADFID;
392         
393         *version = 0x00000005;  /* Windows 2000 registry API version */
394         
395         return WERR_OK;
396 }
397
398
399 /*****************************************************************************
400  Implementation of REG_ENUM_KEY
401  ****************************************************************************/
402  
403 WERROR _winreg_EnumKey(pipes_struct *p, struct policy_handle *handle, uint32_t enum_index, struct winreg_StringBuf *name, struct winreg_StringBuf *keyclass, NTTIME *last_changed_time)
404 {
405         WERROR err;
406         struct registry_key *key = find_regkey_by_hnd( p, handle );
407         
408         if ( !key )
409                 return WERR_BADFID; 
410
411         if ( !name || !keyclass )
412                 return WERR_INVALID_PARAM;
413
414         DEBUG(8,("_reg_enum_key: enumerating key [%s]\n", key->key->name));
415
416         err = reg_enumkey(p->mem_ctx, key, enum_index, (char **)&name->name,
417                           last_changed_time);
418         if (!W_ERROR_IS_OK(err)) {
419                 return err;
420         }
421         keyclass->name = "";
422         return WERR_OK;
423 }
424
425 /*****************************************************************************
426  Implementation of REG_ENUM_VALUE
427  ****************************************************************************/
428
429 WERROR _winreg_EnumValue(pipes_struct *p, struct policy_handle *handle,
430                          uint32_t enum_index, struct winreg_ValNameBuf *name,
431                          enum winreg_Type *type, uint8_t *data,
432                          uint32_t *data_size, uint32_t *value_length)
433 {
434         WERROR err;
435         struct registry_key *key = find_regkey_by_hnd( p, handle );
436         const char *valname;
437         struct registry_value *val;
438         DATA_BLOB value_blob;
439         
440         if ( !key )
441                 return WERR_BADFID;
442
443         if ( !name )
444                 return WERR_INVALID_PARAM;
445
446         DEBUG(8,("_winreg_EnumValue: enumerating values for key [%s]\n",
447                  key->key->name));
448
449         err = reg_enumvalue(p->mem_ctx, key, enum_index, &valname, &val);
450         if (!W_ERROR_IS_OK(err)) {
451                 return err;
452         }
453
454         err = registry_push_value(p->mem_ctx, val, &value_blob);
455         if (!W_ERROR_IS_OK(err)) {
456                 return err;
457         }
458
459         if (name != NULL) {
460                 name->name = valname;
461         }
462
463         if (type != NULL) {
464                 *type = val->type;
465         }
466
467         if (data != NULL) {
468                 if ((data_size == NULL) || (value_length == NULL)) {
469                         return WERR_INVALID_PARAM;
470                 }
471
472                 if (value_blob.length > *data_size) {
473                         return WERR_MORE_DATA;
474                 }
475
476                 memcpy( data, value_blob.data, value_blob.length );
477         }
478
479         if (value_length != NULL) {
480                 *value_length = value_blob.length;
481         }
482         if (data_size != NULL) {
483                 *data_size = value_blob.length;
484         }
485
486         return WERR_OK;
487 }
488
489 /*******************************************************************
490  reg_shutdwon
491  ********************************************************************/
492
493 WERROR _winreg_InitiateSystemShutdown(pipes_struct *p, uint16_t *hostname, struct initshutdown_String *message, uint32_t timeout, uint8_t force_apps, uint8_t reboot)
494 {
495         uint32_t reason = 0;
496
497         /* thunk down to _winreg_InitiateSystemShutdownEx() 
498            (just returns a status) */
499         
500         return _winreg_InitiateSystemShutdownEx( p, hostname, message, timeout, 
501                 force_apps, reboot, reason );
502 }
503
504 /*******************************************************************
505  reg_shutdown_ex
506  ********************************************************************/
507
508 #define SHUTDOWN_R_STRING "-r"
509 #define SHUTDOWN_F_STRING "-f"
510
511
512 WERROR _winreg_InitiateSystemShutdownEx(pipes_struct *p, uint16_t *hostname, struct initshutdown_String *message, uint32_t timeout, uint8_t force_apps, uint8_t reboot, uint32_t reason)
513 {
514         pstring shutdown_script;
515         char *msg = NULL;
516         pstring chkmsg;
517         fstring str_timeout;
518         fstring str_reason;
519         fstring r;
520         fstring f;
521         int ret;
522         BOOL can_shutdown;
523         
524
525         pstrcpy(shutdown_script, lp_shutdown_script());
526         
527         if ( !*shutdown_script )
528                 return WERR_ACCESS_DENIED;
529
530         /* pull the message string and perform necessary sanity checks on it */
531
532         chkmsg[0] = '\0';
533
534         if ( message && message->name && message->name->name ) {
535                 if ( (msg = talloc_strdup(p->mem_ctx, message->name->name )) == NULL ) {
536                         return WERR_NOMEM;
537                 }
538                 alpha_strcpy (chkmsg, msg, NULL, sizeof(chkmsg));
539         } 
540                 
541         fstr_sprintf(str_timeout, "%d", timeout);
542         fstr_sprintf(r, reboot ? SHUTDOWN_R_STRING : "");
543         fstr_sprintf(f, force_apps ? SHUTDOWN_F_STRING : "");
544         fstr_sprintf(str_reason, "%d", reason );
545
546         all_string_sub( shutdown_script, "%z", chkmsg, sizeof(shutdown_script) );
547         all_string_sub( shutdown_script, "%t", str_timeout, sizeof(shutdown_script) );
548         all_string_sub( shutdown_script, "%r", r, sizeof(shutdown_script) );
549         all_string_sub( shutdown_script, "%f", f, sizeof(shutdown_script) );
550         all_string_sub( shutdown_script, "%x", str_reason, sizeof(shutdown_script) );
551
552         can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
553                 
554         /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
555            Take the error return from the script and provide it as the Windows return code. */
556            
557         /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
558         
559         if ( can_shutdown ) 
560                 become_root();
561
562         ret = smbrun( shutdown_script, NULL );
563                 
564         if ( can_shutdown )
565                 unbecome_root();
566
567         /********** END SeRemoteShutdownPrivilege BLOCK **********/
568         
569         DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
570                 shutdown_script, ret));
571                 
572
573         return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
574 }
575
576
577
578
579 /*******************************************************************
580  reg_abort_shutdwon
581  ********************************************************************/
582
583 WERROR _winreg_AbortSystemShutdown(pipes_struct *p, uint16_t *server)
584 {
585         pstring abort_shutdown_script;
586         int ret;
587         BOOL can_shutdown;
588
589         pstrcpy(abort_shutdown_script, lp_abort_shutdown_script());
590
591         if ( !*abort_shutdown_script )
592                 return WERR_ACCESS_DENIED;
593                 
594         can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
595                 
596         /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
597         
598         if ( can_shutdown )
599                 become_root();
600                 
601         ret = smbrun( abort_shutdown_script, NULL );
602         
603         if ( can_shutdown )
604                 unbecome_root();
605                 
606         /********** END SeRemoteShutdownPrivilege BLOCK **********/
607
608         DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",
609                 abort_shutdown_script, ret));
610                 
611
612         return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
613 }
614
615 /*******************************************************************
616  ********************************************************************/
617
618 static int validate_reg_filename( pstring fname )
619 {
620         char *p;
621         int num_services = lp_numservices();
622         int snum;
623         pstring share_path;
624         pstring unix_fname;
625         
626         /* convert to a unix path, stripping the C:\ along the way */
627         
628         if ( !(p = valid_share_pathname( fname ) ))
629                 return -1;
630
631         /* has to exist within a valid file share */
632                         
633         for ( snum=0; snum<num_services; snum++ ) {
634         
635                 if ( !lp_snum_ok(snum) || lp_print_ok(snum) )
636                         continue;
637                 
638                 pstrcpy( share_path, lp_pathname(snum) );
639
640                 /* make sure we have a path (e.g. [homes] ) */
641
642                 if ( strlen( share_path ) == 0 )
643                         continue;
644
645                 if ( strncmp( share_path, p, strlen( share_path )) == 0 )
646                         break;
647         }
648         
649         /* p and fname are overlapping memory so copy out and back in again */
650         
651         pstrcpy( unix_fname, p );
652         pstrcpy( fname, unix_fname );
653         
654         return (snum < num_services) ? snum : -1;
655 }
656
657 /*******************************************************************
658  Note: topkeypat is the *full* path that this *key will be 
659  loaded into (including the name of the key)
660  ********************************************************************/
661
662 static WERROR reg_load_tree( REGF_FILE *regfile, const char *topkeypath,
663                              REGF_NK_REC *key )
664 {
665         REGF_NK_REC *subkey;
666         REGISTRY_KEY registry_key;
667         REGVAL_CTR *values;
668         REGSUBKEY_CTR *subkeys;
669         int i;
670         pstring path;
671         WERROR result = WERR_OK;
672         
673         /* initialize the REGISTRY_KEY structure */
674         
675         if ( !(registry_key.hook = reghook_cache_find(topkeypath)) ) {
676                 DEBUG(0,("reg_load_tree: Failed to assigned a REGISTRY_HOOK to [%s]\n",
677                         topkeypath ));
678                 return WERR_BADFILE;
679         }
680         pstrcpy( registry_key.name, topkeypath );
681         
682         /* now start parsing the values and subkeys */
683
684         if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
685                 return WERR_NOMEM;
686         
687         if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
688                 return WERR_NOMEM;
689
690         /* copy values into the REGVAL_CTR */
691         
692         for ( i=0; i<key->num_values; i++ ) {
693                 regval_ctr_addvalue( values, key->values[i].valuename, key->values[i].type,
694                         (char*)key->values[i].data, (key->values[i].data_size & ~VK_DATA_IN_OFFSET) );
695         }
696
697         /* copy subkeys into the REGSUBKEY_CTR */
698         
699         key->subkey_index = 0;
700         while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
701                 regsubkey_ctr_addkey( subkeys, subkey->keyname );
702         }
703         
704         /* write this key and values out */
705         
706         if ( !store_reg_values( &registry_key, values ) 
707                 || !store_reg_keys( &registry_key, subkeys ) )
708         {
709                 DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath));
710                 result = WERR_REG_IO_FAILURE;
711         }
712         
713         TALLOC_FREE( subkeys );
714         
715         if ( !W_ERROR_IS_OK(result) )
716                 return result;
717         
718         /* now continue to load each subkey registry tree */
719
720         key->subkey_index = 0;
721         while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
722                 pstr_sprintf( path, "%s%s%s", topkeypath, "\\", subkey->keyname );
723                 result = reg_load_tree( regfile, path, subkey );
724                 if ( !W_ERROR_IS_OK(result) )
725                         break;
726         }
727
728         return result;
729 }
730
731 /*******************************************************************
732  ********************************************************************/
733
734 static WERROR restore_registry_key ( REGISTRY_KEY *krecord, const char *fname )
735 {
736         REGF_FILE *regfile;
737         REGF_NK_REC *rootkey;
738         WERROR result;
739                 
740         /* open the registry file....fail if the file already exists */
741         
742         if ( !(regfile = regfio_open( fname, (O_RDONLY), 0 )) ) {
743                 DEBUG(0,("restore_registry_key: failed to open \"%s\" (%s)\n", 
744                         fname, strerror(errno) ));
745                 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
746         }
747         
748         /* get the rootkey from the regf file and then load the tree
749            via recursive calls */
750            
751         if ( !(rootkey = regfio_rootkey( regfile )) ) {
752                 regfio_close( regfile );
753                 return WERR_REG_FILE_INVALID;
754         }
755         
756         result = reg_load_tree( regfile, krecord->name, rootkey );
757                 
758         /* cleanup */
759         
760         regfio_close( regfile );
761         
762         return result;
763 }
764
765 /*******************************************************************
766  ********************************************************************/
767
768 WERROR _winreg_RestoreKey(pipes_struct *p, struct policy_handle *handle, struct winreg_String *filename, uint32_t flags)
769 {
770         struct registry_key *regkey = find_regkey_by_hnd( p, handle );
771         pstring         fname;
772         int             snum;
773         
774         if ( !regkey )
775                 return WERR_BADFID; 
776
777         if ( !filename || !filename->name )
778                 return WERR_INVALID_PARAM;
779
780         pstrcpy( fname, filename->name );
781
782         DEBUG(8,("_winreg_RestoreKey: verifying restore of key [%s] from "
783                  "\"%s\"\n", regkey->key->name, fname));
784
785         if ( (snum = validate_reg_filename( fname )) == -1 )
786                 return WERR_OBJECT_PATH_INVALID;
787                 
788         /* user must posses SeRestorePrivilege for this this proceed */
789         
790         if ( !user_has_privileges( p->pipe_user.nt_user_token, &se_restore ) )
791                 return WERR_ACCESS_DENIED;
792                 
793         DEBUG(2,("_winreg_RestoreKey: Restoring [%s] from %s in share %s\n",
794                  regkey->key->name, fname, lp_servicename(snum) ));
795
796         return restore_registry_key( regkey->key, fname );
797 }
798
799 /********************************************************************
800 ********************************************************************/
801
802 static WERROR reg_write_tree( REGF_FILE *regfile, const char *keypath,
803                               REGF_NK_REC *parent, SEC_DESC *sec_desc )
804 {
805         REGF_NK_REC *key;
806         REGVAL_CTR *values;
807         REGSUBKEY_CTR *subkeys;
808         int i, num_subkeys;
809         pstring key_tmp;
810         char *keyname, *parentpath;
811         pstring subkeypath;
812         char *subkeyname;
813         REGISTRY_KEY registry_key;
814         WERROR result = WERR_OK;
815         
816         if ( !regfile )
817                 return WERR_GENERAL_FAILURE;
818                 
819         if ( !keypath )
820                 return WERR_OBJECT_PATH_INVALID;
821                 
822         /* split up the registry key path */
823         
824         pstrcpy( key_tmp, keypath );
825         if ( !reg_split_key( key_tmp, &parentpath, &keyname ) )
826                 return WERR_OBJECT_PATH_INVALID;
827
828         if ( !keyname )
829                 keyname = parentpath;
830
831         /* we need a REGISTRY_KEY object here to enumerate subkeys and values */
832         
833         ZERO_STRUCT( registry_key );
834
835         if ( (registry_key.name = talloc_strdup(regfile->mem_ctx, keypath)) == NULL )
836                 return WERR_NOMEM;
837
838         if ( (registry_key.hook = reghook_cache_find( registry_key.name )) == NULL )
839                 return WERR_BADFILE;
840
841         /* lookup the values and subkeys */
842         
843         if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) ) 
844                 return WERR_NOMEM;
845
846         if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
847                 return WERR_NOMEM;
848
849         fetch_reg_keys( &registry_key, subkeys );
850         fetch_reg_values( &registry_key, values );
851
852         /* write out this key */
853                 
854         if ( !(key = regfio_write_key( regfile, keyname, values, subkeys, sec_desc, parent )) ) {
855                 result = WERR_CAN_NOT_COMPLETE;
856                 goto done;
857         }
858
859         /* write each one of the subkeys out */
860
861         num_subkeys = regsubkey_ctr_numkeys( subkeys );
862         for ( i=0; i<num_subkeys; i++ ) {
863                 subkeyname = regsubkey_ctr_specific_key( subkeys, i );
864                 pstr_sprintf( subkeypath, "%s\\%s", keypath, subkeyname );
865                 result = reg_write_tree( regfile, subkeypath, key, sec_desc );
866                 if ( !W_ERROR_IS_OK(result) )
867                         goto done;
868         }
869
870         DEBUG(6,("reg_write_tree: wrote key [%s]\n", keypath ));
871
872 done:
873         TALLOC_FREE( subkeys );
874         TALLOC_FREE( registry_key.name );
875
876         return result;
877 }
878
879 /*******************************************************************
880  ********************************************************************/
881
882 static WERROR make_default_reg_sd( TALLOC_CTX *ctx, SEC_DESC **psd )
883 {
884         DOM_SID adm_sid, owner_sid;
885         SEC_ACE ace[2];         /* at most 2 entries */
886         SEC_ACCESS mask;
887         SEC_ACL *psa = NULL;
888         size_t sd_size;
889
890         /* set the owner to BUILTIN\Administrator */
891
892         sid_copy(&owner_sid, &global_sid_Builtin);
893         sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN );
894         
895
896         /* basic access for Everyone */
897
898         init_sec_access(&mask, reg_generic_map.generic_execute | reg_generic_map.generic_read );
899         init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
900
901         /* add Full Access 'BUILTIN\Administrators' */
902
903         init_sec_access(&mask, reg_generic_map.generic_all);
904         sid_copy(&adm_sid, &global_sid_Builtin);
905         sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
906         init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
907
908         /* create the security descriptor */
909
910         if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 2, ace)) == NULL)
911                 return WERR_NOMEM;
912
913         if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, &owner_sid, NULL, NULL, psa, &sd_size)) == NULL)
914                 return WERR_NOMEM;
915
916         return WERR_OK;
917 }
918
919 /*******************************************************************
920  ********************************************************************/
921
922 static WERROR backup_registry_key ( REGISTRY_KEY *krecord, const char *fname )
923 {
924         REGF_FILE *regfile;
925         WERROR result;
926         SEC_DESC *sd = NULL;
927         
928         /* open the registry file....fail if the file already exists */
929         
930         if ( !(regfile = regfio_open( fname, (O_RDWR|O_CREAT|O_EXCL), (S_IREAD|S_IWRITE) )) ) {
931                 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n", 
932                         fname, strerror(errno) ));
933                 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
934         }
935         
936         if ( !W_ERROR_IS_OK(result = make_default_reg_sd( regfile->mem_ctx, &sd )) ) {
937                 regfio_close( regfile );
938                 return result;
939         }
940                 
941         /* write the registry tree to the file  */
942         
943         result = reg_write_tree( regfile, krecord->name, NULL, sd );
944                 
945         /* cleanup */
946         
947         regfio_close( regfile );
948         
949         return result;
950 }
951
952 /*******************************************************************
953  ********************************************************************/
954
955 WERROR _winreg_SaveKey(pipes_struct *p, struct policy_handle *handle, struct winreg_String *filename, struct KeySecurityAttribute *sec_attrib)
956 {
957         struct registry_key *regkey = find_regkey_by_hnd( p, handle );
958         pstring         fname;
959         int             snum;
960         
961         if ( !regkey )
962                 return WERR_BADFID; 
963
964         if ( !filename || !filename->name )
965                 return WERR_INVALID_PARAM;
966
967         pstrcpy( fname, filename->name );
968
969         DEBUG(8,("_winreg_SaveKey: verifying backup of key [%s] to \"%s\"\n",
970                  regkey->key->name, fname));
971         
972         if ( (snum = validate_reg_filename( fname )) == -1 )
973                 return WERR_OBJECT_PATH_INVALID;
974                 
975         DEBUG(2,("_winreg_SaveKey: Saving [%s] to %s in share %s\n",
976                  regkey->key->name, fname, lp_servicename(snum) ));
977                 
978         return backup_registry_key( regkey->key, fname );
979 }
980
981 /*******************************************************************
982  ********************************************************************/
983
984 WERROR _winreg_SaveKeyEx(pipes_struct *p)
985 {
986         /* fill in your code here if you think this call should
987            do anything */
988
989         p->rng_fault_state = True;
990         return WERR_NOT_SUPPORTED;
991 }
992
993 /*******************************************************************
994  ********************************************************************/
995
996 WERROR _winreg_CreateKey( pipes_struct *p, struct policy_handle *handle,
997                           struct winreg_String keyname, 
998                           struct winreg_String keyclass,
999                           uint32_t options, uint32_t access_mask, 
1000                           struct winreg_SecBuf *secdesc,
1001                           struct policy_handle *new_handle, 
1002                           enum winreg_CreateAction *action_taken )
1003 {
1004         struct registry_key *parent = find_regkey_by_hnd(p, handle);
1005         struct registry_key *new_key;
1006         WERROR result;
1007
1008         if ( !parent )
1009                 return WERR_BADFID;
1010
1011         result = reg_createkey(NULL, parent, keyname.name, access_mask,
1012                                &new_key, action_taken);
1013         if (!W_ERROR_IS_OK(result)) {
1014                 return result;
1015         }
1016
1017         if (!create_policy_hnd(p, new_handle, free_regkey, new_key)) {
1018                 TALLOC_FREE(new_key);
1019                 return WERR_BADFILE;
1020         }
1021
1022         return WERR_OK;
1023 }
1024
1025 /*******************************************************************
1026  ********************************************************************/
1027
1028 WERROR _winreg_SetValue(pipes_struct *p, struct policy_handle *handle,
1029                         struct winreg_String name, enum winreg_Type type,
1030                         uint8_t *data, uint32_t size)
1031 {
1032         struct registry_key *key = find_regkey_by_hnd(p, handle);
1033         struct registry_value *val;
1034         WERROR status;
1035
1036         if ( !key )
1037                 return WERR_BADFID;
1038
1039         DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n", key->key->name,
1040                  name.name));
1041
1042         status = registry_pull_value(p->mem_ctx, &val, type, data, size, size);
1043         if (!W_ERROR_IS_OK(status)) {
1044                 return status;
1045         }
1046
1047         return reg_setvalue(key, name.name, val);
1048 }
1049
1050 /*******************************************************************
1051  ********************************************************************/
1052
1053 WERROR _winreg_DeleteKey(pipes_struct *p, struct policy_handle *handle,
1054                          struct winreg_String key)
1055 {
1056         struct registry_key *parent = find_regkey_by_hnd(p, handle);
1057
1058         if ( !parent )
1059                 return WERR_BADFID;
1060
1061         return reg_deletekey(parent, key.name);
1062 }
1063
1064
1065 /*******************************************************************
1066  ********************************************************************/
1067
1068 WERROR _winreg_DeleteValue(pipes_struct *p, struct policy_handle *handle,
1069                            struct winreg_String value)
1070 {
1071         struct registry_key *key = find_regkey_by_hnd(p, handle);
1072         
1073         if ( !key )
1074                 return WERR_BADFID;
1075
1076         return reg_deletevalue(key, value.name);
1077 }
1078
1079 /*******************************************************************
1080  ********************************************************************/
1081
1082 WERROR _winreg_GetKeySecurity(pipes_struct *p, struct policy_handle *handle,
1083                               uint32_t sec_info, struct KeySecurityData *sd)
1084 {
1085         struct registry_key *key = find_regkey_by_hnd(p, handle);
1086         WERROR err;
1087         struct security_descriptor *secdesc;
1088         uint8 *data;
1089         size_t len;
1090
1091         if ( !key )
1092                 return WERR_BADFID;
1093                 
1094         /* access checks first */
1095         
1096         if ( !(key->key->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
1097                 return WERR_ACCESS_DENIED;
1098
1099         err = regkey_get_secdesc(p->mem_ctx, key->key, &secdesc);
1100         if (!W_ERROR_IS_OK(err)) {
1101                 return err;
1102         }
1103
1104         err = ntstatus_to_werror(marshall_sec_desc(p->mem_ctx, secdesc,
1105                                                    &data, &len));
1106         if (!W_ERROR_IS_OK(err)) {
1107                 return err;
1108         }
1109
1110         if (len > sd->size) {
1111                 sd->size = len;
1112                 return WERR_INSUFFICIENT_BUFFER;
1113         }
1114
1115         sd->size = len;
1116         sd->len = len;
1117         sd->data = data;
1118                 
1119         return WERR_OK;
1120 }
1121
1122 /*******************************************************************
1123  ********************************************************************/
1124
1125 WERROR _winreg_SetKeySecurity(pipes_struct *p, struct policy_handle *handle, uint32_t access_mask, struct KeySecurityData *sd)
1126 {
1127         struct registry_key *key = find_regkey_by_hnd(p, handle);
1128         struct security_descriptor *secdesc;
1129         WERROR err;
1130
1131         if ( !key )
1132                 return WERR_BADFID;
1133                 
1134         /* access checks first */
1135         
1136         if ( !(key->key->access_granted & STD_RIGHT_WRITE_DAC_ACCESS) )
1137                 return WERR_ACCESS_DENIED;
1138
1139         err = ntstatus_to_werror(unmarshall_sec_desc(p->mem_ctx, sd->data,
1140                                                      sd->len, &secdesc));
1141         if (!W_ERROR_IS_OK(err)) {
1142                 return err;
1143         }
1144
1145         return regkey_set_secdesc(key->key, secdesc);
1146 }
1147
1148 /*******************************************************************
1149  ********************************************************************/
1150
1151 WERROR _winreg_FlushKey(pipes_struct *p, struct policy_handle *handle)
1152 {
1153         /* I'm just replying OK because there's not a lot 
1154            here I see to do i  --jerry */
1155         
1156         return WERR_OK;
1157 }
1158
1159 /*******************************************************************
1160  ********************************************************************/
1161
1162 WERROR _winreg_UnLoadKey(pipes_struct *p)
1163 {
1164         /* fill in your code here if you think this call should
1165            do anything */
1166
1167         p->rng_fault_state = True;
1168         return WERR_NOT_SUPPORTED;
1169 }
1170
1171 /*******************************************************************
1172  ********************************************************************/
1173
1174 WERROR _winreg_ReplaceKey(pipes_struct *p)
1175 {
1176         /* fill in your code here if you think this call should
1177            do anything */
1178
1179         p->rng_fault_state = True;
1180         return WERR_NOT_SUPPORTED;
1181 }
1182
1183 /*******************************************************************
1184  ********************************************************************/
1185
1186 WERROR _winreg_LoadKey(pipes_struct *p, struct policy_handle *handle, struct winreg_String *keyname, struct winreg_String *filename)
1187 {
1188         /* fill in your code here if you think this call should
1189            do anything */
1190
1191         p->rng_fault_state = True;
1192         return WERR_NOT_SUPPORTED;
1193 }
1194
1195 /*******************************************************************
1196  ********************************************************************/
1197
1198 WERROR _winreg_NotifyChangeKeyValue(pipes_struct *p, struct policy_handle *handle, uint8_t watch_subtree, uint32_t notify_filter, uint32_t unknown, struct winreg_String string1, struct winreg_String string2, uint32_t unknown2)
1199 {
1200         /* fill in your code here if you think this call should
1201            do anything */
1202
1203         p->rng_fault_state = True;
1204         return WERR_NOT_SUPPORTED;
1205 }
1206
1207 /*******************************************************************
1208  ********************************************************************/
1209
1210 WERROR _winreg_QueryMultipleValues(pipes_struct *p, struct policy_handle *key_handle, struct QueryMultipleValue *values, uint32_t num_values, uint8_t *buffer, uint32_t *buffer_size)
1211 {
1212         /* fill in your code here if you think this call should
1213            do anything */
1214
1215         p->rng_fault_state = True;
1216         return WERR_NOT_SUPPORTED;
1217 }
1218
1219 /*******************************************************************
1220  ********************************************************************/
1221
1222 WERROR _winreg_QueryMultipleValues2(pipes_struct *p)
1223 {
1224         /* fill in your code here if you think this call should
1225            do anything */
1226
1227         p->rng_fault_state = True;
1228         return WERR_NOT_SUPPORTED;
1229 }
1230