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