r18934: fix a segv in CreateKey()
[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                 *data_size = *value_length;
484         }
485
486         TALLOC_FREE( regvals );
487         free_registry_value( val );
488
489         return status;
490 }
491
492 /*****************************************************************************
493  Implementation of REG_QUERY_KEY
494  ****************************************************************************/
495
496 WERROR _winreg_QueryInfoKey(pipes_struct *p, struct policy_handle *handle, 
497                             struct winreg_String *classname, 
498                             uint32_t *num_subkeys, uint32_t *max_subkeylen, 
499                             uint32_t *max_subkeysize, 
500                             uint32_t *num_values, uint32_t *max_valnamelen, 
501                             uint32_t *max_valbufsize, 
502                             uint32_t *secdescsize, NTTIME *last_changed_time)
503 {
504         WERROR  status = WERR_OK;
505         REGISTRY_KEY    *regkey = find_regkey_index_by_hnd( p, handle );
506         
507         if ( !regkey )
508                 return WERR_BADFID; 
509         
510         if ( !get_subkey_information( regkey, num_subkeys, max_subkeylen) ) {
511                 DEBUG(0,("_winreg_QueryInfoKey: get_subkey_information() failed!\n"));
512                 return WERR_ACCESS_DENIED;
513         }
514                 
515         if ( !get_value_information( regkey, num_values, max_valnamelen, max_valbufsize) ) {
516                 DEBUG(0,("_winreg_QueryInfoKey: get_value_information() failed!\n"));
517                 return WERR_ACCESS_DENIED;      
518         }
519
520         *secdescsize = 0;       /* used to be hard coded for 0x00000078 */
521         *last_changed_time = 0;
522         *max_subkeysize = 0;    /* maybe this is the classname length ? */
523
524         /* don't bother with class names for now */
525         
526         classname->name = NULL;
527         
528         return status;
529 }
530
531
532 /*****************************************************************************
533  Implementation of REG_GETVERSION
534  ****************************************************************************/
535  
536 WERROR _winreg_GetVersion(pipes_struct *p, struct policy_handle *handle, uint32_t *version)
537 {
538         REGISTRY_KEY    *regkey = find_regkey_index_by_hnd( p, handle );
539         
540         if ( !regkey )
541                 return WERR_BADFID;
542         
543         *version = 0x00000005;  /* Windows 2000 registry API version */
544         
545         return WERR_OK;
546 }
547
548
549 /*****************************************************************************
550  Implementation of REG_ENUM_KEY
551  ****************************************************************************/
552  
553 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)
554 {
555         WERROR  status = WERR_OK;
556         REGISTRY_KEY    *regkey = find_regkey_index_by_hnd( p, handle );
557         char            *subkey = NULL;
558         
559         
560         if ( !regkey )
561                 return WERR_BADFID; 
562
563         if ( !name || !keyclass )
564                 return WERR_INVALID_PARAM;
565
566         DEBUG(8,("_reg_enum_key: enumerating key [%s]\n", regkey->name));
567         
568         if ( !fetch_reg_keys_specific( regkey, &subkey, enum_index ) ) {
569                 status = WERR_NO_MORE_ITEMS;
570                 goto done;
571         }
572         
573         DEBUG(10,("_reg_enum_key: retrieved subkey named [%s]\n", subkey));
574         
575         if ( last_changed_time ) {
576                 *last_changed_time = 0;
577         }
578         keyclass->name = NULL;
579         if ( (name->name = talloc_strdup( p->mem_ctx, subkey )) == NULL ) {
580                 status = WERR_NOMEM;
581         }
582
583 done:   
584         SAFE_FREE( subkey );
585         return status;
586 }
587
588 /*****************************************************************************
589  Implementation of REG_ENUM_VALUE
590  ****************************************************************************/
591
592 WERROR _winreg_EnumValue(pipes_struct *p, struct policy_handle *handle, uint32_t enum_index, struct winreg_StringBuf *name, enum winreg_Type *type, uint8_t *data, uint32_t *data_size, uint32_t *value_length)
593 {
594         WERROR  status = WERR_OK;
595         REGISTRY_KEY    *regkey = find_regkey_index_by_hnd( p, handle );
596         REGISTRY_VALUE  *val;
597         
598         if ( !regkey )
599                 return WERR_BADFID; 
600
601         if ( !name )
602                 return WERR_INVALID_PARAM;
603                 
604         DEBUG(8,("_winreg_EnumValue: enumerating values for key [%s]\n", regkey->name));
605
606         if ( !fetch_reg_values_specific( regkey, &val, enum_index ) ) {
607                 status = WERR_NO_MORE_ITEMS;
608                 goto done;
609         }
610
611         DEBUG(10,("_winreg_EnumValue: retrieved value named  [%s]\n", val->valuename));
612         
613         /* subkey has the string name now */
614         
615         if ( (name->name = talloc_strdup( p->mem_ctx, val->valuename )) == NULL ) {
616                 status = WERR_NOMEM;
617         }
618
619         *value_length =  regval_size( val );
620         *type = val->type;
621
622         if ( *data_size == 0 ) {
623                 status = WERR_OK;
624         } else if ( *value_length > *data_size ) {
625                 status = WERR_MORE_DATA;
626         } else {
627                 memcpy( data, regval_data_p(val), *value_length );
628                 status = WERR_OK;
629         }
630
631         *data_size = *value_length;
632
633 done:   
634         free_registry_value( val );
635         
636         return status;
637 }
638
639
640 /*******************************************************************
641  reg_shutdwon
642  ********************************************************************/
643
644 WERROR _winreg_InitiateSystemShutdown(pipes_struct *p, uint16_t *hostname, struct initshutdown_String *message, uint32_t timeout, uint8_t force_apps, uint8_t reboot)
645 {
646         uint32_t reason = 0;
647
648         /* thunk down to _winreg_InitiateSystemShutdownEx() 
649            (just returns a status) */
650         
651         return _winreg_InitiateSystemShutdownEx( p, hostname, message, timeout, 
652                 force_apps, reboot, reason );
653 }
654
655 /*******************************************************************
656  reg_shutdown_ex
657  ********************************************************************/
658
659 #define SHUTDOWN_R_STRING "-r"
660 #define SHUTDOWN_F_STRING "-f"
661
662
663 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)
664 {
665         pstring shutdown_script;
666         char *msg = NULL;
667         pstring chkmsg;
668         fstring str_timeout;
669         fstring str_reason;
670         fstring r;
671         fstring f;
672         int ret;
673         BOOL can_shutdown;
674         
675
676         pstrcpy(shutdown_script, lp_shutdown_script());
677         
678         if ( !*shutdown_script )
679                 return WERR_ACCESS_DENIED;
680
681         /* pull the message string and perform necessary sanity checks on it */
682
683         if ( message && message->name && message->name->name ) {
684                 if ( (msg = talloc_strdup(p->mem_ctx, message->name->name )) == NULL ) {
685                         return WERR_NOMEM;
686                 }
687         } 
688         alpha_strcpy (chkmsg, msg?msg:"", NULL, strlen(msg));
689                 
690         fstr_sprintf(str_timeout, "%d", timeout);
691         fstr_sprintf(r, reboot ? SHUTDOWN_R_STRING : "");
692         fstr_sprintf(f, force_apps ? SHUTDOWN_F_STRING : "");
693         fstr_sprintf(str_reason, "%d", reason );
694
695         all_string_sub( shutdown_script, "%z", chkmsg, sizeof(shutdown_script) );
696         all_string_sub( shutdown_script, "%t", str_timeout, sizeof(shutdown_script) );
697         all_string_sub( shutdown_script, "%r", r, sizeof(shutdown_script) );
698         all_string_sub( shutdown_script, "%f", f, sizeof(shutdown_script) );
699         all_string_sub( shutdown_script, "%x", str_reason, sizeof(shutdown_script) );
700
701         can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
702                 
703         /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
704            Take the error return from the script and provide it as the Windows return code. */
705            
706         /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
707         
708         if ( can_shutdown ) 
709                 become_root();
710
711         ret = smbrun( shutdown_script, NULL );
712                 
713         if ( can_shutdown )
714                 unbecome_root();
715
716         /********** END SeRemoteShutdownPrivilege BLOCK **********/
717         
718         DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
719                 shutdown_script, ret));
720                 
721
722         return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
723 }
724
725
726
727
728 /*******************************************************************
729  reg_abort_shutdwon
730  ********************************************************************/
731
732 WERROR _winreg_AbortSystemShutdown(pipes_struct *p, uint16_t *server)
733 {
734         pstring abort_shutdown_script;
735         int ret;
736         BOOL can_shutdown;
737
738         pstrcpy(abort_shutdown_script, lp_abort_shutdown_script());
739
740         if ( !*abort_shutdown_script )
741                 return WERR_ACCESS_DENIED;
742                 
743         can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
744                 
745         /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
746         
747         if ( can_shutdown )
748                 become_root();
749                 
750         ret = smbrun( abort_shutdown_script, NULL );
751         
752         if ( can_shutdown )
753                 unbecome_root();
754                 
755         /********** END SeRemoteShutdownPrivilege BLOCK **********/
756
757         DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",
758                 abort_shutdown_script, ret));
759                 
760
761         return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
762 }
763
764 #if 0   /* This code works but is disabled for now until I 
765            fix the WinReg IDL file -- jerry */
766
767 /*******************************************************************
768  ********************************************************************/
769
770 static int validate_reg_filename( pstring fname )
771 {
772         char *p;
773         int num_services = lp_numservices();
774         int snum;
775         pstring share_path;
776         pstring unix_fname;
777         
778         /* convert to a unix path, stripping the C:\ along the way */
779         
780         if ( !(p = valid_share_pathname( fname ) ))
781                 return -1;
782
783         /* has to exist within a valid file share */
784                         
785         for ( snum=0; snum<num_services; snum++ ) {
786         
787                 if ( !lp_snum_ok(snum) || lp_print_ok(snum) )
788                         continue;
789                 
790                 pstrcpy( share_path, lp_pathname(snum) );
791
792                 /* make sure we have a path (e.g. [homes] ) */
793
794                 if ( strlen( share_path ) == 0 )
795                         continue;
796
797                 if ( strncmp( share_path, p, strlen( share_path )) == 0 )
798                         break;
799         }
800         
801         /* p and fname are overlapping memory so copy out and back in again */
802         
803         pstrcpy( unix_fname, p );
804         pstrcpy( fname, unix_fname );
805         
806         return (snum < num_services) ? snum : -1;
807 }
808
809 /*******************************************************************
810  Note: topkeypat is the *full* path that this *key will be 
811  loaded into (including the name of the key)
812  ********************************************************************/
813
814 static WERROR reg_load_tree( REGF_FILE *regfile, const char *topkeypath,
815                              REGF_NK_REC *key )
816 {
817         REGF_NK_REC *subkey;
818         REGISTRY_KEY registry_key;
819         REGVAL_CTR *values;
820         REGSUBKEY_CTR *subkeys;
821         int i;
822         pstring path;
823         WERROR result = WERR_OK;
824         
825         /* initialize the REGISTRY_KEY structure */
826         
827         if ( !(registry_key.hook = reghook_cache_find(topkeypath)) ) {
828                 DEBUG(0,("reg_load_tree: Failed to assigned a REGISTRY_HOOK to [%s]\n",
829                         topkeypath ));
830                 return WERR_BADFILE;
831         }
832         pstrcpy( registry_key.name, topkeypath );
833         
834         /* now start parsing the values and subkeys */
835
836         if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
837                 return WERR_NOMEM;
838         
839         if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
840                 return WERR_NOMEM;
841
842         /* copy values into the REGVAL_CTR */
843         
844         for ( i=0; i<key->num_values; i++ ) {
845                 regval_ctr_addvalue( values, key->values[i].valuename, key->values[i].type,
846                         (char*)key->values[i].data, (key->values[i].data_size & ~VK_DATA_IN_OFFSET) );
847         }
848
849         /* copy subkeys into the REGSUBKEY_CTR */
850         
851         key->subkey_index = 0;
852         while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
853                 regsubkey_ctr_addkey( subkeys, subkey->keyname );
854         }
855         
856         /* write this key and values out */
857         
858         if ( !store_reg_values( &registry_key, values ) 
859                 || !store_reg_keys( &registry_key, subkeys ) )
860         {
861                 DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath));
862                 result = WERR_REG_IO_FAILURE;
863         }
864         
865         TALLOC_FREE( subkeys );
866         
867         if ( !W_ERROR_IS_OK(result) )
868                 return result;
869         
870         /* now continue to load each subkey registry tree */
871
872         key->subkey_index = 0;
873         while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
874                 pstr_sprintf( path, "%s%s%s", topkeypath, "\\", subkey->keyname );
875                 result = reg_load_tree( regfile, path, subkey );
876                 if ( !W_ERROR_IS_OK(result) )
877                         break;
878         }
879
880         return result;
881 }
882
883 /*******************************************************************
884  ********************************************************************/
885
886 static WERROR restore_registry_key ( REGISTRY_KEY *krecord, const char *fname )
887 {
888         REGF_FILE *regfile;
889         REGF_NK_REC *rootkey;
890         WERROR result;
891                 
892         /* open the registry file....fail if the file already exists */
893         
894         if ( !(regfile = regfio_open( fname, (O_RDONLY), 0 )) ) {
895                 DEBUG(0,("restore_registry_key: failed to open \"%s\" (%s)\n", 
896                         fname, strerror(errno) ));
897                 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
898         }
899         
900         /* get the rootkey from the regf file and then load the tree
901            via recursive calls */
902            
903         if ( !(rootkey = regfio_rootkey( regfile )) ) {
904                 regfio_close( regfile );
905                 return WERR_REG_FILE_INVALID;
906         }
907         
908         result = reg_load_tree( regfile, krecord->name, rootkey );
909                 
910         /* cleanup */
911         
912         regfio_close( regfile );
913         
914         return result;
915 }
916
917 #endif
918
919 /*******************************************************************
920  ********************************************************************/
921
922 WERROR _winreg_RestoreKey(pipes_struct *p)
923 {
924 #if 0   /* temporarily disabled */
925         REGISTRY_KEY    *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
926         pstring         filename;
927         int             snum;
928         
929         if ( !regkey )
930                 return WERR_BADFID; 
931
932         rpcstr_pull(filename, q_u->filename.string->buffer, sizeof(filename), q_u->filename.string->uni_str_len*2, STR_TERMINATE);
933
934         DEBUG(8,("_reg_restore_key: verifying restore of key [%s] from \"%s\"\n", regkey->name, filename));
935
936         if ( (snum = validate_reg_filename( filename )) == -1 )
937                 return WERR_OBJECT_PATH_INVALID;
938                 
939         /* user must posses SeRestorePrivilege for this this proceed */
940         
941         if ( !user_has_privileges( p->pipe_user.nt_user_token, &se_restore ) )
942                 return WERR_ACCESS_DENIED;
943                 
944         DEBUG(2,("_reg_restore_key: Restoring [%s] from %s in share %s\n", regkey->name, filename, lp_servicename(snum) ));
945
946         return restore_registry_key( regkey, filename );
947 #endif
948
949         return WERR_NOT_SUPPORTED;
950 }
951
952 #if 0   /* this code works but has been disable until I fix
953            the winreg IDL    -- jerry */
954
955 /********************************************************************
956 ********************************************************************/
957
958 static WERROR reg_write_tree( REGF_FILE *regfile, const char *keypath,
959                               REGF_NK_REC *parent, SEC_DESC *sec_desc )
960 {
961         REGF_NK_REC *key;
962         REGVAL_CTR *values;
963         REGSUBKEY_CTR *subkeys;
964         int i, num_subkeys;
965         pstring key_tmp;
966         char *keyname, *parentpath;
967         pstring subkeypath;
968         char *subkeyname;
969         REGISTRY_KEY registry_key;
970         WERROR result = WERR_OK;
971         
972         if ( !regfile )
973                 return WERR_GENERAL_FAILURE;
974                 
975         if ( !keypath )
976                 return WERR_OBJECT_PATH_INVALID;
977                 
978         /* split up the registry key path */
979         
980         pstrcpy( key_tmp, keypath );
981         if ( !reg_split_key( key_tmp, &parentpath, &keyname ) )
982                 return WERR_OBJECT_PATH_INVALID;
983
984         if ( !keyname )
985                 keyname = parentpath;
986
987         /* we need a REGISTRY_KEY object here to enumerate subkeys and values */
988         
989         ZERO_STRUCT( registry_key );
990         pstrcpy( registry_key.name, keypath );
991         if ( !(registry_key.hook = reghook_cache_find( registry_key.name )) )
992                 return WERR_BADFILE;
993
994         
995         /* lookup the values and subkeys */
996         
997         if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
998                 return WERR_NOMEM;
999
1000         if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
1001                 return WERR_NOMEM;
1002
1003         fetch_reg_keys( &registry_key, subkeys );
1004         fetch_reg_values( &registry_key, values );
1005
1006         /* write out this key */
1007                 
1008         if ( !(key = regfio_write_key( regfile, keyname, values, subkeys, sec_desc, parent )) ) {
1009                 result = WERR_CAN_NOT_COMPLETE;
1010                 goto done;
1011         }
1012
1013         /* write each one of the subkeys out */
1014
1015         num_subkeys = regsubkey_ctr_numkeys( subkeys );
1016         for ( i=0; i<num_subkeys; i++ ) {
1017                 subkeyname = regsubkey_ctr_specific_key( subkeys, i );
1018                 pstr_sprintf( subkeypath, "%s\\%s", keypath, subkeyname );
1019                 result = reg_write_tree( regfile, subkeypath, key, sec_desc );
1020                 if ( !W_ERROR_IS_OK(result) )
1021                         goto done;
1022         }
1023
1024         DEBUG(6,("reg_write_tree: wrote key [%s]\n", keypath ));
1025
1026 done:
1027         TALLOC_FREE( subkeys );
1028
1029         return result;
1030 }
1031
1032 /*******************************************************************
1033  ********************************************************************/
1034
1035 static WERROR make_default_reg_sd( TALLOC_CTX *ctx, SEC_DESC **psd )
1036 {
1037         DOM_SID adm_sid, owner_sid;
1038         SEC_ACE ace[2];         /* at most 2 entries */
1039         SEC_ACCESS mask;
1040         SEC_ACL *psa = NULL;
1041         size_t sd_size;
1042
1043         /* set the owner to BUILTIN\Administrator */
1044
1045         sid_copy(&owner_sid, &global_sid_Builtin);
1046         sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN );
1047         
1048
1049         /* basic access for Everyone */
1050
1051         init_sec_access(&mask, reg_generic_map.generic_execute | reg_generic_map.generic_read );
1052         init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
1053
1054         /* add Full Access 'BUILTIN\Administrators' */
1055
1056         init_sec_access(&mask, reg_generic_map.generic_all);
1057         sid_copy(&adm_sid, &global_sid_Builtin);
1058         sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
1059         init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
1060
1061         /* create the security descriptor */
1062
1063         if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 2, ace)) == NULL)
1064                 return WERR_NOMEM;
1065
1066         if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, &owner_sid, NULL, NULL, psa, &sd_size)) == NULL)
1067                 return WERR_NOMEM;
1068
1069         return WERR_OK;
1070 }
1071
1072 /*******************************************************************
1073  ********************************************************************/
1074
1075 static WERROR backup_registry_key ( REGISTRY_KEY *krecord, const char *fname )
1076 {
1077         REGF_FILE *regfile;
1078         WERROR result;
1079         SEC_DESC *sd = NULL;
1080         
1081         /* open the registry file....fail if the file already exists */
1082         
1083         if ( !(regfile = regfio_open( fname, (O_RDWR|O_CREAT|O_EXCL), (S_IREAD|S_IWRITE) )) ) {
1084                 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n", 
1085                         fname, strerror(errno) ));
1086                 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
1087         }
1088         
1089         if ( !W_ERROR_IS_OK(result = make_default_reg_sd( regfile->mem_ctx, &sd )) ) {
1090                 regfio_close( regfile );
1091                 return result;
1092         }
1093                 
1094         /* write the registry tree to the file  */
1095         
1096         result = reg_write_tree( regfile, krecord->name, NULL, sd );
1097                 
1098         /* cleanup */
1099         
1100         regfio_close( regfile );
1101         
1102         return result;
1103 }
1104 #endif
1105
1106 /*******************************************************************
1107  ********************************************************************/
1108
1109 WERROR _winreg_SaveKey(pipes_struct *p)
1110 {
1111 #if 0
1112         REGISTRY_KEY    *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
1113         pstring         filename;
1114         int             snum;
1115         
1116         if ( !regkey )
1117                 return WERR_BADFID; 
1118
1119         rpcstr_pull(filename, q_u->filename.string->buffer, sizeof(filename), q_u->filename.string->uni_str_len*2, STR_TERMINATE);
1120
1121         DEBUG(8,("_reg_save_key: verifying backup of key [%s] to \"%s\"\n", regkey->name, filename));
1122         
1123         if ( (snum = validate_reg_filename( filename )) == -1 )
1124                 return WERR_OBJECT_PATH_INVALID;
1125                 
1126         DEBUG(2,("_reg_save_key: Saving [%s] to %s in share %s\n", regkey->name, filename, lp_servicename(snum) ));
1127                 
1128         return backup_registry_key( regkey, filename );
1129 #endif
1130
1131         /* disabled for now until I fix the IDL  --jerry */
1132         return WERR_NOT_SUPPORTED;
1133 }
1134
1135 /*******************************************************************
1136  ********************************************************************/
1137
1138 WERROR _winreg_SaveKeyEx(pipes_struct *p)
1139 {
1140         /* disabled for now until I fix the IDL  --jerry */
1141         return WERR_NOT_SUPPORTED;
1142 }
1143
1144 /*******************************************************************
1145  ********************************************************************/
1146
1147 WERROR _winreg_CreateKey( pipes_struct *p, struct policy_handle *handle, struct winreg_String keyname, 
1148                           struct winreg_String keyclass, uint32_t options, uint32_t access_mask, 
1149                           struct winreg_SecBuf *secdesc, struct policy_handle *new_handle, 
1150                           enum winreg_CreateAction *action_taken )
1151 {
1152         REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, handle);
1153         REGISTRY_KEY *newparentinfo, *keyinfo;
1154         POLICY_HND newparent_handle;
1155         REGSUBKEY_CTR *subkeys;
1156         BOOL write_result;
1157         char *name;
1158         WERROR result;
1159
1160         if ( !parent )
1161                 return WERR_BADFID;
1162
1163         if ( (name = talloc_strdup( p->mem_ctx, keyname.name )) == NULL ) {
1164                 return WERR_NOMEM;
1165         }
1166         
1167         /* ok.  Here's what we do.  */
1168
1169         if ( strrchr( name, '\\' ) ) {
1170                 pstring newkeyname;
1171                 char *ptr;
1172                 
1173                 /* (1) check for enumerate rights on the parent handle.  CLients can try 
1174                        create things like 'SOFTWARE\Samba' on the HKLM handle. 
1175                    (2) open the path to the child parent key if necessary */
1176         
1177                 if ( !(parent->access_granted & SEC_RIGHTS_ENUM_SUBKEYS) )
1178                         return WERR_ACCESS_DENIED;
1179                 
1180                 pstrcpy( newkeyname, name );
1181                 ptr = strrchr( newkeyname, '\\' );
1182                 *ptr = '\0';
1183
1184                 result = open_registry_key( p, &newparent_handle, &newparentinfo, 
1185                         parent, newkeyname, (REG_KEY_READ|REG_KEY_WRITE) );
1186                         
1187                 if ( !W_ERROR_IS_OK(result) )
1188                         return result;
1189
1190                 /* copy the new key name (just the lower most keyname) */
1191
1192                 pstrcpy( name, ptr+1 );
1193         }
1194         else {
1195                 /* use the existing open key information */
1196                 newparentinfo = parent;
1197                 memcpy( &newparent_handle, handle, sizeof(POLICY_HND) );
1198         }
1199         
1200         /* (3) check for create subkey rights on the correct parent */
1201         
1202         if ( !(newparentinfo->access_granted & SEC_RIGHTS_CREATE_SUBKEY) ) {
1203                 result = WERR_ACCESS_DENIED;
1204                 goto done;
1205         }       
1206                 
1207         if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) {
1208                 result = WERR_NOMEM;
1209                 goto done;
1210         }
1211
1212         /* (4) lookup the current keys and add the new one */
1213         
1214         fetch_reg_keys( newparentinfo, subkeys );
1215         regsubkey_ctr_addkey( subkeys, name );
1216         
1217         /* now write to the registry backend */
1218         
1219         write_result = store_reg_keys( newparentinfo, subkeys );
1220         
1221         TALLOC_FREE( subkeys );
1222
1223         if ( !write_result )
1224                 return WERR_REG_IO_FAILURE;
1225                 
1226         /* (5) open the new key and return the handle.  Note that it is probably 
1227            not correct to grant full access on this open handle. */
1228         
1229         result = open_registry_key( p, new_handle, &keyinfo, newparentinfo, name, REG_KEY_READ );
1230         keyinfo->access_granted = REG_KEY_ALL;
1231         
1232         /* FIXME: report the truth here */
1233         
1234         if ( action_taken ) {
1235                 *action_taken = REG_CREATED_NEW_KEY;
1236         }
1237
1238 done:
1239         /* close any intermediate key handles */
1240         
1241         if ( newparentinfo != parent )
1242                 close_registry_key( p, &newparent_handle );
1243                 
1244         return result;
1245 }
1246
1247
1248 /*******************************************************************
1249  ********************************************************************/
1250
1251 WERROR _winreg_SetValue(pipes_struct *p, struct policy_handle *handle, struct winreg_String name, enum winreg_Type type, uint8_t *data, uint32_t size)
1252 {
1253         REGISTRY_KEY *key = find_regkey_index_by_hnd(p, handle);
1254         REGVAL_CTR *values;
1255         BOOL write_result;
1256         char *valuename;
1257
1258         if ( !key )
1259                 return WERR_BADFID;
1260                 
1261         /* access checks first */
1262         
1263         if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
1264                 return WERR_ACCESS_DENIED;
1265                 
1266         /* verify the name */
1267         
1268         if ( (valuename = talloc_strdup(p->mem_ctx, name.name)) == NULL ) {
1269                 return WERR_INVALID_PARAM;
1270         }
1271
1272         DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n", key->name, valuename));
1273                 
1274         if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
1275                 return WERR_NOMEM; 
1276         
1277         /* lookup the current values and add the new one */
1278         
1279         fetch_reg_values( key, values );
1280         
1281         regval_ctr_addvalue( values, valuename, type, (const char *)data, size );
1282         
1283         /* now write to the registry backend */
1284         
1285         write_result = store_reg_values( key, values );
1286         
1287         TALLOC_FREE( values );
1288         
1289         if ( !write_result )
1290                 return WERR_REG_IO_FAILURE;
1291                 
1292         return WERR_OK;
1293 }
1294
1295 /*******************************************************************
1296  ********************************************************************/
1297
1298 WERROR _winreg_DeleteKey(pipes_struct *p, struct policy_handle *handle, struct winreg_String key)
1299 {
1300         REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, handle);
1301         REGISTRY_KEY *newparentinfo = NULL;
1302         POLICY_HND newparent_handle;
1303         REGSUBKEY_CTR *subkeys;
1304         BOOL write_result;
1305         char *name;
1306         WERROR result;
1307
1308         if ( !parent )
1309                 return WERR_BADFID;
1310
1311         /* MSDN says parent the handle must have been opened with DELETE access */
1312
1313         /* (1) check for delete rights on the parent */
1314         
1315         if ( !(parent->access_granted & STD_RIGHT_DELETE_ACCESS) ) {
1316                 result = WERR_ACCESS_DENIED;
1317                 goto done;
1318         }
1319                 
1320         if ( (name = talloc_strdup( p->mem_ctx, key.name )) == NULL ) {
1321                 result = WERR_INVALID_PARAM;
1322                 goto done;
1323         }
1324                 
1325         /* ok.  Here's what we do.  */
1326
1327         if ( strrchr( name, '\\' ) ) {
1328                 pstring newkeyname;
1329                 char *ptr;
1330                 
1331                 /* (2) open the path to the child parent key if necessary */
1332                 /* split the registry path and save the subkeyname */
1333         
1334                 pstrcpy( newkeyname, name );
1335                 ptr = strrchr( newkeyname, '\\' );
1336                 *ptr = '\0';
1337                 pstrcpy( name, ptr+1 );
1338
1339                 result = open_registry_key( p, &newparent_handle, &newparentinfo, parent, newkeyname, (REG_KEY_READ|REG_KEY_WRITE) );
1340                 if ( !W_ERROR_IS_OK(result) )
1341                         return result;
1342         }
1343         else {
1344                 /* use the existing open key information */
1345                 newparentinfo = parent;
1346         }
1347         
1348         if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) {
1349                 result = WERR_NOMEM;
1350                 goto done;
1351         }
1352         
1353         /* lookup the current keys and delete the new one */
1354         
1355         fetch_reg_keys( newparentinfo, subkeys );
1356         
1357         regsubkey_ctr_delkey( subkeys, name );
1358         
1359         /* now write to the registry backend */
1360         
1361         write_result = store_reg_keys( newparentinfo, subkeys );
1362         
1363         TALLOC_FREE( subkeys );
1364
1365         result = write_result ? WERR_OK : WERR_REG_IO_FAILURE;
1366         
1367 done:
1368         /* close any intermediate key handles */
1369         
1370         if ( newparentinfo != parent )
1371                 close_registry_key( p, &newparent_handle );
1372
1373         return result;
1374 }
1375
1376
1377 /*******************************************************************
1378  ********************************************************************/
1379
1380 WERROR _winreg_DeleteValue(pipes_struct *p, struct policy_handle *handle, struct winreg_String value)
1381 {
1382         REGISTRY_KEY *key = find_regkey_index_by_hnd(p, handle);
1383         REGVAL_CTR *values;
1384         BOOL write_result;
1385         char *valuename;
1386         
1387         if ( !key )
1388                 return WERR_BADFID;
1389                 
1390         /* access checks first */
1391         
1392         if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
1393                 return WERR_ACCESS_DENIED;
1394
1395         if ( (valuename = talloc_strdup( p->mem_ctx, value.name )) == NULL ) {
1396                 return WERR_INVALID_PARAM;
1397         }
1398
1399         DEBUG(8,("_reg_delete_value: Setting value for [%s:%s]\n", key->name, valuename));
1400
1401         if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
1402                 return WERR_NOMEM;
1403         
1404         /* lookup the current values and add the new one */
1405         
1406         fetch_reg_values( key, values );
1407         
1408         regval_ctr_delvalue( values, valuename );
1409         
1410         /* now write to the registry backend */
1411         
1412         write_result = store_reg_values( key, values );
1413         
1414         TALLOC_FREE( values );
1415         
1416         if ( !write_result )
1417                 return WERR_REG_IO_FAILURE;
1418                 
1419         return WERR_OK;
1420 }
1421
1422 /*******************************************************************
1423  ********************************************************************/
1424
1425 WERROR _winreg_GetKeySecurity(pipes_struct *p, struct policy_handle *handle, uint32_t sec_info, struct KeySecurityData *sd)
1426 {
1427         REGISTRY_KEY *key = find_regkey_index_by_hnd(p, handle);
1428
1429         if ( !key )
1430                 return WERR_BADFID;
1431                 
1432         /* access checks first */
1433         
1434         if ( !(key->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
1435                 return WERR_ACCESS_DENIED;
1436                 
1437         return WERR_ACCESS_DENIED;
1438 }
1439
1440 /*******************************************************************
1441  ********************************************************************/
1442
1443 WERROR _winreg_SetKeySecurity(pipes_struct *p, struct policy_handle *handle, uint32_t access_mask, struct KeySecurityData *sd)
1444 {
1445         REGISTRY_KEY *key = find_regkey_index_by_hnd(p, handle);
1446
1447         if ( !key )
1448                 return WERR_BADFID;
1449                 
1450         /* access checks first */
1451         
1452         if ( !(key->access_granted & STD_RIGHT_WRITE_DAC_ACCESS) )
1453                 return WERR_ACCESS_DENIED;
1454                 
1455         return WERR_ACCESS_DENIED;
1456 }
1457
1458 /*******************************************************************
1459  ********************************************************************/
1460
1461 WERROR _winreg_FlushKey(pipes_struct *p, struct policy_handle *handle)
1462 {
1463         /* I'm just replying OK because there's not a lot 
1464            here I see to do i  --jerry */
1465         
1466         return WERR_OK;
1467 }
1468
1469 /*******************************************************************
1470  ********************************************************************/
1471
1472 WERROR _winreg_UnLoadKey(pipes_struct *p)
1473 {
1474         /* fill in your code here if you think this call should
1475            do anything */
1476
1477         return WERR_NOT_SUPPORTED;
1478 }
1479
1480 /*******************************************************************
1481  ********************************************************************/
1482
1483 WERROR _winreg_ReplaceKey(pipes_struct *p)
1484 {
1485         /* fill in your code here if you think this call should
1486            do anything */
1487
1488         return WERR_NOT_SUPPORTED;
1489 }
1490
1491 /*******************************************************************
1492  ********************************************************************/
1493
1494 WERROR _winreg_LoadKey(pipes_struct *p, struct policy_handle *handle, struct winreg_String *keyname, struct winreg_String *filename)
1495 {
1496         /* fill in your code here if you think this call should
1497            do anything */
1498
1499         return WERR_NOT_SUPPORTED;
1500 }
1501
1502 /*******************************************************************
1503  ********************************************************************/
1504
1505 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)
1506 {
1507         /* fill in your code here if you think this call should
1508            do anything */
1509
1510         return WERR_NOT_SUPPORTED;
1511 }
1512
1513 /*******************************************************************
1514  ********************************************************************/
1515
1516 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)
1517 {
1518         /* fill in your code here if you think this call should
1519            do anything */
1520
1521         return WERR_NOT_SUPPORTED;
1522 }
1523
1524 /*******************************************************************
1525  ********************************************************************/
1526
1527 WERROR _winreg_QueryMultipleValues2(pipes_struct *p)
1528 {
1529         /* fill in your code here if you think this call should
1530            do anything */
1531
1532         return WERR_NOT_SUPPORTED;
1533 }
1534