s3-winreg: add some debug statements to _winreg_QueryValue().
[kai/samba.git] / source3 / rpc_server / srv_winreg_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *
5  *  Copyright (C) Gerald Carter                 2002-2006.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20
21 /* Implementation of registry functions. */
22
23 #include "includes.h"
24 #include "../librpc/gen_ndr/srv_winreg.h"
25
26 #undef DBGC_CLASS
27 #define DBGC_CLASS DBGC_RPC_SRV
28
29 /******************************************************************
30  Find a registry key handle and return a struct registry_key *
31  *****************************************************************/
32
33 static struct registry_key *find_regkey_by_hnd(pipes_struct *p,
34                                                struct policy_handle *hnd)
35 {
36         struct registry_key *regkey = NULL;
37
38         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&regkey)) {
39                 DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: "));
40                 return NULL;
41         }
42
43         return regkey;
44 }
45
46 /*******************************************************************
47  Function for open a new registry handle and creating a handle
48  Note that P should be valid & hnd should already have space
49
50  When we open a key, we store the full path to the key as
51  HK[LM|U]\<key>\<key>\...
52  *******************************************************************/
53
54 static WERROR open_registry_key( pipes_struct *p, struct policy_handle *hnd,
55                                  struct registry_key *parent,
56                                  const char *subkeyname,
57                                  uint32 access_desired  )
58 {
59         WERROR result = WERR_OK;
60         struct registry_key *key;
61
62         if (parent == NULL) {
63                 result = reg_openhive(p->mem_ctx, subkeyname, access_desired,
64                                       p->server_info->ptok, &key);
65         }
66         else {
67                 result = reg_openkey(p->mem_ctx, parent, subkeyname,
68                                      access_desired, &key);
69         }
70
71         if ( !W_ERROR_IS_OK(result) ) {
72                 return result;
73         }
74
75         if ( !create_policy_hnd( p, hnd, key ) ) {
76                 return WERR_BADFILE;
77         }
78
79         return WERR_OK;
80 }
81
82 /*******************************************************************
83  Function for open a new registry handle and creating a handle
84  Note that P should be valid & hnd should already have space
85  *******************************************************************/
86
87 static bool close_registry_key(pipes_struct *p, struct policy_handle *hnd)
88 {
89         struct registry_key *regkey = find_regkey_by_hnd(p, hnd);
90
91         if ( !regkey ) {
92                 DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n",
93                          OUR_HANDLE(hnd)));
94                 return False;
95         }
96
97         close_policy_hnd(p, hnd);
98
99         return True;
100 }
101
102 /********************************************************************
103  _winreg_CloseKey
104  ********************************************************************/
105
106 WERROR _winreg_CloseKey(pipes_struct *p, struct winreg_CloseKey *r)
107 {
108         /* close the policy handle */
109
110         if (!close_registry_key(p, r->in.handle))
111                 return WERR_BADFID;
112
113         ZERO_STRUCTP(r->out.handle);
114
115         return WERR_OK;
116 }
117
118 /*******************************************************************
119  _winreg_OpenHKLM
120  ********************************************************************/
121
122 WERROR _winreg_OpenHKLM(pipes_struct *p, struct winreg_OpenHKLM *r)
123 {
124         return open_registry_key(p, r->out.handle, NULL, KEY_HKLM, r->in.access_mask);
125 }
126
127 /*******************************************************************
128  _winreg_OpenHKPD
129  ********************************************************************/
130
131 WERROR _winreg_OpenHKPD(pipes_struct *p, struct winreg_OpenHKPD *r)
132 {
133         return open_registry_key(p, r->out.handle, NULL, KEY_HKPD, r->in.access_mask);
134 }
135
136 /*******************************************************************
137  _winreg_OpenHKPT
138  ********************************************************************/
139
140 WERROR _winreg_OpenHKPT(pipes_struct *p, struct winreg_OpenHKPT *r)
141 {
142         return open_registry_key(p, r->out.handle, NULL, KEY_HKPT, r->in.access_mask);
143 }
144
145 /*******************************************************************
146  _winreg_OpenHKCR
147  ********************************************************************/
148
149 WERROR _winreg_OpenHKCR(pipes_struct *p, struct winreg_OpenHKCR *r)
150 {
151         return open_registry_key(p, r->out.handle, NULL, KEY_HKCR, r->in.access_mask);
152 }
153
154 /*******************************************************************
155  _winreg_OpenHKU
156  ********************************************************************/
157
158 WERROR _winreg_OpenHKU(pipes_struct *p, struct winreg_OpenHKU *r)
159 {
160         return open_registry_key(p, r->out.handle, NULL, KEY_HKU, r->in.access_mask);
161 }
162
163 /*******************************************************************
164  _winreg_OpenHKCU
165  ********************************************************************/
166
167 WERROR _winreg_OpenHKCU(pipes_struct *p, struct winreg_OpenHKCU *r)
168 {
169         return open_registry_key(p, r->out.handle, NULL, KEY_HKCU, r->in.access_mask);
170 }
171
172 /*******************************************************************
173  _winreg_OpenHKCC
174  ********************************************************************/
175
176 WERROR _winreg_OpenHKCC(pipes_struct *p, struct winreg_OpenHKCC *r)
177 {
178         return open_registry_key(p, r->out.handle, NULL, KEY_HKCC, r->in.access_mask);
179 }
180
181 /*******************************************************************
182  _winreg_OpenHKDD
183  ********************************************************************/
184
185 WERROR _winreg_OpenHKDD(pipes_struct *p, struct winreg_OpenHKDD *r)
186 {
187         return open_registry_key(p, r->out.handle, NULL, KEY_HKDD, r->in.access_mask);
188 }
189
190 /*******************************************************************
191  _winreg_OpenHKPN
192  ********************************************************************/
193
194 WERROR _winreg_OpenHKPN(pipes_struct *p, struct winreg_OpenHKPN *r)
195 {
196         return open_registry_key(p, r->out.handle, NULL, KEY_HKPN, r->in.access_mask);
197 }
198
199 /*******************************************************************
200  _winreg_OpenKey
201  ********************************************************************/
202
203 WERROR _winreg_OpenKey(pipes_struct *p, struct winreg_OpenKey *r)
204 {
205         struct registry_key *parent = find_regkey_by_hnd(p, r->in.parent_handle );
206
207         if ( !parent )
208                 return WERR_BADFID;
209
210         return open_registry_key(p, r->out.handle, parent, r->in.keyname.name, r->in.access_mask);
211 }
212
213 /*******************************************************************
214  _winreg_QueryValue
215  ********************************************************************/
216
217 WERROR _winreg_QueryValue(pipes_struct *p, struct winreg_QueryValue *r)
218 {
219         WERROR        status = WERR_BADFILE;
220         struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
221         prs_struct    prs_hkpd;
222
223         uint8_t *outbuf;
224         uint32_t outbuf_size;
225
226         DATA_BLOB val_blob;
227         bool free_buf = False;
228         bool free_prs = False;
229
230         if ( !regkey )
231                 return WERR_BADFID;
232
233         if ((r->out.data_length == NULL) || (r->out.type == NULL)) {
234                 return WERR_INVALID_PARAM;
235         }
236
237         *r->out.data_length = *r->out.type = REG_NONE;
238
239         DEBUG(7,("_winreg_QueryValue: policy key name = [%s]\n", regkey->key->name));
240         DEBUG(7,("_winreg_QueryValue: policy key type = [%08x]\n", regkey->key->type));
241
242         /* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */
243         if(regkey->key->type == REG_KEY_HKPD)
244         {
245                 if (strequal(r->in.value_name->name, "Global")) {
246                         if (!prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL))
247                                 return WERR_NOMEM;
248                         status = reg_perfcount_get_hkpd(
249                                 &prs_hkpd, *r->in.data_size, &outbuf_size, NULL);
250                         outbuf = (uint8_t *)prs_hkpd.data_p;
251                         free_prs = True;
252                 }
253                 else if (strequal(r->in.value_name->name, "Counter 009")) {
254                         outbuf_size = reg_perfcount_get_counter_names(
255                                 reg_perfcount_get_base_index(),
256                                 (char **)(void *)&outbuf);
257                         free_buf = True;
258                 }
259                 else if (strequal(r->in.value_name->name, "Explain 009")) {
260                         outbuf_size = reg_perfcount_get_counter_help(
261                                 reg_perfcount_get_base_index(),
262                                 (char **)(void *)&outbuf);
263                         free_buf = True;
264                 }
265                 else if (isdigit(r->in.value_name->name[0])) {
266                         /* we probably have a request for a specific object
267                          * here */
268                         if (!prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL))
269                                 return WERR_NOMEM;
270                         status = reg_perfcount_get_hkpd(
271                                 &prs_hkpd, *r->in.data_size, &outbuf_size,
272                                 r->in.value_name->name);
273                         outbuf = (uint8_t *)prs_hkpd.data_p;
274                         free_prs = True;
275                 }
276                 else {
277                         DEBUG(3,("Unsupported key name [%s] for HKPD.\n",
278                                  r->in.value_name->name));
279                         return WERR_BADFILE;
280                 }
281
282                 *r->out.type = REG_BINARY;
283         }
284         else {
285                 struct registry_value *val;
286
287                 status = reg_queryvalue(p->mem_ctx, regkey, r->in.value_name->name,
288                                         &val);
289                 if (!W_ERROR_IS_OK(status)) {
290
291                         DEBUG(10,("_winreg_QueryValue: reg_queryvalue failed with: %s\n",
292                                 win_errstr(status)));
293
294                         if (r->out.data_size) {
295                                 *r->out.data_size = 0;
296                         }
297                         if (r->out.data_length) {
298                                 *r->out.data_length = 0;
299                         }
300                         return status;
301                 }
302
303                 status = registry_push_value(p->mem_ctx, val, &val_blob);
304                 if (!W_ERROR_IS_OK(status)) {
305                         return status;
306                 }
307
308                 outbuf = val_blob.data;
309                 outbuf_size = val_blob.length;
310                 *r->out.type = val->type;
311         }
312
313         *r->out.data_length = outbuf_size;
314
315         if ( *r->in.data_size == 0 || !r->out.data ) {
316                 status = WERR_OK;
317         } else if ( *r->out.data_length > *r->in.data_size ) {
318                 status = WERR_MORE_DATA;
319         } else {
320                 memcpy( r->out.data, outbuf, *r->out.data_length );
321                 status = WERR_OK;
322         }
323
324         *r->out.data_size = *r->out.data_length;
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,("_reg_enum_key: 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         DATA_BLOB value_blob;
420
421         if ( !key )
422                 return WERR_BADFID;
423
424         if ( !r->in.name )
425                 return WERR_INVALID_PARAM;
426
427         DEBUG(8,("_winreg_EnumValue: enumerating values for key [%s]\n",
428                  key->key->name));
429
430         err = reg_enumvalue(p->mem_ctx, key, r->in.enum_index, &valname, &val);
431         if (!W_ERROR_IS_OK(err)) {
432                 return err;
433         }
434
435         err = registry_push_value(p->mem_ctx, val, &value_blob);
436         if (!W_ERROR_IS_OK(err)) {
437                 return err;
438         }
439
440         if (r->out.name != NULL) {
441                 r->out.name->name = valname;
442         }
443
444         if (r->out.type != NULL) {
445                 *r->out.type = val->type;
446         }
447
448         if (r->out.value != NULL) {
449                 if ((r->out.size == NULL) || (r->out.length == NULL)) {
450                         return WERR_INVALID_PARAM;
451                 }
452
453                 if (value_blob.length > *r->out.size) {
454                         return WERR_MORE_DATA;
455                 }
456
457                 memcpy( r->out.value, value_blob.data, value_blob.length );
458         }
459
460         if (r->out.length != NULL) {
461                 *r->out.length = value_blob.length;
462         }
463         if (r->out.size != NULL) {
464                 *r->out.size = value_blob.length;
465         }
466
467         return WERR_OK;
468 }
469
470 /*******************************************************************
471  _winreg_InitiateSystemShutdown
472  ********************************************************************/
473
474 WERROR _winreg_InitiateSystemShutdown(pipes_struct *p, struct winreg_InitiateSystemShutdown *r)
475 {
476         struct winreg_InitiateSystemShutdownEx s;
477
478         s.in.hostname = r->in.hostname;
479         s.in.message = r->in.message;
480         s.in.timeout = r->in.timeout;
481         s.in.force_apps = r->in.force_apps;
482         s.in.do_reboot = r->in.do_reboot;
483         s.in.reason = 0;
484
485         /* thunk down to _winreg_InitiateSystemShutdownEx()
486            (just returns a status) */
487
488         return _winreg_InitiateSystemShutdownEx( p, &s );
489 }
490
491 /*******************************************************************
492  _winreg_InitiateSystemShutdownEx
493  ********************************************************************/
494
495 #define SHUTDOWN_R_STRING "-r"
496 #define SHUTDOWN_F_STRING "-f"
497
498
499 WERROR _winreg_InitiateSystemShutdownEx(pipes_struct *p, struct winreg_InitiateSystemShutdownEx *r)
500 {
501         char *shutdown_script = NULL;
502         char *msg = NULL;
503         char *chkmsg = NULL;
504         fstring str_timeout;
505         fstring str_reason;
506         fstring do_reboot;
507         fstring f;
508         int ret;
509         bool can_shutdown;
510
511         shutdown_script = talloc_strdup(p->mem_ctx, lp_shutdown_script());
512         if (!shutdown_script) {
513                 return WERR_NOMEM;
514         }
515         if (!*shutdown_script) {
516                 return WERR_ACCESS_DENIED;
517         }
518
519         /* pull the message string and perform necessary sanity checks on it */
520
521         if ( r->in.message && r->in.message->string ) {
522                 if ( (msg = talloc_strdup(p->mem_ctx, r->in.message->string )) == NULL ) {
523                         return WERR_NOMEM;
524                 }
525                 chkmsg = TALLOC_ARRAY(p->mem_ctx, char, strlen(msg)+1);
526                 if (!chkmsg) {
527                         return WERR_NOMEM;
528                 }
529                 alpha_strcpy(chkmsg, msg, NULL, strlen(msg)+1);
530         }
531
532         fstr_sprintf(str_timeout, "%d", r->in.timeout);
533         fstr_sprintf(do_reboot, r->in.do_reboot ? SHUTDOWN_R_STRING : "");
534         fstr_sprintf(f, r->in.force_apps ? SHUTDOWN_F_STRING : "");
535         fstr_sprintf(str_reason, "%d", r->in.reason );
536
537         shutdown_script = talloc_all_string_sub(p->mem_ctx,
538                                 shutdown_script, "%z", chkmsg ? chkmsg : "");
539         if (!shutdown_script) {
540                 return WERR_NOMEM;
541         }
542         shutdown_script = talloc_all_string_sub(p->mem_ctx,
543                                         shutdown_script, "%t", str_timeout);
544         if (!shutdown_script) {
545                 return WERR_NOMEM;
546         }
547         shutdown_script = talloc_all_string_sub(p->mem_ctx,
548                                                 shutdown_script, "%r", do_reboot);
549         if (!shutdown_script) {
550                 return WERR_NOMEM;
551         }
552         shutdown_script = talloc_all_string_sub(p->mem_ctx,
553                                                 shutdown_script, "%f", f);
554         if (!shutdown_script) {
555                 return WERR_NOMEM;
556         }
557         shutdown_script = talloc_all_string_sub(p->mem_ctx,
558                                         shutdown_script, "%x", str_reason);
559         if (!shutdown_script) {
560                 return WERR_NOMEM;
561         }
562
563         can_shutdown = user_has_privileges( p->server_info->ptok,
564                                             &se_remote_shutdown );
565
566         /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
567            Take the error return from the script and provide it as the Windows return code. */
568
569         /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
570
571         if ( can_shutdown )
572                 become_root();
573
574         ret = smbrun( shutdown_script, NULL );
575
576         if ( can_shutdown )
577                 unbecome_root();
578
579         /********** END SeRemoteShutdownPrivilege BLOCK **********/
580
581         DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
582                 shutdown_script, ret));
583
584         return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
585 }
586
587 /*******************************************************************
588  _winreg_AbortSystemShutdown
589  ********************************************************************/
590
591 WERROR _winreg_AbortSystemShutdown(pipes_struct *p, struct winreg_AbortSystemShutdown *r)
592 {
593         const char *abort_shutdown_script;
594         int ret;
595         bool can_shutdown;
596
597         abort_shutdown_script = lp_abort_shutdown_script();
598
599         if (!*abort_shutdown_script)
600                 return WERR_ACCESS_DENIED;
601
602         can_shutdown = user_has_privileges( p->server_info->ptok,
603                                             &se_remote_shutdown );
604
605         /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
606
607         if ( can_shutdown )
608                 become_root();
609
610         ret = smbrun( abort_shutdown_script, NULL );
611
612         if ( can_shutdown )
613                 unbecome_root();
614
615         /********** END SeRemoteShutdownPrivilege BLOCK **********/
616
617         DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",
618                 abort_shutdown_script, ret));
619
620         return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
621 }
622
623 /*******************************************************************
624  ********************************************************************/
625
626 static int validate_reg_filename(TALLOC_CTX *ctx, char **pp_fname )
627 {
628         char *p = NULL;
629         int num_services = lp_numservices();
630         int snum = -1;
631         const char *share_path;
632         char *fname = *pp_fname;
633
634         /* convert to a unix path, stripping the C:\ along the way */
635
636         if (!(p = valid_share_pathname(ctx, fname))) {
637                 return -1;
638         }
639
640         /* has to exist within a valid file share */
641
642         for (snum=0; snum<num_services; snum++) {
643                 if (!lp_snum_ok(snum) || lp_print_ok(snum)) {
644                         continue;
645                 }
646
647                 share_path = lp_pathname(snum);
648
649                 /* make sure we have a path (e.g. [homes] ) */
650                 if (strlen(share_path) == 0) {
651                         continue;
652                 }
653
654                 if (strncmp(share_path, p, strlen(share_path)) == 0) {
655                         break;
656                 }
657         }
658
659         *pp_fname = p;
660         return (snum < num_services) ? snum : -1;
661 }
662
663 /*******************************************************************
664  _winreg_RestoreKey
665  ********************************************************************/
666
667 WERROR _winreg_RestoreKey(pipes_struct *p, struct winreg_RestoreKey *r)
668 {
669         struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
670         char *fname = NULL;
671         int             snum;
672
673         if ( !regkey )
674                 return WERR_BADFID;
675
676         if ( !r->in.filename || !r->in.filename->name )
677                 return WERR_INVALID_PARAM;
678
679         fname = talloc_strdup(p->mem_ctx, r->in.filename->name);
680         if (!fname) {
681                 return WERR_NOMEM;
682         }
683
684         DEBUG(8,("_winreg_RestoreKey: verifying restore of key [%s] from "
685                  "\"%s\"\n", regkey->key->name, fname));
686
687         if ((snum = validate_reg_filename(p->mem_ctx, &fname)) == -1)
688                 return WERR_OBJECT_PATH_INVALID;
689
690         /* user must posses SeRestorePrivilege for this this proceed */
691
692         if ( !user_has_privileges( p->server_info->ptok, &se_restore ) )
693                 return WERR_ACCESS_DENIED;
694
695         DEBUG(2,("_winreg_RestoreKey: Restoring [%s] from %s in share %s\n",
696                  regkey->key->name, fname, lp_servicename(snum) ));
697
698         return reg_restorekey(regkey, fname);
699 }
700
701 /*******************************************************************
702  _winreg_SaveKey
703  ********************************************************************/
704
705 WERROR _winreg_SaveKey(pipes_struct *p, struct winreg_SaveKey *r)
706 {
707         struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
708         char *fname = NULL;
709         int snum = -1;
710
711         if ( !regkey )
712                 return WERR_BADFID;
713
714         if ( !r->in.filename || !r->in.filename->name )
715                 return WERR_INVALID_PARAM;
716
717         fname = talloc_strdup(p->mem_ctx, r->in.filename->name);
718         if (!fname) {
719                 return WERR_NOMEM;
720         }
721
722         DEBUG(8,("_winreg_SaveKey: verifying backup of key [%s] to \"%s\"\n",
723                  regkey->key->name, fname));
724
725         if ((snum = validate_reg_filename(p->mem_ctx, &fname)) == -1 )
726                 return WERR_OBJECT_PATH_INVALID;
727
728         DEBUG(2,("_winreg_SaveKey: Saving [%s] to %s in share %s\n",
729                  regkey->key->name, fname, lp_servicename(snum) ));
730
731         return reg_savekey(regkey, fname);
732 }
733
734 /*******************************************************************
735  _winreg_SaveKeyEx
736  ********************************************************************/
737
738 WERROR _winreg_SaveKeyEx(pipes_struct *p, struct winreg_SaveKeyEx *r)
739 {
740         /* fill in your code here if you think this call should
741            do anything */
742
743         p->rng_fault_state = True;
744         return WERR_NOT_SUPPORTED;
745 }
746
747 /*******************************************************************
748  _winreg_CreateKey
749  ********************************************************************/
750
751 WERROR _winreg_CreateKey( pipes_struct *p, struct winreg_CreateKey *r)
752 {
753         struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
754         struct registry_key *new_key;
755         WERROR result;
756
757         if ( !parent )
758                 return WERR_BADFID;
759
760         DEBUG(10, ("_winreg_CreateKey called with parent key '%s' and "
761                    "subkey name '%s'\n", parent->key->name, r->in.name.name));
762
763         result = reg_createkey(NULL, parent, r->in.name.name, r->in.access_mask,
764                                &new_key, r->out.action_taken);
765         if (!W_ERROR_IS_OK(result)) {
766                 return result;
767         }
768
769         if (!create_policy_hnd(p, r->out.new_handle, new_key)) {
770                 TALLOC_FREE(new_key);
771                 return WERR_BADFILE;
772         }
773
774         return WERR_OK;
775 }
776
777 /*******************************************************************
778  _winreg_SetValue
779  ********************************************************************/
780
781 WERROR _winreg_SetValue(pipes_struct *p, struct winreg_SetValue *r)
782 {
783         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
784         struct registry_value *val;
785         WERROR status;
786
787         if ( !key )
788                 return WERR_BADFID;
789
790         DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n",
791                          key->key->name, r->in.name.name));
792
793         status = registry_pull_value(p->mem_ctx, &val, r->in.type, r->in.data,
794                                                                  r->in.size, r->in.size);
795         if (!W_ERROR_IS_OK(status)) {
796                 return status;
797         }
798
799         return reg_setvalue(key, r->in.name.name, val);
800 }
801
802 /*******************************************************************
803  _winreg_DeleteKey
804  ********************************************************************/
805
806 WERROR _winreg_DeleteKey(pipes_struct *p, struct winreg_DeleteKey *r)
807 {
808         struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
809
810         if ( !parent )
811                 return WERR_BADFID;
812
813         return reg_deletekey(parent, r->in.key.name);
814 }
815
816
817 /*******************************************************************
818  _winreg_DeleteValue
819  ********************************************************************/
820
821 WERROR _winreg_DeleteValue(pipes_struct *p, struct winreg_DeleteValue *r)
822 {
823         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
824
825         if ( !key )
826                 return WERR_BADFID;
827
828         return reg_deletevalue(key, r->in.value.name);
829 }
830
831 /*******************************************************************
832  _winreg_GetKeySecurity
833  ********************************************************************/
834
835 WERROR _winreg_GetKeySecurity(pipes_struct *p, struct winreg_GetKeySecurity *r)
836 {
837         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
838         WERROR err;
839         struct security_descriptor *secdesc;
840         uint8 *data;
841         size_t len;
842
843         if ( !key )
844                 return WERR_BADFID;
845
846         /* access checks first */
847
848         if ( !(key->key->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
849                 return WERR_ACCESS_DENIED;
850
851         err = reg_getkeysecurity(p->mem_ctx, key, &secdesc);
852         if (!W_ERROR_IS_OK(err)) {
853                 return err;
854         }
855
856         err = ntstatus_to_werror(marshall_sec_desc(p->mem_ctx, secdesc,
857                                                    &data, &len));
858         if (!W_ERROR_IS_OK(err)) {
859                 return err;
860         }
861
862         if (len > r->out.sd->size) {
863                 r->out.sd->size = len;
864                 return WERR_INSUFFICIENT_BUFFER;
865         }
866
867         r->out.sd->size = len;
868         r->out.sd->len = len;
869         r->out.sd->data = data;
870
871         return WERR_OK;
872 }
873
874 /*******************************************************************
875  _winreg_SetKeySecurity
876  ********************************************************************/
877
878 WERROR _winreg_SetKeySecurity(pipes_struct *p, struct winreg_SetKeySecurity *r)
879 {
880         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
881         struct security_descriptor *secdesc;
882         WERROR err;
883
884         if ( !key )
885                 return WERR_BADFID;
886
887         /* access checks first */
888
889         if ( !(key->key->access_granted & STD_RIGHT_WRITE_DAC_ACCESS) )
890                 return WERR_ACCESS_DENIED;
891
892         err = ntstatus_to_werror(unmarshall_sec_desc(p->mem_ctx, r->in.sd->data,
893                                                      r->in.sd->len, &secdesc));
894         if (!W_ERROR_IS_OK(err)) {
895                 return err;
896         }
897
898         return reg_setkeysecurity(key, secdesc);
899 }
900
901 /*******************************************************************
902  _winreg_FlushKey
903  ********************************************************************/
904
905 WERROR _winreg_FlushKey(pipes_struct *p, struct winreg_FlushKey *r)
906 {
907         /* I'm just replying OK because there's not a lot
908            here I see to do i  --jerry */
909
910         return WERR_OK;
911 }
912
913 /*******************************************************************
914  _winreg_UnLoadKey
915  ********************************************************************/
916
917 WERROR _winreg_UnLoadKey(pipes_struct *p, struct winreg_UnLoadKey *r)
918 {
919         /* fill in your code here if you think this call should
920            do anything */
921
922         p->rng_fault_state = True;
923         return WERR_NOT_SUPPORTED;
924 }
925
926 /*******************************************************************
927  _winreg_ReplaceKey
928  ********************************************************************/
929
930 WERROR _winreg_ReplaceKey(pipes_struct *p, struct winreg_ReplaceKey *r)
931 {
932         /* fill in your code here if you think this call should
933            do anything */
934
935         p->rng_fault_state = True;
936         return WERR_NOT_SUPPORTED;
937 }
938
939 /*******************************************************************
940  _winreg_LoadKey
941  ********************************************************************/
942
943 WERROR _winreg_LoadKey(pipes_struct *p, struct winreg_LoadKey *r)
944 {
945         /* fill in your code here if you think this call should
946            do anything */
947
948         p->rng_fault_state = True;
949         return WERR_NOT_SUPPORTED;
950 }
951
952 /*******************************************************************
953  _winreg_NotifyChangeKeyValue
954  ********************************************************************/
955
956 WERROR _winreg_NotifyChangeKeyValue(pipes_struct *p, struct winreg_NotifyChangeKeyValue *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_QueryMultipleValues
967  ********************************************************************/
968
969 WERROR _winreg_QueryMultipleValues(pipes_struct *p, struct winreg_QueryMultipleValues *r)
970 {
971         /* fill in your code here if you think this call should
972            do anything */
973
974         p->rng_fault_state = True;
975         return WERR_NOT_SUPPORTED;
976 }
977
978 /*******************************************************************
979  _winreg_QueryMultipleValues2
980  ********************************************************************/
981
982 WERROR _winreg_QueryMultipleValues2(pipes_struct *p, struct winreg_QueryMultipleValues2 *r)
983 {
984         /* fill in your code here if you think this call should
985            do anything */
986
987         p->rng_fault_state = True;
988         return WERR_NOT_SUPPORTED;
989 }
990