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