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