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