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