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