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