r18929: * Clarify QueryValue IDL and regenerate code
[kai/samba.git] / source3 / rpc_server / srv_winreg_nt.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell               1992-1997.
5  *  Copyright (C) Jeremy Allison                     2001.
6  *  Copyright (C) Gerald Carter                      2002-2005.
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *  
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *  
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22
23 /* Implementation of registry functions. */
24
25 #include "includes.h"
26 #include "regfio.h"
27
28 #undef DBGC_CLASS
29 #define DBGC_CLASS DBGC_RPC_SRV
30
31 #if 0   /* temporaily disabled */
32 static struct generic_mapping reg_generic_map = 
33         { REG_KEY_READ, REG_KEY_WRITE, REG_KEY_EXECUTE, REG_KEY_ALL };
34 #endif
35
36 /******************************************************************
37  free() function for REGISTRY_KEY
38  *****************************************************************/
39  
40 static void free_regkey_info(void *ptr)
41 {
42         regkey_close_internal( (REGISTRY_KEY*)ptr );
43 }
44
45 /******************************************************************
46  Find a registry key handle and return a REGISTRY_KEY
47  *****************************************************************/
48
49 static REGISTRY_KEY *find_regkey_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
50 {
51         REGISTRY_KEY *regkey = NULL;
52
53         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&regkey)) {
54                 DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: "));
55                 return NULL;
56         }
57
58         return regkey;
59 }
60
61
62 /*******************************************************************
63  Function for open a new registry handle and creating a handle 
64  Note that P should be valid & hnd should already have space
65  
66  When we open a key, we store the full path to the key as 
67  HK[LM|U]\<key>\<key>\...
68  *******************************************************************/
69  
70 static WERROR open_registry_key( pipes_struct *p, POLICY_HND *hnd, 
71                                  REGISTRY_KEY **keyinfo, REGISTRY_KEY *parent,
72                                  const char *subkeyname, uint32 access_desired  )
73 {
74         pstring         keypath;
75         int             path_len;
76         WERROR          result = WERR_OK;
77
78         /* create a full registry path and strip any trailing '\' 
79            characters */
80            
81         pstr_sprintf( keypath, "%s%s%s", 
82                 parent ? parent->name : "",
83                 parent ? "\\" : "", 
84                 subkeyname );
85         
86         path_len = strlen( keypath );
87         if ( path_len && keypath[path_len-1] == '\\' )
88                 keypath[path_len-1] = '\0';
89         
90         /* now do the internal open */
91                 
92         result = regkey_open_internal( keyinfo, keypath, p->pipe_user.nt_user_token, access_desired );
93         if ( !W_ERROR_IS_OK(result) )
94                 return result;
95         
96         if ( !create_policy_hnd( p, hnd, free_regkey_info, *keyinfo ) ) {
97                 result = WERR_BADFILE; 
98                 regkey_close_internal( *keyinfo );
99         }
100         
101         return result;
102 }
103
104 /*******************************************************************
105  Function for open a new registry handle and creating a handle 
106  Note that P should be valid & hnd should already have space
107  *******************************************************************/
108
109 static BOOL close_registry_key(pipes_struct *p, POLICY_HND *hnd)
110 {
111         REGISTRY_KEY *regkey = find_regkey_index_by_hnd(p, hnd);
112         
113         if ( !regkey ) {
114                 DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
115                 return False;
116         }
117         
118         close_policy_hnd(p, hnd);
119         
120         return True;
121 }
122
123 /********************************************************************
124  retrieve information about the subkeys
125  *******************************************************************/
126  
127 static BOOL get_subkey_information( REGISTRY_KEY *key, uint32 *maxnum, uint32 *maxlen )
128 {
129         int             num_subkeys, i;
130         uint32          max_len;
131         REGSUBKEY_CTR   *subkeys;
132         uint32          len;
133         
134         if ( !key )
135                 return False;
136
137         if ( !(subkeys = TALLOC_ZERO_P( NULL, REGSUBKEY_CTR )) )
138                 return False;
139
140         if ( fetch_reg_keys( key, subkeys ) == -1 )
141                 return False;
142
143         /* find the longest string */
144         
145         max_len = 0;
146         num_subkeys = regsubkey_ctr_numkeys( subkeys );
147         
148         for ( i=0; i<num_subkeys; i++ ) {
149                 len = strlen( regsubkey_ctr_specific_key(subkeys, i) );
150                 max_len = MAX(max_len, len);
151         }
152
153         *maxnum = num_subkeys;
154         *maxlen = max_len*2;
155         
156         TALLOC_FREE( subkeys );
157         
158         return True;
159 }
160
161 /********************************************************************
162  retrieve information about the values.  
163  *******************************************************************/
164  
165 static BOOL get_value_information( REGISTRY_KEY *key, uint32 *maxnum, 
166                                     uint32 *maxlen, uint32 *maxsize )
167 {
168         REGVAL_CTR      *values;
169         REGISTRY_VALUE  *val;
170         uint32          sizemax, lenmax;
171         int             i, num_values;
172         
173         if ( !key )
174                 return False;
175
176         if ( !(values = TALLOC_ZERO_P( NULL, REGVAL_CTR )) )
177                 return False;
178         
179         if ( fetch_reg_values( key, values ) == -1 )
180                 return False;
181         
182         lenmax = sizemax = 0;
183         num_values = regval_ctr_numvals( values );
184         
185         val = regval_ctr_specific_value( values, 0 );
186         
187         for ( i=0; i<num_values && val; i++ ) 
188         {
189                 lenmax  = MAX(lenmax,  val->valuename ? strlen(val->valuename)+1 : 0 );
190                 sizemax = MAX(sizemax, val->size );
191                 
192                 val = regval_ctr_specific_value( values, i );
193         }
194
195         *maxnum   = num_values;
196         *maxlen   = lenmax;
197         *maxsize  = sizemax;
198         
199         TALLOC_FREE( values );
200         
201         return True;
202 }
203
204
205 /********************************************************************
206  reg_close
207  ********************************************************************/
208
209 WERROR _winreg_CloseKey(pipes_struct *p, struct policy_handle *handle)
210 {
211         /* close the policy handle */
212
213         if (!close_registry_key(p, handle))
214                 return WERR_BADFID; 
215
216         return WERR_OK;
217 }
218
219 /*******************************************************************
220  ********************************************************************/
221
222 WERROR _winreg_OpenHKLM(pipes_struct *p, uint16_t *system_name, uint32_t access_mask, struct policy_handle *handle)
223 {
224         REGISTRY_KEY *keyinfo;
225         
226         return open_registry_key( p, handle, &keyinfo, NULL, KEY_HKLM, access_mask );
227 }
228
229 /*******************************************************************
230  ********************************************************************/
231
232 WERROR _winreg_OpenHKPD(pipes_struct *p, uint16_t *system_name, uint32_t access_mask, struct policy_handle *handle)
233 {
234         REGISTRY_KEY *keyinfo;
235         
236         return open_registry_key( p, handle, &keyinfo, NULL, KEY_HKPD, access_mask );
237 }
238
239 /*******************************************************************
240  ********************************************************************/
241
242 WERROR _winreg_OpenHKPT(pipes_struct *p, uint16_t *system_name, uint32_t access_mask, struct policy_handle *handle)
243 {
244         REGISTRY_KEY *keyinfo;
245         
246         return open_registry_key( p, handle, &keyinfo, NULL, KEY_HKPT, access_mask );
247 }
248
249 /*******************************************************************
250  ********************************************************************/
251
252 WERROR _winreg_OpenHKCR(pipes_struct *p, uint16_t *system_name, uint32_t access_mask, struct policy_handle *handle)
253 {
254         REGISTRY_KEY *keyinfo;
255         
256         return open_registry_key( p, handle, &keyinfo, NULL, KEY_HKCR, access_mask );
257 }
258
259 /*******************************************************************
260  ********************************************************************/
261
262 WERROR _winreg_OpenHKU(pipes_struct *p, uint16_t *system_name, uint32_t access_mask, struct policy_handle *handle)
263 {
264         REGISTRY_KEY *keyinfo;
265
266         return open_registry_key( p, handle, &keyinfo, NULL, KEY_HKU, access_mask );
267 }
268
269 /*******************************************************************
270  ********************************************************************/
271
272 WERROR _winreg_OpenHKCU(pipes_struct *p, uint16_t *system_name, uint32_t access_mask, struct policy_handle *handle)
273 {
274         REGISTRY_KEY *keyinfo;
275
276         return open_registry_key( p, handle, &keyinfo, NULL, KEY_HKCU, access_mask );
277 }
278
279 /*******************************************************************
280  ********************************************************************/
281
282 WERROR _winreg_OpenHKCC(pipes_struct *p, uint16_t *system_name, uint32_t access_mask, struct policy_handle *handle)
283 {
284         REGISTRY_KEY *keyinfo;
285
286         return open_registry_key( p, handle, &keyinfo, NULL, KEY_HKCC, access_mask );
287 }
288
289 /*******************************************************************
290  ********************************************************************/
291
292 WERROR _winreg_OpenHKDD(pipes_struct *p, uint16_t *system_name, uint32_t access_mask, struct policy_handle *handle)
293 {
294         REGISTRY_KEY *keyinfo;
295
296         return open_registry_key( p, handle, &keyinfo, NULL, KEY_HKDD, access_mask );
297 }
298
299 /*******************************************************************
300  ********************************************************************/
301
302 WERROR _winreg_OpenHKPN(pipes_struct *p, uint16_t *system_name, uint32_t access_mask, struct policy_handle *handle)
303 {
304         REGISTRY_KEY *keyinfo;
305
306         return open_registry_key( p, handle, &keyinfo, NULL, KEY_HKPN, access_mask );
307 }
308
309 /*******************************************************************
310  reg_reply_open_entry
311  ********************************************************************/
312
313 WERROR _winreg_OpenKey(pipes_struct *p, struct policy_handle *parent_handle, struct winreg_String keyname, uint32_t unknown, uint32_t access_mask, struct policy_handle *handle)
314 {
315         char *name;
316         REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, parent_handle );
317         REGISTRY_KEY *newkey = NULL;
318         uint32 check_rights;
319
320         if ( !parent )
321                 return WERR_BADFID;
322
323         if ( (name = talloc_strdup( p->mem_ctx, keyname.name )) == NULL ) {
324                 return WERR_INVALID_PARAM;
325         }
326         
327         /* check granted access first; what is the correct mask here? */
328
329         check_rights = ( SEC_RIGHTS_ENUM_SUBKEYS|
330                          SEC_RIGHTS_CREATE_SUBKEY|
331                          SEC_RIGHTS_QUERY_VALUE|
332                          SEC_RIGHTS_SET_VALUE);
333
334         if ( !(parent->access_granted & check_rights) ) {
335                 DEBUG(8,("Rights check failed, parent had %04x, check_rights %04x\n",parent->access_granted, check_rights));
336                 return WERR_ACCESS_DENIED;
337         }
338         
339         /* 
340          * very crazy, but regedit.exe on Win2k will attempt to call 
341          * REG_OPEN_ENTRY with a keyname of "".  We should return a new 
342          * (second) handle here on the key->name.  regedt32.exe does 
343          * not do this stupidity.   --jerry
344          */
345          
346         return open_registry_key( p, handle, &newkey, parent, name, access_mask );
347 }
348
349 /*******************************************************************
350  reg_reply_info
351  ********************************************************************/
352
353 WERROR _winreg_QueryValue(pipes_struct *p, struct policy_handle *handle, struct winreg_String value_name, enum winreg_Type *type, uint8_t *data, uint32_t *data_size, uint32_t *value_length)
354 {
355         WERROR                  status = WERR_BADFILE;
356         char                    *name;
357         REGISTRY_KEY            *regkey = find_regkey_index_by_hnd( p, handle );
358         REGISTRY_VALUE          *val = NULL;
359         REGVAL_CTR              *regvals;
360         int                     i;
361
362         if ( !regkey )
363                 return WERR_BADFID;
364
365         *value_length = *type = 0;
366         
367         DEBUG(7,("_reg_info: policy key name = [%s]\n", regkey->name));
368         DEBUG(7,("_reg_info: policy key type = [%08x]\n", regkey->type));
369         
370         if ( (name = talloc_strdup( p->mem_ctx, value_name.name )) == NULL ) {
371                 return WERR_NOMEM;
372         }
373
374         DEBUG(5,("_reg_info: looking up value: [%s]\n", name));
375
376         if ( !(regvals = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) ) 
377                 return WERR_NOMEM;
378         
379         /* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */
380         if(regkey->type == REG_KEY_HKPD) 
381         {
382                 if(strequal(name, "Global"))
383                 {
384                         uint32 outbuf_len;
385                         prs_struct prs_hkpd;
386                         prs_init(&prs_hkpd, *data_size, p->mem_ctx, MARSHALL);
387                         status = reg_perfcount_get_hkpd(&prs_hkpd, *data_size, &outbuf_len, NULL);
388                         regval_ctr_addvalue(regvals, "HKPD", REG_BINARY,
389                                             prs_hkpd.data_p, outbuf_len);
390                         val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
391                         prs_mem_free(&prs_hkpd);
392                 }
393                 else if(strequal(name, "Counter 009"))
394                 {
395                         uint32 base_index;
396                         uint32 buffer_size;
397                         char *buffer;
398                         
399                         buffer = NULL;
400                         base_index = reg_perfcount_get_base_index();
401                         buffer_size = reg_perfcount_get_counter_names(base_index, &buffer);
402                         regval_ctr_addvalue(regvals, "Counter 009", 
403                                             REG_MULTI_SZ, buffer, buffer_size);
404                         
405                         val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
406                         
407                         if(buffer_size > 0)
408                         {
409                                 SAFE_FREE(buffer);
410                                 status = WERR_OK;
411                         }
412                 }
413                 else if(strequal(name, "Explain 009"))
414                 {               
415                         uint32 base_index;
416                         uint32 buffer_size;
417                         char *buffer;
418                         
419                         buffer = NULL;
420                         base_index = reg_perfcount_get_base_index();
421                         buffer_size = reg_perfcount_get_counter_help(base_index, &buffer);
422                         regval_ctr_addvalue(regvals, "Explain 009", 
423                                             REG_MULTI_SZ, buffer, buffer_size);
424                         
425                         val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
426                         
427                         if(buffer_size > 0)
428                         {
429                                 SAFE_FREE(buffer);
430                                 status = WERR_OK;
431                         }
432                 }
433                 else if(isdigit(name[0]))
434                 {
435                         /* we probably have a request for a specific object here */
436                         uint32 outbuf_len;
437                         prs_struct prs_hkpd;
438                         prs_init(&prs_hkpd, *data_size, p->mem_ctx, MARSHALL);
439                         status = reg_perfcount_get_hkpd(&prs_hkpd, *data_size, &outbuf_len, name);
440                         regval_ctr_addvalue(regvals, "HKPD", REG_BINARY,
441                                             prs_hkpd.data_p, outbuf_len);
442                         
443                         val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
444                         prs_mem_free(&prs_hkpd);
445                 }
446                 else
447                 {
448                         DEBUG(3,("Unsupported key name [%s] for HKPD.\n", name));
449                         return WERR_BADFILE;
450                 }
451         }
452         /* HKPT calls can be handled out of reg_dynamic.c with the hkpt_params handler */
453         else
454         {
455             for ( i=0; fetch_reg_values_specific(regkey, &val, i); i++ ) 
456             {
457                 DEBUG(10,("_reg_info: Testing value [%s]\n", val->valuename));
458                 if ( strequal( val->valuename, name ) ) {
459                         DEBUG(10,("_reg_info: Found match for value [%s]\n", name));
460                         status = WERR_OK;
461                         break;
462                 }
463                 
464                 free_registry_value( val );
465             }
466         }
467
468         /* if we have a value then copy it to the output */
469
470         if ( val ) {
471                 *value_length =  regval_size( val );
472                 *type = val->type;
473
474                 if ( *data_size == 0 ) {
475                         status = WERR_OK;
476                 } else if ( *value_length > *data_size ) {
477                         status = WERR_MORE_DATA;
478                 } else {
479                         memcpy( data, regval_data_p(val), *value_length );
480                         status = WERR_OK;
481                 }
482         }
483
484         TALLOC_FREE( regvals );
485         free_registry_value( val );
486
487         return status;
488 }
489
490 /*****************************************************************************
491  Implementation of REG_QUERY_KEY
492  ****************************************************************************/
493
494 WERROR _winreg_QueryInfoKey(pipes_struct *p, struct policy_handle *handle, 
495                             struct winreg_String class_in, 
496                             struct winreg_String *class_out, uint32_t *num_subkeys, 
497                             uint32_t *max_subkeylen, uint32_t *max_subkeysize, 
498                             uint32_t *num_values, uint32_t *max_valnamelen, 
499                             uint32_t *max_valbufsize, uint32_t *secdescsize, 
500                             NTTIME *last_changed_time)
501 {
502         WERROR  status = WERR_OK;
503         REGISTRY_KEY    *regkey = find_regkey_index_by_hnd( p, handle );
504         
505         if ( !regkey )
506                 return WERR_BADFID; 
507         
508         if ( !get_subkey_information( regkey, num_subkeys, max_subkeylen) ) {
509                 DEBUG(0,("_reg_query_key: get_subkey_information() failed!\n"));
510                 return WERR_ACCESS_DENIED;
511         }
512                 
513         if ( !get_value_information( regkey, num_values, max_valnamelen, max_valbufsize) ) {
514                 DEBUG(0,("_reg_query_key: get_value_information() failed!\n"));
515                 return WERR_ACCESS_DENIED;      
516         }
517
518         *secdescsize = 0x00000078;      /* size for key's sec_desc */
519         
520         /* Win9x set this to 0x0 since it does not keep timestamps.
521            Doing the same here for simplicity   --jerry */
522            
523         *last_changed_time = 0;
524
525         return status;
526 }
527
528
529 /*****************************************************************************
530  Implementation of REG_GETVERSION
531  ****************************************************************************/
532  
533 WERROR _winreg_GetVersion(pipes_struct *p, struct policy_handle *handle, uint32_t *version)
534 {
535         REGISTRY_KEY    *regkey = find_regkey_index_by_hnd( p, handle );
536         
537         if ( !regkey )
538                 return WERR_BADFID;
539         
540         *version = 0x00000005;  /* Windows 2000 registry API version */
541         
542         return WERR_OK;
543 }
544
545
546 /*****************************************************************************
547  Implementation of REG_ENUM_KEY
548  ****************************************************************************/
549  
550 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)
551 {
552         WERROR  status = WERR_OK;
553         REGISTRY_KEY    *regkey = find_regkey_index_by_hnd( p, handle );
554         char            *subkey = NULL;
555         
556         
557         if ( !regkey )
558                 return WERR_BADFID; 
559
560         if ( !name || !keyclass )
561                 return WERR_INVALID_PARAM;
562
563         DEBUG(8,("_reg_enum_key: enumerating key [%s]\n", regkey->name));
564         
565         if ( !fetch_reg_keys_specific( regkey, &subkey, enum_index ) ) {
566                 status = WERR_NO_MORE_ITEMS;
567                 goto done;
568         }
569         
570         DEBUG(10,("_reg_enum_key: retrieved subkey named [%s]\n", subkey));
571         
572         if ( last_changed_time ) {
573                 *last_changed_time = 0;
574         }
575         keyclass->name = NULL;
576         if ( (name->name = talloc_strdup( p->mem_ctx, subkey )) == NULL ) {
577                 status = WERR_NOMEM;
578         }
579
580 done:   
581         SAFE_FREE( subkey );
582         return status;
583 }
584
585 /*****************************************************************************
586  Implementation of REG_ENUM_VALUE
587  ****************************************************************************/
588
589 WERROR _winreg_EnumValue(pipes_struct *p, struct policy_handle *handle, uint32_t enum_index, struct winreg_StringBuf *name, enum winreg_Type *type, uint8_t *value, uint32_t *size, uint32_t *length)
590 {
591         WERROR  status = WERR_OK;
592         REGISTRY_KEY    *regkey = find_regkey_index_by_hnd( p, handle );
593         REGISTRY_VALUE  *val;
594         
595         if ( !regkey )
596                 return WERR_BADFID; 
597
598         if ( !name || !type || !value || !size || !length )
599                 return WERR_INVALID_PARAM;
600
601         DEBUG(8,("_reg_enum_value: enumerating values for key [%s]\n", regkey->name));
602
603         if ( !fetch_reg_values_specific( regkey, &val, enum_index ) ) {
604                 status = WERR_NO_MORE_ITEMS;
605                 goto done;
606         }
607
608         DEBUG(10,("_reg_enum_value: retrieved value named  [%s]\n", val->valuename));
609         
610         /* subkey has the string name now */
611         
612         if ( (name->name = talloc_strdup( p->mem_ctx, val->valuename )) == NULL ) {
613                 status = WERR_NOMEM;
614         }
615
616         *size   =  regval_size( val );
617         *length =  regval_size( val );
618
619         if ( (value = talloc_memdup( p->mem_ctx, regval_data_p(val), *size )) == NULL ) {
620                 status = WERR_NOMEM;
621         }
622
623         *type = val->type;
624
625 done:   
626         free_registry_value( val );
627         
628         return status;
629 }
630
631
632 /*******************************************************************
633  reg_shutdwon
634  ********************************************************************/
635
636 WERROR _winreg_InitiateSystemShutdown(pipes_struct *p, uint16_t *hostname, struct initshutdown_String *message, uint32_t timeout, uint8_t force_apps, uint8_t reboot)
637 {
638         uint32_t reason = 0;
639
640         /* thunk down to _winreg_InitiateSystemShutdownEx() 
641            (just returns a status) */
642         
643         return _winreg_InitiateSystemShutdownEx( p, hostname, message, timeout, 
644                 force_apps, reboot, reason );
645 }
646
647 /*******************************************************************
648  reg_shutdown_ex
649  ********************************************************************/
650
651 #define SHUTDOWN_R_STRING "-r"
652 #define SHUTDOWN_F_STRING "-f"
653
654
655 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)
656 {
657         pstring shutdown_script;
658         char *msg = NULL;
659         pstring chkmsg;
660         fstring str_timeout;
661         fstring str_reason;
662         fstring r;
663         fstring f;
664         int ret;
665         BOOL can_shutdown;
666         
667
668         pstrcpy(shutdown_script, lp_shutdown_script());
669         
670         if ( !*shutdown_script )
671                 return WERR_ACCESS_DENIED;
672
673         /* pull the message string and perform necessary sanity checks on it */
674
675         if ( message && message->name && message->name->name ) {
676                 if ( (msg = talloc_strdup(p->mem_ctx, message->name->name )) == NULL ) {
677                         return WERR_NOMEM;
678                 }
679         } 
680         alpha_strcpy (chkmsg, msg?msg:"", NULL, strlen(msg));
681                 
682         fstr_sprintf(str_timeout, "%d", timeout);
683         fstr_sprintf(r, reboot ? SHUTDOWN_R_STRING : "");
684         fstr_sprintf(f, force_apps ? SHUTDOWN_F_STRING : "");
685         fstr_sprintf(str_reason, "%d", reason );
686
687         all_string_sub( shutdown_script, "%z", chkmsg, sizeof(shutdown_script) );
688         all_string_sub( shutdown_script, "%t", str_timeout, sizeof(shutdown_script) );
689         all_string_sub( shutdown_script, "%r", r, sizeof(shutdown_script) );
690         all_string_sub( shutdown_script, "%f", f, sizeof(shutdown_script) );
691         all_string_sub( shutdown_script, "%x", str_reason, sizeof(shutdown_script) );
692
693         can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
694                 
695         /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
696            Take the error return from the script and provide it as the Windows return code. */
697            
698         /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
699         
700         if ( can_shutdown ) 
701                 become_root();
702
703         ret = smbrun( shutdown_script, NULL );
704                 
705         if ( can_shutdown )
706                 unbecome_root();
707
708         /********** END SeRemoteShutdownPrivilege BLOCK **********/
709         
710         DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
711                 shutdown_script, ret));
712                 
713
714         return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
715 }
716
717
718
719
720 /*******************************************************************
721  reg_abort_shutdwon
722  ********************************************************************/
723
724 WERROR _winreg_AbortSystemShutdown(pipes_struct *p, uint16_t *server)
725 {
726         pstring abort_shutdown_script;
727         int ret;
728         BOOL can_shutdown;
729
730         pstrcpy(abort_shutdown_script, lp_abort_shutdown_script());
731
732         if ( !*abort_shutdown_script )
733                 return WERR_ACCESS_DENIED;
734                 
735         can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
736                 
737         /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
738         
739         if ( can_shutdown )
740                 become_root();
741                 
742         ret = smbrun( abort_shutdown_script, NULL );
743         
744         if ( can_shutdown )
745                 unbecome_root();
746                 
747         /********** END SeRemoteShutdownPrivilege BLOCK **********/
748
749         DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",
750                 abort_shutdown_script, ret));
751                 
752
753         return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
754 }
755
756 #if 0   /* This code works but is disabled for now until I 
757            fix the WinReg IDL file -- jerry */
758
759 /*******************************************************************
760  ********************************************************************/
761
762 static int validate_reg_filename( pstring fname )
763 {
764         char *p;
765         int num_services = lp_numservices();
766         int snum;
767         pstring share_path;
768         pstring unix_fname;
769         
770         /* convert to a unix path, stripping the C:\ along the way */
771         
772         if ( !(p = valid_share_pathname( fname ) ))
773                 return -1;
774
775         /* has to exist within a valid file share */
776                         
777         for ( snum=0; snum<num_services; snum++ ) {
778         
779                 if ( !lp_snum_ok(snum) || lp_print_ok(snum) )
780                         continue;
781                 
782                 pstrcpy( share_path, lp_pathname(snum) );
783
784                 /* make sure we have a path (e.g. [homes] ) */
785
786                 if ( strlen( share_path ) == 0 )
787                         continue;
788
789                 if ( strncmp( share_path, p, strlen( share_path )) == 0 )
790                         break;
791         }
792         
793         /* p and fname are overlapping memory so copy out and back in again */
794         
795         pstrcpy( unix_fname, p );
796         pstrcpy( fname, unix_fname );
797         
798         return (snum < num_services) ? snum : -1;
799 }
800
801 /*******************************************************************
802  Note: topkeypat is the *full* path that this *key will be 
803  loaded into (including the name of the key)
804  ********************************************************************/
805
806 static WERROR reg_load_tree( REGF_FILE *regfile, const char *topkeypath,
807                              REGF_NK_REC *key )
808 {
809         REGF_NK_REC *subkey;
810         REGISTRY_KEY registry_key;
811         REGVAL_CTR *values;
812         REGSUBKEY_CTR *subkeys;
813         int i;
814         pstring path;
815         WERROR result = WERR_OK;
816         
817         /* initialize the REGISTRY_KEY structure */
818         
819         if ( !(registry_key.hook = reghook_cache_find(topkeypath)) ) {
820                 DEBUG(0,("reg_load_tree: Failed to assigned a REGISTRY_HOOK to [%s]\n",
821                         topkeypath ));
822                 return WERR_BADFILE;
823         }
824         pstrcpy( registry_key.name, topkeypath );
825         
826         /* now start parsing the values and subkeys */
827
828         if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
829                 return WERR_NOMEM;
830         
831         if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
832                 return WERR_NOMEM;
833
834         /* copy values into the REGVAL_CTR */
835         
836         for ( i=0; i<key->num_values; i++ ) {
837                 regval_ctr_addvalue( values, key->values[i].valuename, key->values[i].type,
838                         (char*)key->values[i].data, (key->values[i].data_size & ~VK_DATA_IN_OFFSET) );
839         }
840
841         /* copy subkeys into the REGSUBKEY_CTR */
842         
843         key->subkey_index = 0;
844         while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
845                 regsubkey_ctr_addkey( subkeys, subkey->keyname );
846         }
847         
848         /* write this key and values out */
849         
850         if ( !store_reg_values( &registry_key, values ) 
851                 || !store_reg_keys( &registry_key, subkeys ) )
852         {
853                 DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath));
854                 result = WERR_REG_IO_FAILURE;
855         }
856         
857         TALLOC_FREE( subkeys );
858         
859         if ( !W_ERROR_IS_OK(result) )
860                 return result;
861         
862         /* now continue to load each subkey registry tree */
863
864         key->subkey_index = 0;
865         while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
866                 pstr_sprintf( path, "%s%s%s", topkeypath, "\\", subkey->keyname );
867                 result = reg_load_tree( regfile, path, subkey );
868                 if ( !W_ERROR_IS_OK(result) )
869                         break;
870         }
871
872         return result;
873 }
874
875 /*******************************************************************
876  ********************************************************************/
877
878 static WERROR restore_registry_key ( REGISTRY_KEY *krecord, const char *fname )
879 {
880         REGF_FILE *regfile;
881         REGF_NK_REC *rootkey;
882         WERROR result;
883                 
884         /* open the registry file....fail if the file already exists */
885         
886         if ( !(regfile = regfio_open( fname, (O_RDONLY), 0 )) ) {
887                 DEBUG(0,("restore_registry_key: failed to open \"%s\" (%s)\n", 
888                         fname, strerror(errno) ));
889                 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
890         }
891         
892         /* get the rootkey from the regf file and then load the tree
893            via recursive calls */
894            
895         if ( !(rootkey = regfio_rootkey( regfile )) ) {
896                 regfio_close( regfile );
897                 return WERR_REG_FILE_INVALID;
898         }
899         
900         result = reg_load_tree( regfile, krecord->name, rootkey );
901                 
902         /* cleanup */
903         
904         regfio_close( regfile );
905         
906         return result;
907 }
908
909 #endif
910
911 /*******************************************************************
912  ********************************************************************/
913
914 WERROR _winreg_RestoreKey(pipes_struct *p)
915 {
916 #if 0   /* temporarily disabled */
917         REGISTRY_KEY    *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
918         pstring         filename;
919         int             snum;
920         
921         if ( !regkey )
922                 return WERR_BADFID; 
923
924         rpcstr_pull(filename, q_u->filename.string->buffer, sizeof(filename), q_u->filename.string->uni_str_len*2, STR_TERMINATE);
925
926         DEBUG(8,("_reg_restore_key: verifying restore of key [%s] from \"%s\"\n", regkey->name, filename));
927
928         if ( (snum = validate_reg_filename( filename )) == -1 )
929                 return WERR_OBJECT_PATH_INVALID;
930                 
931         /* user must posses SeRestorePrivilege for this this proceed */
932         
933         if ( !user_has_privileges( p->pipe_user.nt_user_token, &se_restore ) )
934                 return WERR_ACCESS_DENIED;
935                 
936         DEBUG(2,("_reg_restore_key: Restoring [%s] from %s in share %s\n", regkey->name, filename, lp_servicename(snum) ));
937
938         return restore_registry_key( regkey, filename );
939 #endif
940
941         return WERR_NOT_SUPPORTED;
942 }
943
944 #if 0   /* this code works but has been disable until I fix
945            the winreg IDL    -- jerry */
946
947 /********************************************************************
948 ********************************************************************/
949
950 static WERROR reg_write_tree( REGF_FILE *regfile, const char *keypath,
951                               REGF_NK_REC *parent, SEC_DESC *sec_desc )
952 {
953         REGF_NK_REC *key;
954         REGVAL_CTR *values;
955         REGSUBKEY_CTR *subkeys;
956         int i, num_subkeys;
957         pstring key_tmp;
958         char *keyname, *parentpath;
959         pstring subkeypath;
960         char *subkeyname;
961         REGISTRY_KEY registry_key;
962         WERROR result = WERR_OK;
963         
964         if ( !regfile )
965                 return WERR_GENERAL_FAILURE;
966                 
967         if ( !keypath )
968                 return WERR_OBJECT_PATH_INVALID;
969                 
970         /* split up the registry key path */
971         
972         pstrcpy( key_tmp, keypath );
973         if ( !reg_split_key( key_tmp, &parentpath, &keyname ) )
974                 return WERR_OBJECT_PATH_INVALID;
975
976         if ( !keyname )
977                 keyname = parentpath;
978
979         /* we need a REGISTRY_KEY object here to enumerate subkeys and values */
980         
981         ZERO_STRUCT( registry_key );
982         pstrcpy( registry_key.name, keypath );
983         if ( !(registry_key.hook = reghook_cache_find( registry_key.name )) )
984                 return WERR_BADFILE;
985
986         
987         /* lookup the values and subkeys */
988         
989         if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
990                 return WERR_NOMEM;
991
992         if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
993                 return WERR_NOMEM;
994
995         fetch_reg_keys( &registry_key, subkeys );
996         fetch_reg_values( &registry_key, values );
997
998         /* write out this key */
999                 
1000         if ( !(key = regfio_write_key( regfile, keyname, values, subkeys, sec_desc, parent )) ) {
1001                 result = WERR_CAN_NOT_COMPLETE;
1002                 goto done;
1003         }
1004
1005         /* write each one of the subkeys out */
1006
1007         num_subkeys = regsubkey_ctr_numkeys( subkeys );
1008         for ( i=0; i<num_subkeys; i++ ) {
1009                 subkeyname = regsubkey_ctr_specific_key( subkeys, i );
1010                 pstr_sprintf( subkeypath, "%s\\%s", keypath, subkeyname );
1011                 result = reg_write_tree( regfile, subkeypath, key, sec_desc );
1012                 if ( !W_ERROR_IS_OK(result) )
1013                         goto done;
1014         }
1015
1016         DEBUG(6,("reg_write_tree: wrote key [%s]\n", keypath ));
1017
1018 done:
1019         TALLOC_FREE( subkeys );
1020
1021         return result;
1022 }
1023
1024 /*******************************************************************
1025  ********************************************************************/
1026
1027 static WERROR make_default_reg_sd( TALLOC_CTX *ctx, SEC_DESC **psd )
1028 {
1029         DOM_SID adm_sid, owner_sid;
1030         SEC_ACE ace[2];         /* at most 2 entries */
1031         SEC_ACCESS mask;
1032         SEC_ACL *psa = NULL;
1033         size_t sd_size;
1034
1035         /* set the owner to BUILTIN\Administrator */
1036
1037         sid_copy(&owner_sid, &global_sid_Builtin);
1038         sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN );
1039         
1040
1041         /* basic access for Everyone */
1042
1043         init_sec_access(&mask, reg_generic_map.generic_execute | reg_generic_map.generic_read );
1044         init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
1045
1046         /* add Full Access 'BUILTIN\Administrators' */
1047
1048         init_sec_access(&mask, reg_generic_map.generic_all);
1049         sid_copy(&adm_sid, &global_sid_Builtin);
1050         sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
1051         init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
1052
1053         /* create the security descriptor */
1054
1055         if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 2, ace)) == NULL)
1056                 return WERR_NOMEM;
1057
1058         if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, &owner_sid, NULL, NULL, psa, &sd_size)) == NULL)
1059                 return WERR_NOMEM;
1060
1061         return WERR_OK;
1062 }
1063
1064 /*******************************************************************
1065  ********************************************************************/
1066
1067 static WERROR backup_registry_key ( REGISTRY_KEY *krecord, const char *fname )
1068 {
1069         REGF_FILE *regfile;
1070         WERROR result;
1071         SEC_DESC *sd = NULL;
1072         
1073         /* open the registry file....fail if the file already exists */
1074         
1075         if ( !(regfile = regfio_open( fname, (O_RDWR|O_CREAT|O_EXCL), (S_IREAD|S_IWRITE) )) ) {
1076                 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n", 
1077                         fname, strerror(errno) ));
1078                 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
1079         }
1080         
1081         if ( !W_ERROR_IS_OK(result = make_default_reg_sd( regfile->mem_ctx, &sd )) ) {
1082                 regfio_close( regfile );
1083                 return result;
1084         }
1085                 
1086         /* write the registry tree to the file  */
1087         
1088         result = reg_write_tree( regfile, krecord->name, NULL, sd );
1089                 
1090         /* cleanup */
1091         
1092         regfio_close( regfile );
1093         
1094         return result;
1095 }
1096 #endif
1097
1098 /*******************************************************************
1099  ********************************************************************/
1100
1101 WERROR _winreg_SaveKey(pipes_struct *p)
1102 {
1103 #if 0
1104         REGISTRY_KEY    *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
1105         pstring         filename;
1106         int             snum;
1107         
1108         if ( !regkey )
1109                 return WERR_BADFID; 
1110
1111         rpcstr_pull(filename, q_u->filename.string->buffer, sizeof(filename), q_u->filename.string->uni_str_len*2, STR_TERMINATE);
1112
1113         DEBUG(8,("_reg_save_key: verifying backup of key [%s] to \"%s\"\n", regkey->name, filename));
1114         
1115         if ( (snum = validate_reg_filename( filename )) == -1 )
1116                 return WERR_OBJECT_PATH_INVALID;
1117                 
1118         DEBUG(2,("_reg_save_key: Saving [%s] to %s in share %s\n", regkey->name, filename, lp_servicename(snum) ));
1119                 
1120         return backup_registry_key( regkey, filename );
1121 #endif
1122
1123         /* disabled for now until I fix the IDL  --jerry */
1124         return WERR_NOT_SUPPORTED;
1125 }
1126
1127 /*******************************************************************
1128  ********************************************************************/
1129
1130 WERROR _winreg_SaveKeyEx(pipes_struct *p)
1131 {
1132         /* disabled for now until I fix the IDL  --jerry */
1133         return WERR_NOT_SUPPORTED;
1134 }
1135
1136 /*******************************************************************
1137  ********************************************************************/
1138
1139 WERROR _winreg_CreateKey( pipes_struct *p, struct policy_handle *handle, struct winreg_String keyname, 
1140                           struct winreg_String keyclass, uint32_t options, uint32_t access_mask, 
1141                           struct winreg_SecBuf *secdesc, struct policy_handle *new_handle, 
1142                           enum winreg_CreateAction *action_taken )
1143 {
1144         REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, handle);
1145         REGISTRY_KEY *newparentinfo, *keyinfo;
1146         POLICY_HND newparent_handle;
1147         REGSUBKEY_CTR *subkeys;
1148         BOOL write_result;
1149         char *name;
1150         WERROR result;
1151
1152         if ( !parent )
1153                 return WERR_BADFID;
1154
1155         if ( (name = talloc_strdup( p->mem_ctx, keyname.name )) == NULL ) {
1156                 return WERR_NOMEM;
1157         }
1158         
1159         /* ok.  Here's what we do.  */
1160
1161         if ( strrchr( name, '\\' ) ) {
1162                 pstring newkeyname;
1163                 char *ptr;
1164                 
1165                 /* (1) check for enumerate rights on the parent handle.  CLients can try 
1166                        create things like 'SOFTWARE\Samba' on the HKLM handle. 
1167                    (2) open the path to the child parent key if necessary */
1168         
1169                 if ( !(parent->access_granted & SEC_RIGHTS_ENUM_SUBKEYS) )
1170                         return WERR_ACCESS_DENIED;
1171                 
1172                 pstrcpy( newkeyname, name );
1173                 ptr = strrchr( newkeyname, '\\' );
1174                 *ptr = '\0';
1175
1176                 result = open_registry_key( p, &newparent_handle, &newparentinfo, 
1177                         parent, newkeyname, (REG_KEY_READ|REG_KEY_WRITE) );
1178                         
1179                 if ( !W_ERROR_IS_OK(result) )
1180                         return result;
1181
1182                 /* copy the new key name (just the lower most keyname) */
1183
1184                 pstrcpy( name, ptr+1 );
1185         }
1186         else {
1187                 /* use the existing open key information */
1188                 newparentinfo = parent;
1189                 memcpy( &newparent_handle, handle, sizeof(POLICY_HND) );
1190         }
1191         
1192         /* (3) check for create subkey rights on the correct parent */
1193         
1194         if ( !(newparentinfo->access_granted & SEC_RIGHTS_CREATE_SUBKEY) ) {
1195                 result = WERR_ACCESS_DENIED;
1196                 goto done;
1197         }       
1198                 
1199         if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) {
1200                 result = WERR_NOMEM;
1201                 goto done;
1202         }
1203
1204         /* (4) lookup the current keys and add the new one */
1205         
1206         fetch_reg_keys( newparentinfo, subkeys );
1207         regsubkey_ctr_addkey( subkeys, name );
1208         
1209         /* now write to the registry backend */
1210         
1211         write_result = store_reg_keys( newparentinfo, subkeys );
1212         
1213         TALLOC_FREE( subkeys );
1214
1215         if ( !write_result )
1216                 return WERR_REG_IO_FAILURE;
1217                 
1218         /* (5) open the new key and return the handle.  Note that it is probably 
1219            not correct to grant full access on this open handle. */
1220         
1221         result = open_registry_key( p, new_handle, &keyinfo, newparentinfo, name, REG_KEY_READ );
1222         keyinfo->access_granted = REG_KEY_ALL;
1223         
1224         /* FIXME: report the truth here */
1225         
1226         *action_taken = REG_CREATED_NEW_KEY;
1227
1228 done:
1229         /* close any intermediate key handles */
1230         
1231         if ( newparentinfo != parent )
1232                 close_registry_key( p, &newparent_handle );
1233                 
1234         return result;
1235 }
1236
1237
1238 /*******************************************************************
1239  ********************************************************************/
1240
1241 WERROR _winreg_SetValue(pipes_struct *p, struct policy_handle *handle, struct winreg_String name, enum winreg_Type type, uint8_t *data, uint32_t size)
1242 {
1243         REGISTRY_KEY *key = find_regkey_index_by_hnd(p, handle);
1244         REGVAL_CTR *values;
1245         BOOL write_result;
1246         char *valuename;
1247
1248         if ( !key )
1249                 return WERR_BADFID;
1250                 
1251         /* access checks first */
1252         
1253         if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
1254                 return WERR_ACCESS_DENIED;
1255                 
1256         /* verify the name */
1257         
1258         if ( (valuename = talloc_strdup(p->mem_ctx, name.name)) == NULL ) {
1259                 return WERR_INVALID_PARAM;
1260         }
1261
1262         DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n", key->name, valuename));
1263                 
1264         if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
1265                 return WERR_NOMEM; 
1266         
1267         /* lookup the current values and add the new one */
1268         
1269         fetch_reg_values( key, values );
1270         
1271         regval_ctr_addvalue( values, valuename, type, (const char *)data, size );
1272         
1273         /* now write to the registry backend */
1274         
1275         write_result = store_reg_values( key, values );
1276         
1277         TALLOC_FREE( values );
1278         
1279         if ( !write_result )
1280                 return WERR_REG_IO_FAILURE;
1281                 
1282         return WERR_OK;
1283 }
1284
1285 /*******************************************************************
1286  ********************************************************************/
1287
1288 WERROR _winreg_DeleteKey(pipes_struct *p, struct policy_handle *handle, struct winreg_String key)
1289 {
1290         REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, handle);
1291         REGISTRY_KEY *newparentinfo = NULL;
1292         POLICY_HND newparent_handle;
1293         REGSUBKEY_CTR *subkeys;
1294         BOOL write_result;
1295         char *name;
1296         WERROR result;
1297
1298         if ( !parent )
1299                 return WERR_BADFID;
1300
1301         /* MSDN says parent the handle must have been opened with DELETE access */
1302
1303         /* (1) check for delete rights on the parent */
1304         
1305         if ( !(parent->access_granted & STD_RIGHT_DELETE_ACCESS) ) {
1306                 result = WERR_ACCESS_DENIED;
1307                 goto done;
1308         }
1309                 
1310         if ( (name = talloc_strdup( p->mem_ctx, key.name )) == NULL ) {
1311                 result = WERR_INVALID_PARAM;
1312                 goto done;
1313         }
1314                 
1315         /* ok.  Here's what we do.  */
1316
1317         if ( strrchr( name, '\\' ) ) {
1318                 pstring newkeyname;
1319                 char *ptr;
1320                 
1321                 /* (2) open the path to the child parent key if necessary */
1322                 /* split the registry path and save the subkeyname */
1323         
1324                 pstrcpy( newkeyname, name );
1325                 ptr = strrchr( newkeyname, '\\' );
1326                 *ptr = '\0';
1327                 pstrcpy( name, ptr+1 );
1328
1329                 result = open_registry_key( p, &newparent_handle, &newparentinfo, parent, newkeyname, (REG_KEY_READ|REG_KEY_WRITE) );
1330                 if ( !W_ERROR_IS_OK(result) )
1331                         return result;
1332         }
1333         else {
1334                 /* use the existing open key information */
1335                 newparentinfo = parent;
1336         }
1337         
1338         if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) {
1339                 result = WERR_NOMEM;
1340                 goto done;
1341         }
1342         
1343         /* lookup the current keys and delete the new one */
1344         
1345         fetch_reg_keys( newparentinfo, subkeys );
1346         
1347         regsubkey_ctr_delkey( subkeys, name );
1348         
1349         /* now write to the registry backend */
1350         
1351         write_result = store_reg_keys( newparentinfo, subkeys );
1352         
1353         TALLOC_FREE( subkeys );
1354
1355         result = write_result ? WERR_OK : WERR_REG_IO_FAILURE;
1356         
1357 done:
1358         /* close any intermediate key handles */
1359         
1360         if ( newparentinfo != parent )
1361                 close_registry_key( p, &newparent_handle );
1362
1363         return result;
1364 }
1365
1366
1367 /*******************************************************************
1368  ********************************************************************/
1369
1370 WERROR _winreg_DeleteValue(pipes_struct *p, struct policy_handle *handle, struct winreg_String value)
1371 {
1372         REGISTRY_KEY *key = find_regkey_index_by_hnd(p, handle);
1373         REGVAL_CTR *values;
1374         BOOL write_result;
1375         char *valuename;
1376         
1377         if ( !key )
1378                 return WERR_BADFID;
1379                 
1380         /* access checks first */
1381         
1382         if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
1383                 return WERR_ACCESS_DENIED;
1384
1385         if ( (valuename = talloc_strdup( p->mem_ctx, value.name )) == NULL ) {
1386                 return WERR_INVALID_PARAM;
1387         }
1388
1389         DEBUG(8,("_reg_delete_value: Setting value for [%s:%s]\n", key->name, valuename));
1390
1391         if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
1392                 return WERR_NOMEM;
1393         
1394         /* lookup the current values and add the new one */
1395         
1396         fetch_reg_values( key, values );
1397         
1398         regval_ctr_delvalue( values, valuename );
1399         
1400         /* now write to the registry backend */
1401         
1402         write_result = store_reg_values( key, values );
1403         
1404         TALLOC_FREE( values );
1405         
1406         if ( !write_result )
1407                 return WERR_REG_IO_FAILURE;
1408                 
1409         return WERR_OK;
1410 }
1411
1412 /*******************************************************************
1413  ********************************************************************/
1414
1415 WERROR _winreg_GetKeySecurity(pipes_struct *p, struct policy_handle *handle, uint32_t sec_info, struct KeySecurityData *sd)
1416 {
1417         REGISTRY_KEY *key = find_regkey_index_by_hnd(p, handle);
1418
1419         if ( !key )
1420                 return WERR_BADFID;
1421                 
1422         /* access checks first */
1423         
1424         if ( !(key->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
1425                 return WERR_ACCESS_DENIED;
1426                 
1427         return WERR_ACCESS_DENIED;
1428 }
1429
1430 /*******************************************************************
1431  ********************************************************************/
1432
1433 WERROR _winreg_SetKeySecurity(pipes_struct *p, struct policy_handle *handle, uint32_t access_mask, struct KeySecurityData *sd)
1434 {
1435         REGISTRY_KEY *key = find_regkey_index_by_hnd(p, handle);
1436
1437         if ( !key )
1438                 return WERR_BADFID;
1439                 
1440         /* access checks first */
1441         
1442         if ( !(key->access_granted & STD_RIGHT_WRITE_DAC_ACCESS) )
1443                 return WERR_ACCESS_DENIED;
1444                 
1445         return WERR_ACCESS_DENIED;
1446 }
1447
1448 /*******************************************************************
1449  ********************************************************************/
1450
1451 WERROR _winreg_FlushKey(pipes_struct *p, struct policy_handle *handle)
1452 {
1453         /* I'm just replying OK because there's not a lot 
1454            here I see to do i  --jerry */
1455         
1456         return WERR_OK;
1457 }
1458
1459 /*******************************************************************
1460  ********************************************************************/
1461
1462 WERROR _winreg_UnLoadKey(pipes_struct *p)
1463 {
1464         /* fill in your code here if you think this call should
1465            do anything */
1466
1467         return WERR_NOT_SUPPORTED;
1468 }
1469
1470 /*******************************************************************
1471  ********************************************************************/
1472
1473 WERROR _winreg_ReplaceKey(pipes_struct *p)
1474 {
1475         /* fill in your code here if you think this call should
1476            do anything */
1477
1478         return WERR_NOT_SUPPORTED;
1479 }
1480
1481 /*******************************************************************
1482  ********************************************************************/
1483
1484 WERROR _winreg_LoadKey(pipes_struct *p, struct policy_handle *handle, struct winreg_String *keyname, struct winreg_String *filename)
1485 {
1486         /* fill in your code here if you think this call should
1487            do anything */
1488
1489         return WERR_NOT_SUPPORTED;
1490 }
1491
1492 /*******************************************************************
1493  ********************************************************************/
1494
1495 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)
1496 {
1497         /* fill in your code here if you think this call should
1498            do anything */
1499
1500         return WERR_NOT_SUPPORTED;
1501 }
1502
1503 /*******************************************************************
1504  ********************************************************************/
1505
1506 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)
1507 {
1508         /* fill in your code here if you think this call should
1509            do anything */
1510
1511         return WERR_NOT_SUPPORTED;
1512 }
1513
1514 /*******************************************************************
1515  ********************************************************************/
1516
1517 WERROR _winreg_QueryMultipleValues2(pipes_struct *p)
1518 {
1519         /* fill in your code here if you think this call should
1520            do anything */
1521
1522         return WERR_NOT_SUPPORTED;
1523 }
1524