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