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