s3-schannel: add dump_NL_AUTH_SIGNATURE.
[samba.git] / source3 / rpc_server / srv_winreg_nt.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  * 
5  *  Copyright (C) Gerald Carter                 2002-2006.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 3 of the License, or
10  *  (at your option) any later version.
11  *  
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *  
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 /* Implementation of registry functions. */
22
23 #include "includes.h"
24
25 #undef DBGC_CLASS
26 #define DBGC_CLASS DBGC_RPC_SRV
27
28 /******************************************************************
29  Find a registry key handle and return a struct registry_key *
30  *****************************************************************/
31
32 static struct registry_key *find_regkey_by_hnd(pipes_struct *p,
33                                                struct policy_handle *hnd)
34 {
35         struct registry_key *regkey = NULL;
36
37         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&regkey)) {
38                 DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: "));
39                 return NULL;
40         }
41
42         return regkey;
43 }
44
45 /*******************************************************************
46  Function for open a new registry handle and creating a handle 
47  Note that P should be valid & hnd should already have space
48  
49  When we open a key, we store the full path to the key as 
50  HK[LM|U]\<key>\<key>\...
51  *******************************************************************/
52  
53 static WERROR open_registry_key( pipes_struct *p, struct policy_handle *hnd,
54                                  struct registry_key *parent,
55                                  const char *subkeyname,
56                                  uint32 access_desired  )
57 {
58         WERROR result = WERR_OK;
59         struct registry_key *key;
60
61         if (parent == NULL) {
62                 result = reg_openhive(p->mem_ctx, subkeyname, access_desired,
63                                       p->server_info->ptok, &key);
64         }
65         else {
66                 result = reg_openkey(p->mem_ctx, parent, subkeyname,
67                                      access_desired, &key);
68         }
69
70         if ( !W_ERROR_IS_OK(result) ) {
71                 return result;
72         }
73         
74         if ( !create_policy_hnd( p, hnd, key ) ) {
75                 return WERR_BADFILE; 
76         }
77         
78         return WERR_OK;
79 }
80
81 /*******************************************************************
82  Function for open a new registry handle and creating a handle 
83  Note that P should be valid & hnd should already have space
84  *******************************************************************/
85
86 static bool close_registry_key(pipes_struct *p, struct policy_handle *hnd)
87 {
88         struct registry_key *regkey = find_regkey_by_hnd(p, hnd);
89         
90         if ( !regkey ) {
91                 DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n",
92                          OUR_HANDLE(hnd)));
93                 return False;
94         }
95         
96         close_policy_hnd(p, hnd);
97         
98         return True;
99 }
100
101 /********************************************************************
102  reg_close
103  ********************************************************************/
104
105 WERROR _winreg_CloseKey(pipes_struct *p, struct winreg_CloseKey *r)
106 {
107         /* close the policy handle */
108
109         if (!close_registry_key(p, r->in.handle))
110                 return WERR_BADFID; 
111
112         ZERO_STRUCTP(r->out.handle);
113
114         return WERR_OK;
115 }
116
117 /*******************************************************************
118  ********************************************************************/
119
120 WERROR _winreg_OpenHKLM(pipes_struct *p, struct winreg_OpenHKLM *r)
121 {
122         return open_registry_key(p, r->out.handle, NULL, KEY_HKLM, r->in.access_mask);
123 }
124
125 /*******************************************************************
126  ********************************************************************/
127
128 WERROR _winreg_OpenHKPD(pipes_struct *p, struct winreg_OpenHKPD *r)
129 {
130         return open_registry_key(p, r->out.handle, NULL, KEY_HKPD, r->in.access_mask);
131 }
132
133 /*******************************************************************
134  ********************************************************************/
135
136 WERROR _winreg_OpenHKPT(pipes_struct *p, struct winreg_OpenHKPT *r)
137 {
138         return open_registry_key(p, r->out.handle, NULL, KEY_HKPT, r->in.access_mask);
139 }
140
141 /*******************************************************************
142  ********************************************************************/
143
144 WERROR _winreg_OpenHKCR(pipes_struct *p, struct winreg_OpenHKCR *r)
145 {
146         return open_registry_key(p, r->out.handle, NULL, KEY_HKCR, r->in.access_mask);
147 }
148
149 /*******************************************************************
150  ********************************************************************/
151
152 WERROR _winreg_OpenHKU(pipes_struct *p, struct winreg_OpenHKU *r)
153 {
154         return open_registry_key(p, r->out.handle, NULL, KEY_HKU, r->in.access_mask);
155 }
156
157 /*******************************************************************
158  ********************************************************************/
159
160 WERROR _winreg_OpenHKCU(pipes_struct *p, struct winreg_OpenHKCU *r)
161 {
162         return open_registry_key(p, r->out.handle, NULL, KEY_HKCU, r->in.access_mask);
163 }
164
165 /*******************************************************************
166  ********************************************************************/
167
168 WERROR _winreg_OpenHKCC(pipes_struct *p, struct winreg_OpenHKCC *r)
169 {
170         return open_registry_key(p, r->out.handle, NULL, KEY_HKCC, r->in.access_mask);
171 }
172
173 /*******************************************************************
174  ********************************************************************/
175
176 WERROR _winreg_OpenHKDD(pipes_struct *p, struct winreg_OpenHKDD *r)
177 {
178         return open_registry_key(p, r->out.handle, NULL, KEY_HKDD, r->in.access_mask);
179 }
180
181 /*******************************************************************
182  ********************************************************************/
183
184 WERROR _winreg_OpenHKPN(pipes_struct *p, struct winreg_OpenHKPN *r)
185 {
186         return open_registry_key(p, r->out.handle, NULL, KEY_HKPN, r->in.access_mask);
187 }
188
189 /*******************************************************************
190  reg_reply_open_entry
191  ********************************************************************/
192
193 WERROR _winreg_OpenKey(pipes_struct *p, struct winreg_OpenKey *r)
194 {
195         struct registry_key *parent = find_regkey_by_hnd(p, r->in.parent_handle );
196
197         if ( !parent )
198                 return WERR_BADFID;
199
200         return open_registry_key(p, r->out.handle, parent, r->in.keyname.name, r->in.access_mask);
201 }
202
203 /*******************************************************************
204  reg_reply_info
205  ********************************************************************/
206
207 WERROR _winreg_QueryValue(pipes_struct *p, struct winreg_QueryValue *r)
208 {
209         WERROR        status = WERR_BADFILE;
210         struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
211         prs_struct    prs_hkpd;
212
213         uint8_t *outbuf;
214         uint32_t outbuf_size;
215
216         DATA_BLOB val_blob;
217         bool free_buf = False;
218         bool free_prs = False;
219
220         if ( !regkey )
221                 return WERR_BADFID;
222
223         if ((r->out.data_length == NULL) || (r->out.type == NULL)) {
224                 return WERR_INVALID_PARAM;
225         }
226
227         *r->out.data_length = *r->out.type = REG_NONE;
228         
229         DEBUG(7,("_reg_info: policy key name = [%s]\n", regkey->key->name));
230         DEBUG(7,("_reg_info: policy key type = [%08x]\n", regkey->key->type));
231         
232         /* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */
233         if(regkey->key->type == REG_KEY_HKPD) 
234         {
235                 if (strequal(r->in.value_name->name, "Global")) {
236                         if (!prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL))
237                                 return WERR_NOMEM;
238                         status = reg_perfcount_get_hkpd(
239                                 &prs_hkpd, *r->in.data_size, &outbuf_size, NULL);
240                         outbuf = (uint8_t *)prs_hkpd.data_p;
241                         free_prs = True;
242                 }
243                 else if (strequal(r->in.value_name->name, "Counter 009")) {
244                         outbuf_size = reg_perfcount_get_counter_names(
245                                 reg_perfcount_get_base_index(),
246                                 (char **)(void *)&outbuf);
247                         free_buf = True;
248                 }
249                 else if (strequal(r->in.value_name->name, "Explain 009")) {
250                         outbuf_size = reg_perfcount_get_counter_help(
251                                 reg_perfcount_get_base_index(),
252                                 (char **)(void *)&outbuf);
253                         free_buf = True;
254                 }
255                 else if (isdigit(r->in.value_name->name[0])) {
256                         /* we probably have a request for a specific object
257                          * here */
258                         if (!prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL))
259                                 return WERR_NOMEM;
260                         status = reg_perfcount_get_hkpd(
261                                 &prs_hkpd, *r->in.data_size, &outbuf_size,
262                                 r->in.value_name->name);
263                         outbuf = (uint8_t *)prs_hkpd.data_p;
264                         free_prs = True;
265                 }
266                 else {
267                         DEBUG(3,("Unsupported key name [%s] for HKPD.\n",
268                                  r->in.value_name->name));
269                         return WERR_BADFILE;
270                 }
271
272                 *r->out.type = REG_BINARY;
273         }
274         else {
275                 struct registry_value *val;
276
277                 status = reg_queryvalue(p->mem_ctx, regkey, r->in.value_name->name,
278                                         &val);
279                 if (!W_ERROR_IS_OK(status)) {
280                         if (r->out.data_size) {
281                                 *r->out.data_size = 0;
282                         }
283                         if (r->out.data_length) {
284                                 *r->out.data_length = 0;
285                         }
286                         return status;
287                 }
288
289                 status = registry_push_value(p->mem_ctx, val, &val_blob);
290                 if (!W_ERROR_IS_OK(status)) {
291                         return status;
292                 }
293
294                 outbuf = val_blob.data;
295                 outbuf_size = val_blob.length;
296                 *r->out.type = val->type;
297         }
298
299         *r->out.data_length = outbuf_size;
300
301         if ( *r->in.data_size == 0 || !r->out.data ) {
302                 status = WERR_OK;
303         } else if ( *r->out.data_length > *r->in.data_size ) {
304                 status = WERR_MORE_DATA;
305         } else {
306                 memcpy( r->out.data, outbuf, *r->out.data_length );
307                 status = WERR_OK;
308         }
309
310         *r->out.data_size = *r->out.data_length;
311
312         if (free_prs) prs_mem_free(&prs_hkpd);
313         if (free_buf) SAFE_FREE(outbuf);
314
315         return status;
316 }
317
318 /*****************************************************************************
319  Implementation of REG_QUERY_KEY
320  ****************************************************************************/
321
322 WERROR _winreg_QueryInfoKey(pipes_struct *p, struct winreg_QueryInfoKey *r)
323 {
324         WERROR  status = WERR_OK;
325         struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
326         
327         if ( !regkey )
328                 return WERR_BADFID;
329
330         r->out.classname->name = NULL;
331
332         status = reg_queryinfokey(regkey, r->out.num_subkeys, r->out.max_subkeylen,
333                                   r->out.max_classlen, r->out.num_values, r->out.max_valnamelen,
334                                   r->out.max_valbufsize, r->out.secdescsize,
335                                   r->out.last_changed_time);
336         if (!W_ERROR_IS_OK(status)) {
337                 return status;
338         }
339
340         /*
341          * These calculations account for the registry buffers being
342          * UTF-16. They are inexact at best, but so far they worked.
343          */
344
345         *r->out.max_subkeylen *= 2;
346
347         *r->out.max_valnamelen += 1;
348         *r->out.max_valnamelen *= 2;
349         
350         return WERR_OK;
351 }
352
353
354 /*****************************************************************************
355  Implementation of REG_GETVERSION
356  ****************************************************************************/
357  
358 WERROR _winreg_GetVersion(pipes_struct *p, struct winreg_GetVersion *r)
359 {
360         struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
361         
362         if ( !regkey )
363                 return WERR_BADFID;
364         
365         return reg_getversion(r->out.version);
366 }
367
368
369 /*****************************************************************************
370  Implementation of REG_ENUM_KEY
371  ****************************************************************************/
372  
373 WERROR _winreg_EnumKey(pipes_struct *p, struct winreg_EnumKey *r)
374 {
375         WERROR err;
376         struct registry_key *key = find_regkey_by_hnd( p, r->in.handle );
377         
378         if ( !key )
379                 return WERR_BADFID; 
380
381         if ( !r->in.name || !r->in.keyclass )
382                 return WERR_INVALID_PARAM;
383
384         DEBUG(8,("_reg_enum_key: enumerating key [%s]\n", key->key->name));
385
386         err = reg_enumkey(p->mem_ctx, key, r->in.enum_index, (char **)&r->out.name->name,
387                           r->out.last_changed_time);
388         if (!W_ERROR_IS_OK(err)) {
389                 return err;
390         }
391         r->out.keyclass->name = "";
392         return WERR_OK;
393 }
394
395 /*****************************************************************************
396  Implementation of REG_ENUM_VALUE
397  ****************************************************************************/
398
399 WERROR _winreg_EnumValue(pipes_struct *p, struct winreg_EnumValue *r)
400 {
401         WERROR err;
402         struct registry_key *key = find_regkey_by_hnd( p, r->in.handle );
403         char *valname;
404         struct registry_value *val;
405         DATA_BLOB value_blob;
406         
407         if ( !key )
408                 return WERR_BADFID;
409
410         if ( !r->in.name )
411                 return WERR_INVALID_PARAM;
412
413         DEBUG(8,("_winreg_EnumValue: enumerating values for key [%s]\n",
414                  key->key->name));
415
416         err = reg_enumvalue(p->mem_ctx, key, r->in.enum_index, &valname, &val);
417         if (!W_ERROR_IS_OK(err)) {
418                 return err;
419         }
420
421         err = registry_push_value(p->mem_ctx, val, &value_blob);
422         if (!W_ERROR_IS_OK(err)) {
423                 return err;
424         }
425
426         if (r->out.name != NULL) {
427                 r->out.name->name = valname;
428         }
429
430         if (r->out.type != NULL) {
431                 *r->out.type = val->type;
432         }
433
434         if (r->out.value != NULL) {
435                 if ((r->out.size == NULL) || (r->out.length == NULL)) {
436                         return WERR_INVALID_PARAM;
437                 }
438
439                 if (value_blob.length > *r->out.size) {
440                         return WERR_MORE_DATA;
441                 }
442
443                 memcpy( r->out.value, value_blob.data, value_blob.length );
444         }
445
446         if (r->out.length != NULL) {
447                 *r->out.length = value_blob.length;
448         }
449         if (r->out.size != NULL) {
450                 *r->out.size = value_blob.length;
451         }
452
453         return WERR_OK;
454 }
455
456 /*******************************************************************
457  reg_shutdwon
458  ********************************************************************/
459
460 WERROR _winreg_InitiateSystemShutdown(pipes_struct *p, struct winreg_InitiateSystemShutdown *r)
461 {
462         struct winreg_InitiateSystemShutdownEx s;
463
464         s.in.hostname = r->in.hostname;
465         s.in.message = r->in.message;
466         s.in.timeout = r->in.timeout;
467         s.in.force_apps = r->in.force_apps;
468         s.in.do_reboot = r->in.do_reboot;
469         s.in.reason = 0;
470
471         /* thunk down to _winreg_InitiateSystemShutdownEx() 
472            (just returns a status) */
473         
474         return _winreg_InitiateSystemShutdownEx( p, &s );
475 }
476
477 /*******************************************************************
478  reg_shutdown_ex
479  ********************************************************************/
480
481 #define SHUTDOWN_R_STRING "-r"
482 #define SHUTDOWN_F_STRING "-f"
483
484
485 WERROR _winreg_InitiateSystemShutdownEx(pipes_struct *p, struct winreg_InitiateSystemShutdownEx *r)
486 {
487         char *shutdown_script = NULL;
488         char *msg = NULL;
489         char *chkmsg = NULL;
490         fstring str_timeout;
491         fstring str_reason;
492         fstring do_reboot;
493         fstring f;
494         int ret;
495         bool can_shutdown;
496
497         shutdown_script = talloc_strdup(p->mem_ctx, lp_shutdown_script());
498         if (!shutdown_script) {
499                 return WERR_NOMEM;
500         }
501         if (!*shutdown_script) {
502                 return WERR_ACCESS_DENIED;
503         }
504
505         /* pull the message string and perform necessary sanity checks on it */
506
507         if ( r->in.message && r->in.message->string ) {
508                 if ( (msg = talloc_strdup(p->mem_ctx, r->in.message->string )) == NULL ) {
509                         return WERR_NOMEM;
510                 }
511                 chkmsg = TALLOC_ARRAY(p->mem_ctx, char, strlen(msg)+1);
512                 if (!chkmsg) {
513                         return WERR_NOMEM;
514                 }
515                 alpha_strcpy(chkmsg, msg, NULL, strlen(msg)+1);
516         }
517
518         fstr_sprintf(str_timeout, "%d", r->in.timeout);
519         fstr_sprintf(do_reboot, r->in.do_reboot ? SHUTDOWN_R_STRING : "");
520         fstr_sprintf(f, r->in.force_apps ? SHUTDOWN_F_STRING : "");
521         fstr_sprintf(str_reason, "%d", r->in.reason );
522
523         shutdown_script = talloc_all_string_sub(p->mem_ctx,
524                                 shutdown_script, "%z", chkmsg ? chkmsg : "");
525         if (!shutdown_script) {
526                 return WERR_NOMEM;
527         }
528         shutdown_script = talloc_all_string_sub(p->mem_ctx,
529                                         shutdown_script, "%t", str_timeout);
530         if (!shutdown_script) {
531                 return WERR_NOMEM;
532         }
533         shutdown_script = talloc_all_string_sub(p->mem_ctx,
534                                                 shutdown_script, "%r", do_reboot);
535         if (!shutdown_script) {
536                 return WERR_NOMEM;
537         }
538         shutdown_script = talloc_all_string_sub(p->mem_ctx,
539                                                 shutdown_script, "%f", f);
540         if (!shutdown_script) {
541                 return WERR_NOMEM;
542         }
543         shutdown_script = talloc_all_string_sub(p->mem_ctx,
544                                         shutdown_script, "%x", str_reason);
545         if (!shutdown_script) {
546                 return WERR_NOMEM;
547         }
548
549         can_shutdown = user_has_privileges( p->server_info->ptok,
550                                             &se_remote_shutdown );
551
552         /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
553            Take the error return from the script and provide it as the Windows return code. */
554
555         /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
556
557         if ( can_shutdown )
558                 become_root();
559
560         ret = smbrun( shutdown_script, NULL );
561
562         if ( can_shutdown )
563                 unbecome_root();
564
565         /********** END SeRemoteShutdownPrivilege BLOCK **********/
566
567         DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
568                 shutdown_script, ret));
569
570         return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
571 }
572
573 /*******************************************************************
574  reg_abort_shutdwon
575  ********************************************************************/
576
577 WERROR _winreg_AbortSystemShutdown(pipes_struct *p, struct winreg_AbortSystemShutdown *r)
578 {
579         const char *abort_shutdown_script;
580         int ret;
581         bool can_shutdown;
582
583         abort_shutdown_script = lp_abort_shutdown_script();
584
585         if (!*abort_shutdown_script)
586                 return WERR_ACCESS_DENIED;
587
588         can_shutdown = user_has_privileges( p->server_info->ptok,
589                                             &se_remote_shutdown );
590
591         /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
592
593         if ( can_shutdown )
594                 become_root();
595
596         ret = smbrun( abort_shutdown_script, NULL );
597
598         if ( can_shutdown )
599                 unbecome_root();
600
601         /********** END SeRemoteShutdownPrivilege BLOCK **********/
602
603         DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",
604                 abort_shutdown_script, ret));
605
606         return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
607 }
608
609 /*******************************************************************
610  ********************************************************************/
611
612 static int validate_reg_filename(TALLOC_CTX *ctx, char **pp_fname )
613 {
614         char *p = NULL;
615         int num_services = lp_numservices();
616         int snum = -1;
617         const char *share_path;
618         char *fname = *pp_fname;
619
620         /* convert to a unix path, stripping the C:\ along the way */
621
622         if (!(p = valid_share_pathname(ctx, fname))) {
623                 return -1;
624         }
625
626         /* has to exist within a valid file share */
627
628         for (snum=0; snum<num_services; snum++) {
629                 if (!lp_snum_ok(snum) || lp_print_ok(snum)) {
630                         continue;
631                 }
632
633                 share_path = lp_pathname(snum);
634
635                 /* make sure we have a path (e.g. [homes] ) */
636                 if (strlen(share_path) == 0) {
637                         continue;
638                 }
639
640                 if (strncmp(share_path, p, strlen(share_path)) == 0) {
641                         break;
642                 }
643         }
644
645         *pp_fname = p;
646         return (snum < num_services) ? snum : -1;
647 }
648
649 /*******************************************************************
650  ********************************************************************/
651
652 WERROR _winreg_RestoreKey(pipes_struct *p, struct winreg_RestoreKey *r)
653 {
654         struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
655         char *fname = NULL;
656         int             snum;
657
658         if ( !regkey )
659                 return WERR_BADFID;
660
661         if ( !r->in.filename || !r->in.filename->name )
662                 return WERR_INVALID_PARAM;
663
664         fname = talloc_strdup(p->mem_ctx, r->in.filename->name);
665         if (!fname) {
666                 return WERR_NOMEM;
667         }
668
669         DEBUG(8,("_winreg_RestoreKey: verifying restore of key [%s] from "
670                  "\"%s\"\n", regkey->key->name, fname));
671
672         if ((snum = validate_reg_filename(p->mem_ctx, &fname)) == -1)
673                 return WERR_OBJECT_PATH_INVALID;
674
675         /* user must posses SeRestorePrivilege for this this proceed */
676
677         if ( !user_has_privileges( p->server_info->ptok, &se_restore ) )
678                 return WERR_ACCESS_DENIED;
679
680         DEBUG(2,("_winreg_RestoreKey: Restoring [%s] from %s in share %s\n",
681                  regkey->key->name, fname, lp_servicename(snum) ));
682
683         return reg_restorekey(regkey, fname);
684 }
685
686 WERROR _winreg_SaveKey(pipes_struct *p, struct winreg_SaveKey *r)
687 {
688         struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
689         char *fname = NULL;
690         int snum = -1;
691
692         if ( !regkey )
693                 return WERR_BADFID;
694
695         if ( !r->in.filename || !r->in.filename->name )
696                 return WERR_INVALID_PARAM;
697
698         fname = talloc_strdup(p->mem_ctx, r->in.filename->name);
699         if (!fname) {
700                 return WERR_NOMEM;
701         }
702
703         DEBUG(8,("_winreg_SaveKey: verifying backup of key [%s] to \"%s\"\n",
704                  regkey->key->name, fname));
705
706         if ((snum = validate_reg_filename(p->mem_ctx, &fname)) == -1 )
707                 return WERR_OBJECT_PATH_INVALID;
708
709         DEBUG(2,("_winreg_SaveKey: Saving [%s] to %s in share %s\n",
710                  regkey->key->name, fname, lp_servicename(snum) ));
711
712         return reg_savekey(regkey, fname);
713 }
714
715 /*******************************************************************
716  ********************************************************************/
717
718 WERROR _winreg_SaveKeyEx(pipes_struct *p, struct winreg_SaveKeyEx *r)
719 {
720         /* fill in your code here if you think this call should
721            do anything */
722
723         p->rng_fault_state = True;
724         return WERR_NOT_SUPPORTED;
725 }
726
727 /*******************************************************************
728  ********************************************************************/
729
730 WERROR _winreg_CreateKey( pipes_struct *p, struct winreg_CreateKey *r)
731 {
732         struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
733         struct registry_key *new_key;
734         WERROR result;
735
736         if ( !parent )
737                 return WERR_BADFID;
738
739         DEBUG(10, ("_winreg_CreateKey called with parent key '%s' and "
740                    "subkey name '%s'\n", parent->key->name, r->in.name.name));
741
742         result = reg_createkey(NULL, parent, r->in.name.name, r->in.access_mask,
743                                &new_key, r->out.action_taken);
744         if (!W_ERROR_IS_OK(result)) {
745                 return result;
746         }
747
748         if (!create_policy_hnd(p, r->out.new_handle, new_key)) {
749                 TALLOC_FREE(new_key);
750                 return WERR_BADFILE;
751         }
752
753         return WERR_OK;
754 }
755
756 /*******************************************************************
757  ********************************************************************/
758
759 WERROR _winreg_SetValue(pipes_struct *p, struct winreg_SetValue *r)
760 {
761         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
762         struct registry_value *val;
763         WERROR status;
764
765         if ( !key )
766                 return WERR_BADFID;
767
768         DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n", 
769                          key->key->name, r->in.name.name));
770
771         status = registry_pull_value(p->mem_ctx, &val, r->in.type, r->in.data, 
772                                                                  r->in.size, r->in.size);
773         if (!W_ERROR_IS_OK(status)) {
774                 return status;
775         }
776
777         return reg_setvalue(key, r->in.name.name, val);
778 }
779
780 /*******************************************************************
781  ********************************************************************/
782
783 WERROR _winreg_DeleteKey(pipes_struct *p, struct winreg_DeleteKey *r)
784 {
785         struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
786
787         if ( !parent )
788                 return WERR_BADFID;
789
790         return reg_deletekey(parent, r->in.key.name);
791 }
792
793
794 /*******************************************************************
795  ********************************************************************/
796
797 WERROR _winreg_DeleteValue(pipes_struct *p, struct winreg_DeleteValue *r)
798 {
799         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
800         
801         if ( !key )
802                 return WERR_BADFID;
803
804         return reg_deletevalue(key, r->in.value.name);
805 }
806
807 /*******************************************************************
808  ********************************************************************/
809
810 WERROR _winreg_GetKeySecurity(pipes_struct *p, struct winreg_GetKeySecurity *r)
811 {
812         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
813         WERROR err;
814         struct security_descriptor *secdesc;
815         uint8 *data;
816         size_t len;
817
818         if ( !key )
819                 return WERR_BADFID;
820                 
821         /* access checks first */
822         
823         if ( !(key->key->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
824                 return WERR_ACCESS_DENIED;
825
826         err = reg_getkeysecurity(p->mem_ctx, key, &secdesc);
827         if (!W_ERROR_IS_OK(err)) {
828                 return err;
829         }
830
831         err = ntstatus_to_werror(marshall_sec_desc(p->mem_ctx, secdesc,
832                                                    &data, &len));
833         if (!W_ERROR_IS_OK(err)) {
834                 return err;
835         }
836
837         if (len > r->out.sd->size) {
838                 r->out.sd->size = len;
839                 return WERR_INSUFFICIENT_BUFFER;
840         }
841
842         r->out.sd->size = len;
843         r->out.sd->len = len;
844         r->out.sd->data = data;
845                 
846         return WERR_OK;
847 }
848
849 /*******************************************************************
850  ********************************************************************/
851
852 WERROR _winreg_SetKeySecurity(pipes_struct *p, struct winreg_SetKeySecurity *r)
853 {
854         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
855         struct security_descriptor *secdesc;
856         WERROR err;
857
858         if ( !key )
859                 return WERR_BADFID;
860                 
861         /* access checks first */
862         
863         if ( !(key->key->access_granted & STD_RIGHT_WRITE_DAC_ACCESS) )
864                 return WERR_ACCESS_DENIED;
865
866         err = ntstatus_to_werror(unmarshall_sec_desc(p->mem_ctx, r->in.sd->data,
867                                                      r->in.sd->len, &secdesc));
868         if (!W_ERROR_IS_OK(err)) {
869                 return err;
870         }
871
872         return reg_setkeysecurity(key, secdesc);
873 }
874
875 /*******************************************************************
876  ********************************************************************/
877
878 WERROR _winreg_FlushKey(pipes_struct *p, struct winreg_FlushKey *r)
879 {
880         /* I'm just replying OK because there's not a lot 
881            here I see to do i  --jerry */
882         
883         return WERR_OK;
884 }
885
886 /*******************************************************************
887  ********************************************************************/
888
889 WERROR _winreg_UnLoadKey(pipes_struct *p, struct winreg_UnLoadKey *r)
890 {
891         /* fill in your code here if you think this call should
892            do anything */
893
894         p->rng_fault_state = True;
895         return WERR_NOT_SUPPORTED;
896 }
897
898 /*******************************************************************
899  ********************************************************************/
900
901 WERROR _winreg_ReplaceKey(pipes_struct *p, struct winreg_ReplaceKey *r)
902 {
903         /* fill in your code here if you think this call should
904            do anything */
905
906         p->rng_fault_state = True;
907         return WERR_NOT_SUPPORTED;
908 }
909
910 /*******************************************************************
911  ********************************************************************/
912
913 WERROR _winreg_LoadKey(pipes_struct *p, struct winreg_LoadKey *r)
914 {
915         /* fill in your code here if you think this call should
916            do anything */
917
918         p->rng_fault_state = True;
919         return WERR_NOT_SUPPORTED;
920 }
921
922 /*******************************************************************
923  ********************************************************************/
924
925 WERROR _winreg_NotifyChangeKeyValue(pipes_struct *p, struct winreg_NotifyChangeKeyValue *r)
926 {
927         /* fill in your code here if you think this call should
928            do anything */
929
930         p->rng_fault_state = True;
931         return WERR_NOT_SUPPORTED;
932 }
933
934 /*******************************************************************
935  ********************************************************************/
936
937 WERROR _winreg_QueryMultipleValues(pipes_struct *p, struct winreg_QueryMultipleValues *r)
938 {
939         /* fill in your code here if you think this call should
940            do anything */
941
942         p->rng_fault_state = True;
943         return WERR_NOT_SUPPORTED;
944 }
945
946 /*******************************************************************
947  ********************************************************************/
948
949 WERROR _winreg_QueryMultipleValues2(pipes_struct *p, struct winreg_QueryMultipleValues2 *r)
950 {
951         /* fill in your code here if you think this call should
952            do anything */
953
954         p->rng_fault_state = True;
955         return WERR_NOT_SUPPORTED;
956 }
957