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