s3: include ntdomain.h before including generated srv_ headers.
[obnox/samba/samba-obnox.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_api_regf.h"
29 #include "registry/reg_perfcount.h"
30 #include "rpc_misc.h"
31 #include "auth.h"
32 #include "lib/privileges.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_BADFILE;
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_BADFID;
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_BADFID;
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_BADFILE;
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_BADFID;
253
254         if (r->in.value_name->name == NULL) {
255                 return WERR_INVALID_PARAM;
256         }
257
258         if ((r->out.data_length == NULL) || (r->out.type == NULL) || (r->out.data_size == NULL)) {
259                 return WERR_INVALID_PARAM;
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_NOMEM;
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_NOMEM;
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_BADFILE;
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_BADFILE;
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_BADFID;
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_BADFID;
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
414         if ( !key )
415                 return WERR_BADFID;
416
417         if ( !r->in.name || !r->in.keyclass )
418                 return WERR_INVALID_PARAM;
419
420         DEBUG(8,("_winreg_EnumKey: enumerating key [%s]\n", key->key->name));
421
422         err = reg_enumkey(p->mem_ctx, key, r->in.enum_index, (char **)&r->out.name->name,
423                           r->out.last_changed_time);
424         if (!W_ERROR_IS_OK(err)) {
425                 return err;
426         }
427         r->out.keyclass->name = "";
428         return WERR_OK;
429 }
430
431 /*****************************************************************************
432  _winreg_EnumValue
433  ****************************************************************************/
434
435 WERROR _winreg_EnumValue(struct pipes_struct *p,
436                          struct winreg_EnumValue *r)
437 {
438         WERROR err = WERR_OK;
439         struct registry_key *key = find_regkey_by_hnd( p, r->in.handle );
440         char *valname = NULL;
441         struct registry_value *val = NULL;
442
443         if ( !key )
444                 return WERR_BADFID;
445
446         if ( !r->in.name )
447                 return WERR_INVALID_PARAM;
448
449         DEBUG(8,("_winreg_EnumValue: enumerating values for key [%s]\n",
450                  key->key->name));
451
452         err = reg_enumvalue(p->mem_ctx, key, r->in.enum_index, &valname, &val);
453         if (!W_ERROR_IS_OK(err)) {
454                 return err;
455         }
456
457         if (r->out.name != NULL) {
458                 r->out.name->name = valname;
459         }
460
461         if (r->out.type != NULL) {
462                 *r->out.type = val->type;
463         }
464
465         if (r->out.value != NULL) {
466                 if ((r->out.size == NULL) || (r->out.length == NULL)) {
467                         return WERR_INVALID_PARAM;
468                 }
469
470                 if (val->data.length > *r->out.size) {
471                         return WERR_MORE_DATA;
472                 }
473
474                 memcpy( r->out.value, val->data.data, val->data.length );
475         }
476
477         if (r->out.length != NULL) {
478                 *r->out.length = val->data.length;
479         }
480         if (r->out.size != NULL) {
481                 *r->out.size = val->data.length;
482         }
483
484         return WERR_OK;
485 }
486
487 /*******************************************************************
488  _winreg_InitiateSystemShutdown
489  ********************************************************************/
490
491 WERROR _winreg_InitiateSystemShutdown(struct pipes_struct *p,
492                                       struct winreg_InitiateSystemShutdown *r)
493 {
494         struct winreg_InitiateSystemShutdownEx s;
495
496         s.in.hostname = r->in.hostname;
497         s.in.message = r->in.message;
498         s.in.timeout = r->in.timeout;
499         s.in.force_apps = r->in.force_apps;
500         s.in.do_reboot = r->in.do_reboot;
501         s.in.reason = 0;
502
503         /* thunk down to _winreg_InitiateSystemShutdownEx()
504            (just returns a status) */
505
506         return _winreg_InitiateSystemShutdownEx( p, &s );
507 }
508
509 /*******************************************************************
510  _winreg_InitiateSystemShutdownEx
511  ********************************************************************/
512
513 #define SHUTDOWN_R_STRING "-r"
514 #define SHUTDOWN_F_STRING "-f"
515
516
517 WERROR _winreg_InitiateSystemShutdownEx(struct pipes_struct *p,
518                                         struct winreg_InitiateSystemShutdownEx *r)
519 {
520         char *shutdown_script = NULL;
521         char *msg = NULL;
522         char *chkmsg = NULL;
523         fstring str_timeout;
524         fstring str_reason;
525         fstring do_reboot;
526         fstring f;
527         int ret = -1;
528         bool can_shutdown = false;
529
530         shutdown_script = talloc_strdup(p->mem_ctx, lp_shutdown_script());
531         if (!shutdown_script) {
532                 return WERR_NOMEM;
533         }
534         if (!*shutdown_script) {
535                 return WERR_ACCESS_DENIED;
536         }
537
538         /* pull the message string and perform necessary sanity checks on it */
539
540         if ( r->in.message && r->in.message->string ) {
541                 if ( (msg = talloc_strdup(p->mem_ctx, r->in.message->string )) == NULL ) {
542                         return WERR_NOMEM;
543                 }
544                 chkmsg = TALLOC_ARRAY(p->mem_ctx, char, strlen(msg)+1);
545                 if (!chkmsg) {
546                         return WERR_NOMEM;
547                 }
548                 alpha_strcpy(chkmsg, msg, NULL, strlen(msg)+1);
549         }
550
551         fstr_sprintf(str_timeout, "%d", r->in.timeout);
552         fstr_sprintf(do_reboot, r->in.do_reboot ? SHUTDOWN_R_STRING : "");
553         fstr_sprintf(f, r->in.force_apps ? SHUTDOWN_F_STRING : "");
554         fstr_sprintf(str_reason, "%d", r->in.reason );
555
556         shutdown_script = talloc_all_string_sub(p->mem_ctx,
557                                 shutdown_script, "%z", chkmsg ? chkmsg : "");
558         if (!shutdown_script) {
559                 return WERR_NOMEM;
560         }
561         shutdown_script = talloc_all_string_sub(p->mem_ctx,
562                                         shutdown_script, "%t", str_timeout);
563         if (!shutdown_script) {
564                 return WERR_NOMEM;
565         }
566         shutdown_script = talloc_all_string_sub(p->mem_ctx,
567                                                 shutdown_script, "%r", do_reboot);
568         if (!shutdown_script) {
569                 return WERR_NOMEM;
570         }
571         shutdown_script = talloc_all_string_sub(p->mem_ctx,
572                                                 shutdown_script, "%f", f);
573         if (!shutdown_script) {
574                 return WERR_NOMEM;
575         }
576         shutdown_script = talloc_all_string_sub(p->mem_ctx,
577                                         shutdown_script, "%x", str_reason);
578         if (!shutdown_script) {
579                 return WERR_NOMEM;
580         }
581
582         can_shutdown = security_token_has_privilege(p->session_info->security_token, SEC_PRIV_REMOTE_SHUTDOWN);
583
584         /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
585            Take the error return from the script and provide it as the Windows return code. */
586
587         /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
588
589         if ( can_shutdown )
590                 become_root();
591
592         ret = smbrun( shutdown_script, NULL );
593
594         if ( can_shutdown )
595                 unbecome_root();
596
597         /********** END SeRemoteShutdownPrivilege BLOCK **********/
598
599         DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
600                 shutdown_script, ret));
601
602         return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
603 }
604
605 /*******************************************************************
606  _winreg_AbortSystemShutdown
607  ********************************************************************/
608
609 WERROR _winreg_AbortSystemShutdown(struct pipes_struct *p,
610                                    struct winreg_AbortSystemShutdown *r)
611 {
612         const char *abort_shutdown_script = lp_abort_shutdown_script();
613         int ret = -1;
614         bool can_shutdown = false;
615
616         if (!*abort_shutdown_script)
617                 return WERR_ACCESS_DENIED;
618
619         can_shutdown = security_token_has_privilege(p->session_info->security_token, SEC_PRIV_REMOTE_SHUTDOWN);
620
621         /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
622
623         if ( can_shutdown )
624                 become_root();
625
626         ret = smbrun( abort_shutdown_script, NULL );
627
628         if ( can_shutdown )
629                 unbecome_root();
630
631         /********** END SeRemoteShutdownPrivilege BLOCK **********/
632
633         DEBUG(3,("_winreg_AbortSystemShutdown: Running the command `%s' gave %d\n",
634                 abort_shutdown_script, ret));
635
636         return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
637 }
638
639 /*******************************************************************
640  ********************************************************************/
641
642 static int validate_reg_filename(TALLOC_CTX *ctx, char **pp_fname )
643 {
644         char *p = NULL;
645         int num_services = lp_numservices();
646         int snum = -1;
647         const char *share_path = NULL;
648         char *fname = *pp_fname;
649
650         /* convert to a unix path, stripping the C:\ along the way */
651
652         if (!(p = valid_share_pathname(ctx, fname))) {
653                 return -1;
654         }
655
656         /* has to exist within a valid file share */
657
658         for (snum=0; snum<num_services; snum++) {
659                 if (!lp_snum_ok(snum) || lp_print_ok(snum)) {
660                         continue;
661                 }
662
663                 share_path = lp_pathname(snum);
664
665                 /* make sure we have a path (e.g. [homes] ) */
666                 if (strlen(share_path) == 0) {
667                         continue;
668                 }
669
670                 if (strncmp(share_path, p, strlen(share_path)) == 0) {
671                         break;
672                 }
673         }
674
675         *pp_fname = p;
676         return (snum < num_services) ? snum : -1;
677 }
678
679 /*******************************************************************
680  _winreg_RestoreKey
681  ********************************************************************/
682
683 WERROR _winreg_RestoreKey(struct pipes_struct *p,
684                           struct winreg_RestoreKey *r)
685 {
686         struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
687         char *fname = NULL;
688         int snum = -1;
689
690         if ( !regkey )
691                 return WERR_BADFID;
692
693         if ( !r->in.filename || !r->in.filename->name )
694                 return WERR_INVALID_PARAM;
695
696         fname = talloc_strdup(p->mem_ctx, r->in.filename->name);
697         if (!fname) {
698                 return WERR_NOMEM;
699         }
700
701         DEBUG(8,("_winreg_RestoreKey: verifying restore of key [%s] from "
702                  "\"%s\"\n", regkey->key->name, fname));
703
704         if ((snum = validate_reg_filename(p->mem_ctx, &fname)) == -1)
705                 return WERR_OBJECT_PATH_INVALID;
706
707         /* user must posses SeRestorePrivilege for this this proceed */
708
709         if ( !security_token_has_privilege(p->session_info->security_token, SEC_PRIV_RESTORE)) {
710                 return WERR_ACCESS_DENIED;
711         }
712
713         DEBUG(2,("_winreg_RestoreKey: Restoring [%s] from %s in share %s\n",
714                  regkey->key->name, fname, lp_servicename(snum) ));
715
716         return reg_restorekey(regkey, fname);
717 }
718
719 /*******************************************************************
720  _winreg_SaveKey
721  ********************************************************************/
722
723 WERROR _winreg_SaveKey(struct pipes_struct *p,
724                        struct winreg_SaveKey *r)
725 {
726         struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
727         char *fname = NULL;
728         int snum = -1;
729
730         if ( !regkey )
731                 return WERR_BADFID;
732
733         if ( !r->in.filename || !r->in.filename->name )
734                 return WERR_INVALID_PARAM;
735
736         fname = talloc_strdup(p->mem_ctx, r->in.filename->name);
737         if (!fname) {
738                 return WERR_NOMEM;
739         }
740
741         DEBUG(8,("_winreg_SaveKey: verifying backup of key [%s] to \"%s\"\n",
742                  regkey->key->name, fname));
743
744         if ((snum = validate_reg_filename(p->mem_ctx, &fname)) == -1 )
745                 return WERR_OBJECT_PATH_INVALID;
746
747         DEBUG(2,("_winreg_SaveKey: Saving [%s] to %s in share %s\n",
748                  regkey->key->name, fname, lp_servicename(snum) ));
749
750         return reg_savekey(regkey, fname);
751 }
752
753 /*******************************************************************
754  _winreg_SaveKeyEx
755  ********************************************************************/
756
757 WERROR _winreg_SaveKeyEx(struct pipes_struct *p,
758                          struct winreg_SaveKeyEx *r)
759 {
760         /* fill in your code here if you think this call should
761            do anything */
762
763         p->rng_fault_state = True;
764         return WERR_NOT_SUPPORTED;
765 }
766
767 /*******************************************************************
768  _winreg_CreateKey
769  ********************************************************************/
770
771 WERROR _winreg_CreateKey(struct pipes_struct *p,
772                          struct winreg_CreateKey *r)
773 {
774         struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
775         struct registry_key *new_key = NULL;
776         WERROR result = WERR_OK;
777
778         if ( !parent )
779                 return WERR_BADFID;
780
781         DEBUG(10, ("_winreg_CreateKey called with parent key '%s' and "
782                    "subkey name '%s'\n", parent->key->name, r->in.name.name));
783
784         result = reg_createkey(NULL, parent, r->in.name.name, r->in.access_mask,
785                                &new_key, r->out.action_taken);
786         if (!W_ERROR_IS_OK(result)) {
787                 return result;
788         }
789
790         if (!create_policy_hnd(p, r->out.new_handle, new_key)) {
791                 TALLOC_FREE(new_key);
792                 return WERR_BADFILE;
793         }
794
795         return WERR_OK;
796 }
797
798 /*******************************************************************
799  _winreg_SetValue
800  ********************************************************************/
801
802 WERROR _winreg_SetValue(struct pipes_struct *p,
803                         struct winreg_SetValue *r)
804 {
805         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
806         struct registry_value *val = NULL;
807
808         if ( !key )
809                 return WERR_BADFID;
810
811         DEBUG(8,("_winreg_SetValue: Setting value for [%s:%s]\n",
812                          key->key->name, r->in.name.name));
813
814         val = talloc_zero(p->mem_ctx, struct registry_value);
815         if (val == NULL) {
816                 return WERR_NOMEM;
817         }
818
819         val->type = r->in.type;
820         val->data = data_blob_talloc(p->mem_ctx, r->in.data, r->in.size);
821
822         return reg_setvalue(key, r->in.name.name, val);
823 }
824
825 /*******************************************************************
826  _winreg_DeleteKey
827  ********************************************************************/
828
829 WERROR _winreg_DeleteKey(struct pipes_struct *p,
830                          struct winreg_DeleteKey *r)
831 {
832         struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
833
834         if ( !parent )
835                 return WERR_BADFID;
836
837         return reg_deletekey(parent, r->in.key.name);
838 }
839
840
841 /*******************************************************************
842  _winreg_DeleteValue
843  ********************************************************************/
844
845 WERROR _winreg_DeleteValue(struct pipes_struct *p,
846                            struct winreg_DeleteValue *r)
847 {
848         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
849
850         if ( !key )
851                 return WERR_BADFID;
852
853         return reg_deletevalue(key, r->in.value.name);
854 }
855
856 /*******************************************************************
857  _winreg_GetKeySecurity
858  ********************************************************************/
859
860 WERROR _winreg_GetKeySecurity(struct pipes_struct *p,
861                               struct winreg_GetKeySecurity *r)
862 {
863         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
864         WERROR err = WERR_OK;
865         struct security_descriptor *secdesc = NULL;
866         uint8 *data = NULL;
867         size_t len = 0;
868
869         if ( !key )
870                 return WERR_BADFID;
871
872         /* access checks first */
873
874         if ( !(key->key->access_granted & SEC_STD_READ_CONTROL) )
875                 return WERR_ACCESS_DENIED;
876
877         err = reg_getkeysecurity(p->mem_ctx, key, &secdesc);
878         if (!W_ERROR_IS_OK(err)) {
879                 return err;
880         }
881
882         err = ntstatus_to_werror(marshall_sec_desc(p->mem_ctx, secdesc,
883                                                    &data, &len));
884         if (!W_ERROR_IS_OK(err)) {
885                 return err;
886         }
887
888         if (len > r->out.sd->size) {
889                 r->out.sd->size = len;
890                 return WERR_INSUFFICIENT_BUFFER;
891         }
892
893         r->out.sd->size = len;
894         r->out.sd->len = len;
895         r->out.sd->data = data;
896
897         return WERR_OK;
898 }
899
900 /*******************************************************************
901  _winreg_SetKeySecurity
902  ********************************************************************/
903
904 WERROR _winreg_SetKeySecurity(struct pipes_struct *p,
905                               struct winreg_SetKeySecurity *r)
906 {
907         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
908         struct security_descriptor *secdesc = NULL;
909         WERROR err = WERR_OK;
910
911         if ( !key )
912                 return WERR_BADFID;
913
914         /* access checks first */
915
916         if ( !(key->key->access_granted & SEC_STD_WRITE_DAC) )
917                 return WERR_ACCESS_DENIED;
918
919         err = ntstatus_to_werror(unmarshall_sec_desc(p->mem_ctx, r->in.sd->data,
920                                                      r->in.sd->len, &secdesc));
921         if (!W_ERROR_IS_OK(err)) {
922                 return err;
923         }
924
925         return reg_setkeysecurity(key, secdesc);
926 }
927
928 /*******************************************************************
929  _winreg_FlushKey
930  ********************************************************************/
931
932 WERROR _winreg_FlushKey(struct pipes_struct *p,
933                         struct winreg_FlushKey *r)
934 {
935         /* I'm just replying OK because there's not a lot
936            here I see to do i  --jerry */
937
938         return WERR_OK;
939 }
940
941 /*******************************************************************
942  _winreg_UnLoadKey
943  ********************************************************************/
944
945 WERROR _winreg_UnLoadKey(struct pipes_struct *p,
946                          struct winreg_UnLoadKey *r)
947 {
948         /* fill in your code here if you think this call should
949            do anything */
950
951         p->rng_fault_state = True;
952         return WERR_NOT_SUPPORTED;
953 }
954
955 /*******************************************************************
956  _winreg_ReplaceKey
957  ********************************************************************/
958
959 WERROR _winreg_ReplaceKey(struct pipes_struct *p,
960                           struct winreg_ReplaceKey *r)
961 {
962         /* fill in your code here if you think this call should
963            do anything */
964
965         p->rng_fault_state = True;
966         return WERR_NOT_SUPPORTED;
967 }
968
969 /*******************************************************************
970  _winreg_LoadKey
971  ********************************************************************/
972
973 WERROR _winreg_LoadKey(struct pipes_struct *p,
974                        struct winreg_LoadKey *r)
975 {
976         /* fill in your code here if you think this call should
977            do anything */
978
979         p->rng_fault_state = True;
980         return WERR_NOT_SUPPORTED;
981 }
982
983 /*******************************************************************
984  _winreg_NotifyChangeKeyValue
985  ********************************************************************/
986
987 WERROR _winreg_NotifyChangeKeyValue(struct pipes_struct *p,
988                                     struct winreg_NotifyChangeKeyValue *r)
989 {
990         return WERR_NOT_SUPPORTED;
991 }
992
993 /*******************************************************************
994  _winreg_QueryMultipleValues
995  ********************************************************************/
996
997 WERROR _winreg_QueryMultipleValues(struct pipes_struct *p,
998                                    struct winreg_QueryMultipleValues *r)
999 {
1000         struct winreg_QueryMultipleValues2 r2;
1001         uint32_t needed = 0;
1002
1003         r2.in.key_handle        = r->in.key_handle;
1004         r2.in.values_in         = r->in.values_in;
1005         r2.in.num_values        = r->in.num_values;
1006         r2.in.offered           = r->in.buffer_size;
1007         r2.in.buffer            = r->in.buffer;
1008         r2.out.values_out       = r->out.values_out;
1009         r2.out.needed           = &needed;
1010         r2.out.buffer           = r->out.buffer;
1011
1012         return _winreg_QueryMultipleValues2(p, &r2);
1013 }
1014
1015 /*******************************************************************
1016  ********************************************************************/
1017
1018 static WERROR construct_multiple_entry(TALLOC_CTX *mem_ctx,
1019                                        const char *valuename,
1020                                        uint32_t value_length,
1021                                        uint32_t offset,
1022                                        enum winreg_Type type,
1023                                        struct QueryMultipleValue *r)
1024 {
1025         r->ve_valuename = talloc_zero(mem_ctx, struct winreg_ValNameBuf);
1026         if (r->ve_valuename == NULL) {
1027                 return WERR_NOMEM;
1028         }
1029
1030         r->ve_valuename->name = talloc_strdup(r->ve_valuename, valuename ? valuename : "");
1031         if (r->ve_valuename->name == NULL) {
1032                 return WERR_NOMEM;
1033         }
1034
1035         r->ve_valuename->size = strlen_m_term(r->ve_valuename->name)*2;
1036         r->ve_valuelen = value_length;
1037         r->ve_valueptr = offset;
1038         r->ve_type = type;
1039
1040         return WERR_OK;
1041 }
1042
1043 /*******************************************************************
1044  _winreg_QueryMultipleValues2
1045  ********************************************************************/
1046
1047 WERROR _winreg_QueryMultipleValues2(struct pipes_struct *p,
1048                                     struct winreg_QueryMultipleValues2 *r)
1049 {
1050         struct registry_key *regkey = find_regkey_by_hnd(p, r->in.key_handle);
1051         struct registry_value *vals = NULL;
1052         const char **names = NULL;
1053         uint32_t offset = 0, num_vals = 0;
1054         DATA_BLOB result = data_blob_null;
1055         int i = 0;
1056         WERROR err = WERR_OK;
1057
1058         if (!regkey) {
1059                 return WERR_BADFID;
1060         }
1061
1062         names = talloc_zero_array(p->mem_ctx, const char *, r->in.num_values);
1063         if (names == NULL) {
1064                 return WERR_NOMEM;
1065         }
1066
1067         for (i=0; i < r->in.num_values; i++) {
1068                 if (r->in.values_in[i].ve_valuename &&
1069                     r->in.values_in[i].ve_valuename->name) {
1070                         names[i] = talloc_strdup(names,
1071                                 r->in.values_in[i].ve_valuename->name);
1072                         if (names[i] == NULL) {
1073                                 return WERR_NOMEM;
1074                         }
1075                 }
1076         }
1077
1078         err = reg_querymultiplevalues(p->mem_ctx, regkey,
1079                                       r->in.num_values, names,
1080                                       &num_vals, &vals);
1081         if (!W_ERROR_IS_OK(err)) {
1082                 return err;
1083         }
1084
1085         result = data_blob_talloc(p->mem_ctx, NULL, 0);
1086
1087         for (i=0; i < r->in.num_values; i++) {
1088                 const char *valuename = NULL;
1089
1090                 if (vals[i].data.length > 0) {
1091                         if (!data_blob_append(p->mem_ctx, &result,
1092                                               vals[i].data.data,
1093                                               vals[i].data.length)) {
1094                                 return WERR_NOMEM;
1095                         }
1096                 }
1097
1098                 if (r->in.values_in[i].ve_valuename &&
1099                     r->in.values_in[i].ve_valuename->name) {
1100                         valuename = r->in.values_in[i].ve_valuename->name;
1101                 }
1102
1103                 err = construct_multiple_entry(r->out.values_out,
1104                                                valuename,
1105                                                vals[i].data.length,
1106                                                offset,
1107                                                vals[i].type,
1108                                                &r->out.values_out[i]);
1109                 if (!W_ERROR_IS_OK(err)) {
1110                         return err;
1111                 }
1112
1113                 offset += vals[i].data.length;
1114         }
1115
1116         *r->out.needed = result.length;
1117
1118         if (r->in.num_values != num_vals) {
1119                 return WERR_BADFILE;
1120         }
1121
1122         if (*r->in.offered >= *r->out.needed) {
1123                 if (r->out.buffer) {
1124                         memcpy(r->out.buffer, result.data, MIN(result.length, *r->in.offered));
1125                 }
1126                 return WERR_OK;
1127         } else {
1128                 return WERR_MORE_DATA;
1129         }
1130 }
1131
1132 /*******************************************************************
1133  _winreg_DeleteKeyEx
1134  ********************************************************************/
1135
1136 WERROR _winreg_DeleteKeyEx(struct pipes_struct *p,
1137                            struct winreg_DeleteKeyEx *r)
1138 {
1139         /* fill in your code here if you think this call should
1140            do anything */
1141
1142         p->rng_fault_state = True;
1143         return WERR_NOT_SUPPORTED;
1144 }