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