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