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