r18789: Replace the winreg server code with the libndr parsing code.
[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 *size, uint32_t *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         *size = *length = *type = 0;
366         value_name.name = NULL;
367                 
368         DEBUG(7,("_reg_info: policy key name = [%s]\n", regkey->name));
369         DEBUG(7,("_reg_info: policy key type = [%08x]\n", regkey->type));
370         
371         if ( (name = talloc_strdup( p->mem_ctx, value_name.name )) == NULL ) {
372                 return WERR_NOMEM;
373         }
374
375         DEBUG(5,("_reg_info: looking up value: [%s]\n", name));
376
377         if ( !(regvals = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) ) 
378                 return WERR_NOMEM;
379         
380         /* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */
381         if(regkey->type == REG_KEY_HKPD) 
382         {
383                 if(strequal(name, "Global"))
384                 {
385                         uint32 outbuf_len;
386                         prs_struct prs_hkpd;
387                         prs_init(&prs_hkpd, *size, p->mem_ctx, MARSHALL);
388                         status = reg_perfcount_get_hkpd(&prs_hkpd, *size, &outbuf_len, NULL);
389                         regval_ctr_addvalue(regvals, "HKPD", REG_BINARY,
390                                             prs_hkpd.data_p, outbuf_len);
391                         val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
392                         prs_mem_free(&prs_hkpd);
393                 }
394                 else if(strequal(name, "Counter 009"))
395                 {
396                         uint32 base_index;
397                         uint32 buffer_size;
398                         char *buffer;
399                         
400                         buffer = NULL;
401                         base_index = reg_perfcount_get_base_index();
402                         buffer_size = reg_perfcount_get_counter_names(base_index, &buffer);
403                         regval_ctr_addvalue(regvals, "Counter 009", 
404                                             REG_MULTI_SZ, buffer, buffer_size);
405                         
406                         val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
407                         
408                         if(buffer_size > 0)
409                         {
410                                 SAFE_FREE(buffer);
411                                 status = WERR_OK;
412                         }
413                 }
414                 else if(strequal(name, "Explain 009"))
415                 {               
416                         uint32 base_index;
417                         uint32 buffer_size;
418                         char *buffer;
419                         
420                         buffer = NULL;
421                         base_index = reg_perfcount_get_base_index();
422                         buffer_size = reg_perfcount_get_counter_help(base_index, &buffer);
423                         regval_ctr_addvalue(regvals, "Explain 009", 
424                                             REG_MULTI_SZ, buffer, buffer_size);
425                         
426                         val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
427                         
428                         if(buffer_size > 0)
429                         {
430                                 SAFE_FREE(buffer);
431                                 status = WERR_OK;
432                         }
433                 }
434                 else if(isdigit(name[0]))
435                 {
436                         /* we probably have a request for a specific object here */
437                         uint32 outbuf_len;
438                         prs_struct prs_hkpd;
439                         prs_init(&prs_hkpd, *size, p->mem_ctx, MARSHALL);
440                         status = reg_perfcount_get_hkpd(&prs_hkpd, *size, &outbuf_len, name);
441                         regval_ctr_addvalue(regvals, "HKPD", REG_BINARY,
442                                             prs_hkpd.data_p, outbuf_len);
443                         
444                         val = dup_registry_value(regval_ctr_specific_value(regvals, 0));
445                         prs_mem_free(&prs_hkpd);
446                 }
447                 else
448                 {
449                         DEBUG(3,("Unsupported key name [%s] for HKPD.\n", name));
450                         return WERR_BADFILE;
451                 }
452         }
453         /* HKPT calls can be handled out of reg_dynamic.c with the hkpt_params handler */
454         else
455         {
456             for ( i=0; fetch_reg_values_specific(regkey, &val, i); i++ ) 
457             {
458                 DEBUG(10,("_reg_info: Testing value [%s]\n", val->valuename));
459                 if ( strequal( val->valuename, name ) ) {
460                         DEBUG(10,("_reg_info: Found match for value [%s]\n", name));
461                         status = WERR_OK;
462                         break;
463                 }
464                 
465                 free_registry_value( val );
466             }
467         }
468
469         if ( val ) {
470                 *size   =  regval_size( val );
471                 *length =  regval_size( val );
472
473                 if ( (*data = talloc_memdup( p->mem_ctx, regval_data_p(val), *size )) == NULL ) {
474                         status = WERR_NOMEM;
475                 }
476
477                 *type = val->type;
478         }
479
480         TALLOC_FREE( regvals );
481         free_registry_value( val );
482
483         return status;
484 }
485
486 /*****************************************************************************
487  Implementation of REG_QUERY_KEY
488  ****************************************************************************/
489
490 WERROR _winreg_QueryInfoKey(pipes_struct *p, struct policy_handle *handle, 
491                             struct winreg_String class_in, 
492                             struct winreg_String *class_out, uint32_t *num_subkeys, 
493                             uint32_t *max_subkeylen, uint32_t *max_subkeysize, 
494                             uint32_t *num_values, uint32_t *max_valnamelen, 
495                             uint32_t *max_valbufsize, uint32_t *secdescsize, 
496                             NTTIME *last_changed_time)
497 {
498         WERROR  status = WERR_OK;
499         REGISTRY_KEY    *regkey = find_regkey_index_by_hnd( p, handle );
500         
501         if ( !regkey )
502                 return WERR_BADFID; 
503         
504         if ( !get_subkey_information( regkey, num_subkeys, max_subkeylen) ) {
505                 DEBUG(0,("_reg_query_key: get_subkey_information() failed!\n"));
506                 return WERR_ACCESS_DENIED;
507         }
508                 
509         if ( !get_value_information( regkey, num_values, max_valnamelen, max_valbufsize) ) {
510                 DEBUG(0,("_reg_query_key: get_value_information() failed!\n"));
511                 return WERR_ACCESS_DENIED;      
512         }
513
514         *secdescsize = 0x00000078;      /* size for key's sec_desc */
515         
516         /* Win9x set this to 0x0 since it does not keep timestamps.
517            Doing the same here for simplicity   --jerry */
518            
519         *last_changed_time = 0;
520
521         return status;
522 }
523
524
525 /*****************************************************************************
526  Implementation of REG_GETVERSION
527  ****************************************************************************/
528  
529 WERROR _winreg_GetVersion(pipes_struct *p, struct policy_handle *handle, uint32_t *version)
530 {
531         REGISTRY_KEY    *regkey = find_regkey_index_by_hnd( p, handle );
532         
533         if ( !regkey )
534                 return WERR_BADFID;
535         
536         *version = 0x00000005;  /* Windows 2000 registry API version */
537         
538         return WERR_OK;
539 }
540
541
542 /*****************************************************************************
543  Implementation of REG_ENUM_KEY
544  ****************************************************************************/
545  
546 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)
547 {
548         WERROR  status = WERR_OK;
549         REGISTRY_KEY    *regkey = find_regkey_index_by_hnd( p, handle );
550         char            *subkey = NULL;
551         
552         
553         if ( !regkey )
554                 return WERR_BADFID; 
555
556         if ( !name || !keyclass || !last_changed_time )
557                 return WERR_INVALID_PARAM;
558
559         DEBUG(8,("_reg_enum_key: enumerating key [%s]\n", regkey->name));
560         
561         if ( !fetch_reg_keys_specific( regkey, &subkey, enum_index ) ) {
562                 status = WERR_NO_MORE_ITEMS;
563                 goto done;
564         }
565         
566         DEBUG(10,("_reg_enum_key: retrieved subkey named [%s]\n", subkey));
567         
568         *last_changed_time = 0;
569         keyclass->name = NULL;
570         if ( (name->name = talloc_strdup( p->mem_ctx, subkey )) == NULL ) {
571                 status = WERR_NOMEM;
572         }
573
574 done:   
575         SAFE_FREE( subkey );
576         return status;
577 }
578
579 /*****************************************************************************
580  Implementation of REG_ENUM_VALUE
581  ****************************************************************************/
582
583 WERROR _winreg_EnumValue(pipes_struct *p, struct policy_handle *handle, uint32_t enum_index, struct winreg_StringBuf *name, enum winreg_Type *type, uint8_t *value, uint32_t *size, uint32_t *length)
584 {
585         WERROR  status = WERR_OK;
586         REGISTRY_KEY    *regkey = find_regkey_index_by_hnd( p, handle );
587         REGISTRY_VALUE  *val;
588         
589         if ( !regkey )
590                 return WERR_BADFID; 
591
592         if ( !name || !type || !value || !size || !length )
593                 return WERR_INVALID_PARAM;
594
595         DEBUG(8,("_reg_enum_value: enumerating values for key [%s]\n", regkey->name));
596
597         if ( !fetch_reg_values_specific( regkey, &val, enum_index ) ) {
598                 status = WERR_NO_MORE_ITEMS;
599                 goto done;
600         }
601
602         DEBUG(10,("_reg_enum_value: retrieved value named  [%s]\n", val->valuename));
603         
604         /* subkey has the string name now */
605         
606         if ( (name->name = talloc_strdup( p->mem_ctx, val->valuename )) == NULL ) {
607                 status = WERR_NOMEM;
608         }
609
610         *size   =  regval_size( val );
611         *length =  regval_size( val );
612
613         if ( (value = talloc_memdup( p->mem_ctx, regval_data_p(val), *size )) == NULL ) {
614                 status = WERR_NOMEM;
615         }
616
617         *type = val->type;
618
619 done:   
620         free_registry_value( val );
621         
622         return status;
623 }
624
625
626 /*******************************************************************
627  reg_shutdwon
628  ********************************************************************/
629
630 WERROR _winreg_InitiateSystemShutdown(pipes_struct *p, uint16_t *hostname, struct initshutdown_String *message, uint32_t timeout, uint8_t force_apps, uint8_t reboot)
631 {
632         uint32_t reason = 0;
633
634         /* thunk down to _winreg_InitiateSystemShutdownEx() 
635            (just returns a status) */
636         
637         return _winreg_InitiateSystemShutdownEx( p, hostname, message, timeout, 
638                 force_apps, reboot, reason );
639 }
640
641 /*******************************************************************
642  reg_shutdown_ex
643  ********************************************************************/
644
645 #define SHUTDOWN_R_STRING "-r"
646 #define SHUTDOWN_F_STRING "-f"
647
648
649 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)
650 {
651         pstring shutdown_script;
652         char *msg = NULL;
653         pstring chkmsg;
654         fstring str_timeout;
655         fstring str_reason;
656         fstring r;
657         fstring f;
658         int ret;
659         BOOL can_shutdown;
660         
661
662         pstrcpy(shutdown_script, lp_shutdown_script());
663         
664         if ( !*shutdown_script )
665                 return WERR_ACCESS_DENIED;
666
667         /* pull the message string and perform necessary sanity checks on it */
668
669         if ( message && message->name && message->name->name ) {
670                 if ( (msg = talloc_strdup(p->mem_ctx, message->name->name )) == NULL ) {
671                         return WERR_NOMEM;
672                 }
673         } 
674         alpha_strcpy (chkmsg, msg?msg:"", NULL, strlen(msg));
675                 
676         fstr_sprintf(str_timeout, "%d", timeout);
677         fstr_sprintf(r, reboot ? SHUTDOWN_R_STRING : "");
678         fstr_sprintf(f, force_apps ? SHUTDOWN_F_STRING : "");
679         fstr_sprintf(str_reason, "%d", reason );
680
681         all_string_sub( shutdown_script, "%z", chkmsg, sizeof(shutdown_script) );
682         all_string_sub( shutdown_script, "%t", str_timeout, sizeof(shutdown_script) );
683         all_string_sub( shutdown_script, "%r", r, sizeof(shutdown_script) );
684         all_string_sub( shutdown_script, "%f", f, sizeof(shutdown_script) );
685         all_string_sub( shutdown_script, "%x", str_reason, sizeof(shutdown_script) );
686
687         can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
688                 
689         /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
690            Take the error return from the script and provide it as the Windows return code. */
691            
692         /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
693         
694         if ( can_shutdown ) 
695                 become_root();
696
697         ret = smbrun( shutdown_script, NULL );
698                 
699         if ( can_shutdown )
700                 unbecome_root();
701
702         /********** END SeRemoteShutdownPrivilege BLOCK **********/
703         
704         DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
705                 shutdown_script, ret));
706                 
707
708         return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
709 }
710
711
712
713
714 /*******************************************************************
715  reg_abort_shutdwon
716  ********************************************************************/
717
718 WERROR _winreg_AbortSystemShutdown(pipes_struct *p, uint16_t *server)
719 {
720         pstring abort_shutdown_script;
721         int ret;
722         BOOL can_shutdown;
723
724         pstrcpy(abort_shutdown_script, lp_abort_shutdown_script());
725
726         if ( !*abort_shutdown_script )
727                 return WERR_ACCESS_DENIED;
728                 
729         can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
730                 
731         /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
732         
733         if ( can_shutdown )
734                 become_root();
735                 
736         ret = smbrun( abort_shutdown_script, NULL );
737         
738         if ( can_shutdown )
739                 unbecome_root();
740                 
741         /********** END SeRemoteShutdownPrivilege BLOCK **********/
742
743         DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",
744                 abort_shutdown_script, ret));
745                 
746
747         return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
748 }
749
750 #if 0   /* This code works but is disabled for now until I 
751            fix the WinReg IDL file -- jerry */
752
753 /*******************************************************************
754  ********************************************************************/
755
756 static int validate_reg_filename( pstring fname )
757 {
758         char *p;
759         int num_services = lp_numservices();
760         int snum;
761         pstring share_path;
762         pstring unix_fname;
763         
764         /* convert to a unix path, stripping the C:\ along the way */
765         
766         if ( !(p = valid_share_pathname( fname ) ))
767                 return -1;
768
769         /* has to exist within a valid file share */
770                         
771         for ( snum=0; snum<num_services; snum++ ) {
772         
773                 if ( !lp_snum_ok(snum) || lp_print_ok(snum) )
774                         continue;
775                 
776                 pstrcpy( share_path, lp_pathname(snum) );
777
778                 /* make sure we have a path (e.g. [homes] ) */
779
780                 if ( strlen( share_path ) == 0 )
781                         continue;
782
783                 if ( strncmp( share_path, p, strlen( share_path )) == 0 )
784                         break;
785         }
786         
787         /* p and fname are overlapping memory so copy out and back in again */
788         
789         pstrcpy( unix_fname, p );
790         pstrcpy( fname, unix_fname );
791         
792         return (snum < num_services) ? snum : -1;
793 }
794
795 /*******************************************************************
796  Note: topkeypat is the *full* path that this *key will be 
797  loaded into (including the name of the key)
798  ********************************************************************/
799
800 static WERROR reg_load_tree( REGF_FILE *regfile, const char *topkeypath,
801                              REGF_NK_REC *key )
802 {
803         REGF_NK_REC *subkey;
804         REGISTRY_KEY registry_key;
805         REGVAL_CTR *values;
806         REGSUBKEY_CTR *subkeys;
807         int i;
808         pstring path;
809         WERROR result = WERR_OK;
810         
811         /* initialize the REGISTRY_KEY structure */
812         
813         if ( !(registry_key.hook = reghook_cache_find(topkeypath)) ) {
814                 DEBUG(0,("reg_load_tree: Failed to assigned a REGISTRY_HOOK to [%s]\n",
815                         topkeypath ));
816                 return WERR_BADFILE;
817         }
818         pstrcpy( registry_key.name, topkeypath );
819         
820         /* now start parsing the values and subkeys */
821
822         if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
823                 return WERR_NOMEM;
824         
825         if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
826                 return WERR_NOMEM;
827
828         /* copy values into the REGVAL_CTR */
829         
830         for ( i=0; i<key->num_values; i++ ) {
831                 regval_ctr_addvalue( values, key->values[i].valuename, key->values[i].type,
832                         (char*)key->values[i].data, (key->values[i].data_size & ~VK_DATA_IN_OFFSET) );
833         }
834
835         /* copy subkeys into the REGSUBKEY_CTR */
836         
837         key->subkey_index = 0;
838         while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
839                 regsubkey_ctr_addkey( subkeys, subkey->keyname );
840         }
841         
842         /* write this key and values out */
843         
844         if ( !store_reg_values( &registry_key, values ) 
845                 || !store_reg_keys( &registry_key, subkeys ) )
846         {
847                 DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath));
848                 result = WERR_REG_IO_FAILURE;
849         }
850         
851         TALLOC_FREE( subkeys );
852         
853         if ( !W_ERROR_IS_OK(result) )
854                 return result;
855         
856         /* now continue to load each subkey registry tree */
857
858         key->subkey_index = 0;
859         while ( (subkey = regfio_fetch_subkey( regfile, key )) ) {
860                 pstr_sprintf( path, "%s%s%s", topkeypath, "\\", subkey->keyname );
861                 result = reg_load_tree( regfile, path, subkey );
862                 if ( !W_ERROR_IS_OK(result) )
863                         break;
864         }
865
866         return result;
867 }
868
869 /*******************************************************************
870  ********************************************************************/
871
872 static WERROR restore_registry_key ( REGISTRY_KEY *krecord, const char *fname )
873 {
874         REGF_FILE *regfile;
875         REGF_NK_REC *rootkey;
876         WERROR result;
877                 
878         /* open the registry file....fail if the file already exists */
879         
880         if ( !(regfile = regfio_open( fname, (O_RDONLY), 0 )) ) {
881                 DEBUG(0,("restore_registry_key: failed to open \"%s\" (%s)\n", 
882                         fname, strerror(errno) ));
883                 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
884         }
885         
886         /* get the rootkey from the regf file and then load the tree
887            via recursive calls */
888            
889         if ( !(rootkey = regfio_rootkey( regfile )) ) {
890                 regfio_close( regfile );
891                 return WERR_REG_FILE_INVALID;
892         }
893         
894         result = reg_load_tree( regfile, krecord->name, rootkey );
895                 
896         /* cleanup */
897         
898         regfio_close( regfile );
899         
900         return result;
901 }
902
903 #endif
904
905 /*******************************************************************
906  ********************************************************************/
907
908 WERROR _winreg_RestoreKey(pipes_struct *p)
909 {
910 #if 0   /* temporarily disabled */
911         REGISTRY_KEY    *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
912         pstring         filename;
913         int             snum;
914         
915         if ( !regkey )
916                 return WERR_BADFID; 
917
918         rpcstr_pull(filename, q_u->filename.string->buffer, sizeof(filename), q_u->filename.string->uni_str_len*2, STR_TERMINATE);
919
920         DEBUG(8,("_reg_restore_key: verifying restore of key [%s] from \"%s\"\n", regkey->name, filename));
921
922         if ( (snum = validate_reg_filename( filename )) == -1 )
923                 return WERR_OBJECT_PATH_INVALID;
924                 
925         /* user must posses SeRestorePrivilege for this this proceed */
926         
927         if ( !user_has_privileges( p->pipe_user.nt_user_token, &se_restore ) )
928                 return WERR_ACCESS_DENIED;
929                 
930         DEBUG(2,("_reg_restore_key: Restoring [%s] from %s in share %s\n", regkey->name, filename, lp_servicename(snum) ));
931
932         return restore_registry_key( regkey, filename );
933 #endif
934
935         return WERR_NOT_SUPPORTED;
936 }
937
938 #if 0   /* this code works but has been disable until I fix
939            the winreg IDL    -- jerry */
940
941 /********************************************************************
942 ********************************************************************/
943
944 static WERROR reg_write_tree( REGF_FILE *regfile, const char *keypath,
945                               REGF_NK_REC *parent, SEC_DESC *sec_desc )
946 {
947         REGF_NK_REC *key;
948         REGVAL_CTR *values;
949         REGSUBKEY_CTR *subkeys;
950         int i, num_subkeys;
951         pstring key_tmp;
952         char *keyname, *parentpath;
953         pstring subkeypath;
954         char *subkeyname;
955         REGISTRY_KEY registry_key;
956         WERROR result = WERR_OK;
957         
958         if ( !regfile )
959                 return WERR_GENERAL_FAILURE;
960                 
961         if ( !keypath )
962                 return WERR_OBJECT_PATH_INVALID;
963                 
964         /* split up the registry key path */
965         
966         pstrcpy( key_tmp, keypath );
967         if ( !reg_split_key( key_tmp, &parentpath, &keyname ) )
968                 return WERR_OBJECT_PATH_INVALID;
969
970         if ( !keyname )
971                 keyname = parentpath;
972
973         /* we need a REGISTRY_KEY object here to enumerate subkeys and values */
974         
975         ZERO_STRUCT( registry_key );
976         pstrcpy( registry_key.name, keypath );
977         if ( !(registry_key.hook = reghook_cache_find( registry_key.name )) )
978                 return WERR_BADFILE;
979
980         
981         /* lookup the values and subkeys */
982         
983         if ( !(subkeys = TALLOC_ZERO_P( regfile->mem_ctx, REGSUBKEY_CTR )) )
984                 return WERR_NOMEM;
985
986         if ( !(values = TALLOC_ZERO_P( subkeys, REGVAL_CTR )) )
987                 return WERR_NOMEM;
988
989         fetch_reg_keys( &registry_key, subkeys );
990         fetch_reg_values( &registry_key, values );
991
992         /* write out this key */
993                 
994         if ( !(key = regfio_write_key( regfile, keyname, values, subkeys, sec_desc, parent )) ) {
995                 result = WERR_CAN_NOT_COMPLETE;
996                 goto done;
997         }
998
999         /* write each one of the subkeys out */
1000
1001         num_subkeys = regsubkey_ctr_numkeys( subkeys );
1002         for ( i=0; i<num_subkeys; i++ ) {
1003                 subkeyname = regsubkey_ctr_specific_key( subkeys, i );
1004                 pstr_sprintf( subkeypath, "%s\\%s", keypath, subkeyname );
1005                 result = reg_write_tree( regfile, subkeypath, key, sec_desc );
1006                 if ( !W_ERROR_IS_OK(result) )
1007                         goto done;
1008         }
1009
1010         DEBUG(6,("reg_write_tree: wrote key [%s]\n", keypath ));
1011
1012 done:
1013         TALLOC_FREE( subkeys );
1014
1015         return result;
1016 }
1017
1018 /*******************************************************************
1019  ********************************************************************/
1020
1021 static WERROR make_default_reg_sd( TALLOC_CTX *ctx, SEC_DESC **psd )
1022 {
1023         DOM_SID adm_sid, owner_sid;
1024         SEC_ACE ace[2];         /* at most 2 entries */
1025         SEC_ACCESS mask;
1026         SEC_ACL *psa = NULL;
1027         size_t sd_size;
1028
1029         /* set the owner to BUILTIN\Administrator */
1030
1031         sid_copy(&owner_sid, &global_sid_Builtin);
1032         sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN );
1033         
1034
1035         /* basic access for Everyone */
1036
1037         init_sec_access(&mask, reg_generic_map.generic_execute | reg_generic_map.generic_read );
1038         init_sec_ace(&ace[0], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
1039
1040         /* add Full Access 'BUILTIN\Administrators' */
1041
1042         init_sec_access(&mask, reg_generic_map.generic_all);
1043         sid_copy(&adm_sid, &global_sid_Builtin);
1044         sid_append_rid(&adm_sid, BUILTIN_ALIAS_RID_ADMINS);
1045         init_sec_ace(&ace[1], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
1046
1047         /* create the security descriptor */
1048
1049         if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 2, ace)) == NULL)
1050                 return WERR_NOMEM;
1051
1052         if ((*psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, &owner_sid, NULL, NULL, psa, &sd_size)) == NULL)
1053                 return WERR_NOMEM;
1054
1055         return WERR_OK;
1056 }
1057
1058 /*******************************************************************
1059  ********************************************************************/
1060
1061 static WERROR backup_registry_key ( REGISTRY_KEY *krecord, const char *fname )
1062 {
1063         REGF_FILE *regfile;
1064         WERROR result;
1065         SEC_DESC *sd = NULL;
1066         
1067         /* open the registry file....fail if the file already exists */
1068         
1069         if ( !(regfile = regfio_open( fname, (O_RDWR|O_CREAT|O_EXCL), (S_IREAD|S_IWRITE) )) ) {
1070                 DEBUG(0,("backup_registry_key: failed to open \"%s\" (%s)\n", 
1071                         fname, strerror(errno) ));
1072                 return ( ntstatus_to_werror(map_nt_error_from_unix( errno )) );
1073         }
1074         
1075         if ( !W_ERROR_IS_OK(result = make_default_reg_sd( regfile->mem_ctx, &sd )) ) {
1076                 regfio_close( regfile );
1077                 return result;
1078         }
1079                 
1080         /* write the registry tree to the file  */
1081         
1082         result = reg_write_tree( regfile, krecord->name, NULL, sd );
1083                 
1084         /* cleanup */
1085         
1086         regfio_close( regfile );
1087         
1088         return result;
1089 }
1090 #endif
1091
1092 /*******************************************************************
1093  ********************************************************************/
1094
1095 WERROR _winreg_SaveKey(pipes_struct *p)
1096 {
1097 #if 0
1098         REGISTRY_KEY    *regkey = find_regkey_index_by_hnd( p, &q_u->pol );
1099         pstring         filename;
1100         int             snum;
1101         
1102         if ( !regkey )
1103                 return WERR_BADFID; 
1104
1105         rpcstr_pull(filename, q_u->filename.string->buffer, sizeof(filename), q_u->filename.string->uni_str_len*2, STR_TERMINATE);
1106
1107         DEBUG(8,("_reg_save_key: verifying backup of key [%s] to \"%s\"\n", regkey->name, filename));
1108         
1109         if ( (snum = validate_reg_filename( filename )) == -1 )
1110                 return WERR_OBJECT_PATH_INVALID;
1111                 
1112         DEBUG(2,("_reg_save_key: Saving [%s] to %s in share %s\n", regkey->name, filename, lp_servicename(snum) ));
1113                 
1114         return backup_registry_key( regkey, filename );
1115 #endif
1116
1117         /* disabled for now until I fix the IDL  --jerry */
1118         return WERR_NOT_SUPPORTED;
1119 }
1120
1121 /*******************************************************************
1122  ********************************************************************/
1123
1124 WERROR _winreg_SaveKeyEx(pipes_struct *p)
1125 {
1126         /* disabled for now until I fix the IDL  --jerry */
1127         return WERR_NOT_SUPPORTED;
1128 }
1129
1130 /*******************************************************************
1131  ********************************************************************/
1132
1133 WERROR _winreg_CreateKey( pipes_struct *p, struct policy_handle *handle, struct winreg_String keyname, 
1134                           struct winreg_String keyclass, uint32_t options, uint32_t access_mask, 
1135                           struct winreg_SecBuf *secdesc, struct policy_handle *new_handle, 
1136                           enum winreg_CreateAction *action_taken )
1137 {
1138         REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, handle);
1139         REGISTRY_KEY *newparentinfo, *keyinfo;
1140         POLICY_HND newparent_handle;
1141         REGSUBKEY_CTR *subkeys;
1142         BOOL write_result;
1143         char *name;
1144         WERROR result;
1145
1146         if ( !parent )
1147                 return WERR_BADFID;
1148
1149         if ( (name = talloc_strdup( p->mem_ctx, keyname.name )) == NULL ) {
1150                 return WERR_NOMEM;
1151         }
1152         
1153         /* ok.  Here's what we do.  */
1154
1155         if ( strrchr( name, '\\' ) ) {
1156                 pstring newkeyname;
1157                 char *ptr;
1158                 
1159                 /* (1) check for enumerate rights on the parent handle.  CLients can try 
1160                        create things like 'SOFTWARE\Samba' on the HKLM handle. 
1161                    (2) open the path to the child parent key if necessary */
1162         
1163                 if ( !(parent->access_granted & SEC_RIGHTS_ENUM_SUBKEYS) )
1164                         return WERR_ACCESS_DENIED;
1165                 
1166                 pstrcpy( newkeyname, name );
1167                 ptr = strrchr( newkeyname, '\\' );
1168                 *ptr = '\0';
1169
1170                 result = open_registry_key( p, &newparent_handle, &newparentinfo, 
1171                         parent, newkeyname, (REG_KEY_READ|REG_KEY_WRITE) );
1172                         
1173                 if ( !W_ERROR_IS_OK(result) )
1174                         return result;
1175
1176                 /* copy the new key name (just the lower most keyname) */
1177
1178                 pstrcpy( name, ptr+1 );
1179         }
1180         else {
1181                 /* use the existing open key information */
1182                 newparentinfo = parent;
1183                 memcpy( &newparent_handle, handle, sizeof(POLICY_HND) );
1184         }
1185         
1186         /* (3) check for create subkey rights on the correct parent */
1187         
1188         if ( !(newparentinfo->access_granted & SEC_RIGHTS_CREATE_SUBKEY) ) {
1189                 result = WERR_ACCESS_DENIED;
1190                 goto done;
1191         }       
1192                 
1193         if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) {
1194                 result = WERR_NOMEM;
1195                 goto done;
1196         }
1197
1198         /* (4) lookup the current keys and add the new one */
1199         
1200         fetch_reg_keys( newparentinfo, subkeys );
1201         regsubkey_ctr_addkey( subkeys, name );
1202         
1203         /* now write to the registry backend */
1204         
1205         write_result = store_reg_keys( newparentinfo, subkeys );
1206         
1207         TALLOC_FREE( subkeys );
1208
1209         if ( !write_result )
1210                 return WERR_REG_IO_FAILURE;
1211                 
1212         /* (5) open the new key and return the handle.  Note that it is probably 
1213            not correct to grant full access on this open handle. */
1214         
1215         result = open_registry_key( p, new_handle, &keyinfo, newparentinfo, name, REG_KEY_READ );
1216         keyinfo->access_granted = REG_KEY_ALL;
1217         
1218         /* FIXME: report the truth here */
1219         
1220         *action_taken = REG_CREATED_NEW_KEY;
1221
1222 done:
1223         /* close any intermediate key handles */
1224         
1225         if ( newparentinfo != parent )
1226                 close_registry_key( p, &newparent_handle );
1227                 
1228         return result;
1229 }
1230
1231
1232 /*******************************************************************
1233  ********************************************************************/
1234
1235 WERROR _winreg_SetValue(pipes_struct *p, struct policy_handle *handle, struct winreg_String name, enum winreg_Type type, uint8_t *data, uint32_t size)
1236 {
1237         REGISTRY_KEY *key = find_regkey_index_by_hnd(p, handle);
1238         REGVAL_CTR *values;
1239         BOOL write_result;
1240         char *valuename;
1241
1242         if ( !key )
1243                 return WERR_BADFID;
1244                 
1245         /* access checks first */
1246         
1247         if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
1248                 return WERR_ACCESS_DENIED;
1249                 
1250         /* verify the name */
1251         
1252         if ( (valuename = talloc_strdup(p->mem_ctx, name.name)) == NULL ) {
1253                 return WERR_INVALID_PARAM;
1254         }
1255
1256         DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n", key->name, valuename));
1257                 
1258         if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
1259                 return WERR_NOMEM; 
1260         
1261         /* lookup the current values and add the new one */
1262         
1263         fetch_reg_values( key, values );
1264         
1265         regval_ctr_addvalue( values, valuename, type, (const char *)data, size );
1266         
1267         /* now write to the registry backend */
1268         
1269         write_result = store_reg_values( key, values );
1270         
1271         TALLOC_FREE( values );
1272         
1273         if ( !write_result )
1274                 return WERR_REG_IO_FAILURE;
1275                 
1276         return WERR_OK;
1277 }
1278
1279 /*******************************************************************
1280  ********************************************************************/
1281
1282 WERROR _winreg_DeleteKey(pipes_struct *p, struct policy_handle *handle, struct winreg_String key)
1283 {
1284         REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, handle);
1285         REGISTRY_KEY *newparentinfo = NULL;
1286         POLICY_HND newparent_handle;
1287         REGSUBKEY_CTR *subkeys;
1288         BOOL write_result;
1289         char *name;
1290         WERROR result;
1291
1292         if ( !parent )
1293                 return WERR_BADFID;
1294
1295         /* MSDN says parent the handle must have been opened with DELETE access */
1296
1297         /* (1) check for delete rights on the parent */
1298         
1299         if ( !(parent->access_granted & STD_RIGHT_DELETE_ACCESS) ) {
1300                 result = WERR_ACCESS_DENIED;
1301                 goto done;
1302         }
1303                 
1304         if ( (name = talloc_strdup( p->mem_ctx, key.name )) == NULL ) {
1305                 result = WERR_INVALID_PARAM;
1306                 goto done;
1307         }
1308                 
1309         /* ok.  Here's what we do.  */
1310
1311         if ( strrchr( name, '\\' ) ) {
1312                 pstring newkeyname;
1313                 char *ptr;
1314                 
1315                 /* (2) open the path to the child parent key if necessary */
1316                 /* split the registry path and save the subkeyname */
1317         
1318                 pstrcpy( newkeyname, name );
1319                 ptr = strrchr( newkeyname, '\\' );
1320                 *ptr = '\0';
1321                 pstrcpy( name, ptr+1 );
1322
1323                 result = open_registry_key( p, &newparent_handle, &newparentinfo, parent, newkeyname, (REG_KEY_READ|REG_KEY_WRITE) );
1324                 if ( !W_ERROR_IS_OK(result) )
1325                         return result;
1326         }
1327         else {
1328                 /* use the existing open key information */
1329                 newparentinfo = parent;
1330         }
1331         
1332         if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) {
1333                 result = WERR_NOMEM;
1334                 goto done;
1335         }
1336         
1337         /* lookup the current keys and delete the new one */
1338         
1339         fetch_reg_keys( newparentinfo, subkeys );
1340         
1341         regsubkey_ctr_delkey( subkeys, name );
1342         
1343         /* now write to the registry backend */
1344         
1345         write_result = store_reg_keys( newparentinfo, subkeys );
1346         
1347         TALLOC_FREE( subkeys );
1348
1349         result = write_result ? WERR_OK : WERR_REG_IO_FAILURE;
1350         
1351 done:
1352         /* close any intermediate key handles */
1353         
1354         if ( newparentinfo != parent )
1355                 close_registry_key( p, &newparent_handle );
1356
1357         return result;
1358 }
1359
1360
1361 /*******************************************************************
1362  ********************************************************************/
1363
1364 WERROR _winreg_DeleteValue(pipes_struct *p, struct policy_handle *handle, struct winreg_String value)
1365 {
1366         REGISTRY_KEY *key = find_regkey_index_by_hnd(p, handle);
1367         REGVAL_CTR *values;
1368         BOOL write_result;
1369         char *valuename;
1370         
1371         if ( !key )
1372                 return WERR_BADFID;
1373                 
1374         /* access checks first */
1375         
1376         if ( !(key->access_granted & SEC_RIGHTS_SET_VALUE) )
1377                 return WERR_ACCESS_DENIED;
1378
1379         if ( (valuename = talloc_strdup( p->mem_ctx, value.name )) == NULL ) {
1380                 return WERR_INVALID_PARAM;
1381         }
1382
1383         DEBUG(8,("_reg_delete_value: Setting value for [%s:%s]\n", key->name, valuename));
1384
1385         if ( !(values = TALLOC_ZERO_P( p->mem_ctx, REGVAL_CTR )) )
1386                 return WERR_NOMEM;
1387         
1388         /* lookup the current values and add the new one */
1389         
1390         fetch_reg_values( key, values );
1391         
1392         regval_ctr_delvalue( values, valuename );
1393         
1394         /* now write to the registry backend */
1395         
1396         write_result = store_reg_values( key, values );
1397         
1398         TALLOC_FREE( values );
1399         
1400         if ( !write_result )
1401                 return WERR_REG_IO_FAILURE;
1402                 
1403         return WERR_OK;
1404 }
1405
1406 /*******************************************************************
1407  ********************************************************************/
1408
1409 WERROR _winreg_GetKeySecurity(pipes_struct *p, struct policy_handle *handle, uint32_t sec_info, struct KeySecurityData *sd)
1410 {
1411         REGISTRY_KEY *key = find_regkey_index_by_hnd(p, handle);
1412
1413         if ( !key )
1414                 return WERR_BADFID;
1415                 
1416         /* access checks first */
1417         
1418         if ( !(key->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
1419                 return WERR_ACCESS_DENIED;
1420                 
1421         return WERR_ACCESS_DENIED;
1422 }
1423
1424 /*******************************************************************
1425  ********************************************************************/
1426
1427 WERROR _winreg_SetKeySecurity(pipes_struct *p, struct policy_handle *handle, uint32_t access_mask, struct KeySecurityData *sd)
1428 {
1429         REGISTRY_KEY *key = find_regkey_index_by_hnd(p, handle);
1430
1431         if ( !key )
1432                 return WERR_BADFID;
1433                 
1434         /* access checks first */
1435         
1436         if ( !(key->access_granted & STD_RIGHT_WRITE_DAC_ACCESS) )
1437                 return WERR_ACCESS_DENIED;
1438                 
1439         return WERR_ACCESS_DENIED;
1440 }
1441
1442 /*******************************************************************
1443  ********************************************************************/
1444
1445 WERROR _winreg_FlushKey(pipes_struct *p, struct policy_handle *handle)
1446 {
1447         /* I'm just replying OK because there's not a lot 
1448            here I see to do i  --jerry */
1449         
1450         return WERR_OK;
1451 }
1452
1453 /*******************************************************************
1454  ********************************************************************/
1455
1456 WERROR _winreg_UnLoadKey(pipes_struct *p)
1457 {
1458         /* fill in your code here if you think this call should
1459            do anything */
1460
1461         return WERR_NOT_SUPPORTED;
1462 }
1463
1464 /*******************************************************************
1465  ********************************************************************/
1466
1467 WERROR _winreg_ReplaceKey(pipes_struct *p)
1468 {
1469         /* fill in your code here if you think this call should
1470            do anything */
1471
1472         return WERR_NOT_SUPPORTED;
1473 }
1474
1475 /*******************************************************************
1476  ********************************************************************/
1477
1478 WERROR _winreg_LoadKey(pipes_struct *p, struct policy_handle *handle, struct winreg_String *keyname, struct winreg_String *filename)
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_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)
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_QueryMultipleValues(pipes_struct *p, struct policy_handle *key_handle, struct QueryMultipleValue *values, uint32_t num_values, uint8_t *buffer, uint32_t *buffer_size)
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_QueryMultipleValues2(pipes_struct *p)
1512 {
1513         /* fill in your code here if you think this call should
1514            do anything */
1515
1516         return WERR_NOT_SUPPORTED;
1517 }
1518