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