692c83cb6918272fdf796589bd8b2e7c3527f99c
[sfrench/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
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) || (r->out.data_size == NULL)) {
234                 return WERR_INVALID_PARAM;
235         }
236
237         DEBUG(7,("_winreg_QueryValue: policy key name = [%s]\n", regkey->key->name));
238         DEBUG(7,("_winreg_QueryValue: policy key type = [%08x]\n", regkey->key->type));
239
240         /* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */
241         if(regkey->key->type == REG_KEY_HKPD)
242         {
243                 if (strequal(r->in.value_name->name, "Global")) {
244                         if (!prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL))
245                                 return WERR_NOMEM;
246                         status = reg_perfcount_get_hkpd(
247                                 &prs_hkpd, *r->in.data_size, &outbuf_size, NULL);
248                         outbuf = (uint8_t *)prs_hkpd.data_p;
249                         free_prs = True;
250                 }
251                 else if (strequal(r->in.value_name->name, "Counter 009")) {
252                         outbuf_size = reg_perfcount_get_counter_names(
253                                 reg_perfcount_get_base_index(),
254                                 (char **)(void *)&outbuf);
255                         free_buf = True;
256                 }
257                 else if (strequal(r->in.value_name->name, "Explain 009")) {
258                         outbuf_size = reg_perfcount_get_counter_help(
259                                 reg_perfcount_get_base_index(),
260                                 (char **)(void *)&outbuf);
261                         free_buf = True;
262                 }
263                 else if (isdigit(r->in.value_name->name[0])) {
264                         /* we probably have a request for a specific object
265                          * here */
266                         if (!prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL))
267                                 return WERR_NOMEM;
268                         status = reg_perfcount_get_hkpd(
269                                 &prs_hkpd, *r->in.data_size, &outbuf_size,
270                                 r->in.value_name->name);
271                         outbuf = (uint8_t *)prs_hkpd.data_p;
272                         free_prs = True;
273                 }
274                 else {
275                         DEBUG(3,("Unsupported key name [%s] for HKPD.\n",
276                                  r->in.value_name->name));
277                         return WERR_BADFILE;
278                 }
279
280                 *r->out.type = REG_BINARY;
281         }
282         else {
283                 struct registry_value *val;
284
285                 status = reg_queryvalue(p->mem_ctx, regkey, r->in.value_name->name,
286                                         &val);
287                 if (!W_ERROR_IS_OK(status)) {
288
289                         DEBUG(10,("_winreg_QueryValue: reg_queryvalue failed with: %s\n",
290                                 win_errstr(status)));
291
292                         if (r->out.data_size) {
293                                 *r->out.data_size = 0;
294                         }
295                         if (r->out.data_length) {
296                                 *r->out.data_length = 0;
297                         }
298                         return status;
299                 }
300
301                 status = registry_push_value(p->mem_ctx, val, &val_blob);
302                 if (!W_ERROR_IS_OK(status)) {
303                         return status;
304                 }
305
306                 outbuf = val_blob.data;
307                 outbuf_size = val_blob.length;
308                 *r->out.type = val->type;
309         }
310
311         status = WERR_BADFILE;
312
313         if (*r->in.data_size < outbuf_size) {
314                 *r->out.data_size = outbuf_size;
315                 status = r->in.data ? WERR_MORE_DATA : WERR_OK;
316         } else {
317                 *r->out.data_length = outbuf_size;
318                 *r->out.data_size = outbuf_size;
319                 memcpy(r->out.data, outbuf, outbuf_size);
320                 status = WERR_OK;
321         }
322
323         if (free_prs) prs_mem_free(&prs_hkpd);
324         if (free_buf) SAFE_FREE(outbuf);
325
326         return status;
327 }
328
329 /*****************************************************************************
330  _winreg_QueryInfoKey
331  ****************************************************************************/
332
333 WERROR _winreg_QueryInfoKey(pipes_struct *p, struct winreg_QueryInfoKey *r)
334 {
335         WERROR  status = WERR_OK;
336         struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
337
338         if ( !regkey )
339                 return WERR_BADFID;
340
341         r->out.classname->name = NULL;
342
343         status = reg_queryinfokey(regkey, r->out.num_subkeys, r->out.max_subkeylen,
344                                   r->out.max_classlen, r->out.num_values, r->out.max_valnamelen,
345                                   r->out.max_valbufsize, r->out.secdescsize,
346                                   r->out.last_changed_time);
347         if (!W_ERROR_IS_OK(status)) {
348                 return status;
349         }
350
351         /*
352          * These calculations account for the registry buffers being
353          * UTF-16. They are inexact at best, but so far they worked.
354          */
355
356         *r->out.max_subkeylen *= 2;
357
358         *r->out.max_valnamelen += 1;
359         *r->out.max_valnamelen *= 2;
360
361         return WERR_OK;
362 }
363
364
365 /*****************************************************************************
366  _winreg_GetVersion
367  ****************************************************************************/
368
369 WERROR _winreg_GetVersion(pipes_struct *p, struct winreg_GetVersion *r)
370 {
371         struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
372
373         if ( !regkey )
374                 return WERR_BADFID;
375
376         return reg_getversion(r->out.version);
377 }
378
379
380 /*****************************************************************************
381  _winreg_EnumKey
382  ****************************************************************************/
383
384 WERROR _winreg_EnumKey(pipes_struct *p, struct winreg_EnumKey *r)
385 {
386         WERROR err;
387         struct registry_key *key = find_regkey_by_hnd( p, r->in.handle );
388
389         if ( !key )
390                 return WERR_BADFID;
391
392         if ( !r->in.name || !r->in.keyclass )
393                 return WERR_INVALID_PARAM;
394
395         DEBUG(8,("_winreg_EnumKey: enumerating key [%s]\n", key->key->name));
396
397         err = reg_enumkey(p->mem_ctx, key, r->in.enum_index, (char **)&r->out.name->name,
398                           r->out.last_changed_time);
399         if (!W_ERROR_IS_OK(err)) {
400                 return err;
401         }
402         r->out.keyclass->name = "";
403         return WERR_OK;
404 }
405
406 /*****************************************************************************
407  _winreg_EnumValue
408  ****************************************************************************/
409
410 WERROR _winreg_EnumValue(pipes_struct *p, struct winreg_EnumValue *r)
411 {
412         WERROR err;
413         struct registry_key *key = find_regkey_by_hnd( p, r->in.handle );
414         char *valname;
415         struct registry_value *val;
416         DATA_BLOB value_blob;
417
418         if ( !key )
419                 return WERR_BADFID;
420
421         if ( !r->in.name )
422                 return WERR_INVALID_PARAM;
423
424         DEBUG(8,("_winreg_EnumValue: enumerating values for key [%s]\n",
425                  key->key->name));
426
427         err = reg_enumvalue(p->mem_ctx, key, r->in.enum_index, &valname, &val);
428         if (!W_ERROR_IS_OK(err)) {
429                 return err;
430         }
431
432         err = registry_push_value(p->mem_ctx, val, &value_blob);
433         if (!W_ERROR_IS_OK(err)) {
434                 return err;
435         }
436
437         if (r->out.name != NULL) {
438                 r->out.name->name = valname;
439         }
440
441         if (r->out.type != NULL) {
442                 *r->out.type = val->type;
443         }
444
445         if (r->out.value != NULL) {
446                 if ((r->out.size == NULL) || (r->out.length == NULL)) {
447                         return WERR_INVALID_PARAM;
448                 }
449
450                 if (value_blob.length > *r->out.size) {
451                         return WERR_MORE_DATA;
452                 }
453
454                 memcpy( r->out.value, value_blob.data, value_blob.length );
455         }
456
457         if (r->out.length != NULL) {
458                 *r->out.length = value_blob.length;
459         }
460         if (r->out.size != NULL) {
461                 *r->out.size = value_blob.length;
462         }
463
464         return WERR_OK;
465 }
466
467 /*******************************************************************
468  _winreg_InitiateSystemShutdown
469  ********************************************************************/
470
471 WERROR _winreg_InitiateSystemShutdown(pipes_struct *p, struct winreg_InitiateSystemShutdown *r)
472 {
473         struct winreg_InitiateSystemShutdownEx s;
474
475         s.in.hostname = r->in.hostname;
476         s.in.message = r->in.message;
477         s.in.timeout = r->in.timeout;
478         s.in.force_apps = r->in.force_apps;
479         s.in.do_reboot = r->in.do_reboot;
480         s.in.reason = 0;
481
482         /* thunk down to _winreg_InitiateSystemShutdownEx()
483            (just returns a status) */
484
485         return _winreg_InitiateSystemShutdownEx( p, &s );
486 }
487
488 /*******************************************************************
489  _winreg_InitiateSystemShutdownEx
490  ********************************************************************/
491
492 #define SHUTDOWN_R_STRING "-r"
493 #define SHUTDOWN_F_STRING "-f"
494
495
496 WERROR _winreg_InitiateSystemShutdownEx(pipes_struct *p, struct winreg_InitiateSystemShutdownEx *r)
497 {
498         char *shutdown_script = NULL;
499         char *msg = NULL;
500         char *chkmsg = NULL;
501         fstring str_timeout;
502         fstring str_reason;
503         fstring do_reboot;
504         fstring f;
505         int ret;
506         bool can_shutdown;
507
508         shutdown_script = talloc_strdup(p->mem_ctx, lp_shutdown_script());
509         if (!shutdown_script) {
510                 return WERR_NOMEM;
511         }
512         if (!*shutdown_script) {
513                 return WERR_ACCESS_DENIED;
514         }
515
516         /* pull the message string and perform necessary sanity checks on it */
517
518         if ( r->in.message && r->in.message->string ) {
519                 if ( (msg = talloc_strdup(p->mem_ctx, r->in.message->string )) == NULL ) {
520                         return WERR_NOMEM;
521                 }
522                 chkmsg = TALLOC_ARRAY(p->mem_ctx, char, strlen(msg)+1);
523                 if (!chkmsg) {
524                         return WERR_NOMEM;
525                 }
526                 alpha_strcpy(chkmsg, msg, NULL, strlen(msg)+1);
527         }
528
529         fstr_sprintf(str_timeout, "%d", r->in.timeout);
530         fstr_sprintf(do_reboot, r->in.do_reboot ? SHUTDOWN_R_STRING : "");
531         fstr_sprintf(f, r->in.force_apps ? SHUTDOWN_F_STRING : "");
532         fstr_sprintf(str_reason, "%d", r->in.reason );
533
534         shutdown_script = talloc_all_string_sub(p->mem_ctx,
535                                 shutdown_script, "%z", chkmsg ? chkmsg : "");
536         if (!shutdown_script) {
537                 return WERR_NOMEM;
538         }
539         shutdown_script = talloc_all_string_sub(p->mem_ctx,
540                                         shutdown_script, "%t", str_timeout);
541         if (!shutdown_script) {
542                 return WERR_NOMEM;
543         }
544         shutdown_script = talloc_all_string_sub(p->mem_ctx,
545                                                 shutdown_script, "%r", do_reboot);
546         if (!shutdown_script) {
547                 return WERR_NOMEM;
548         }
549         shutdown_script = talloc_all_string_sub(p->mem_ctx,
550                                                 shutdown_script, "%f", f);
551         if (!shutdown_script) {
552                 return WERR_NOMEM;
553         }
554         shutdown_script = talloc_all_string_sub(p->mem_ctx,
555                                         shutdown_script, "%x", str_reason);
556         if (!shutdown_script) {
557                 return WERR_NOMEM;
558         }
559
560         can_shutdown = user_has_privileges( p->server_info->ptok,
561                                             &se_remote_shutdown );
562
563         /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
564            Take the error return from the script and provide it as the Windows return code. */
565
566         /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
567
568         if ( can_shutdown )
569                 become_root();
570
571         ret = smbrun( shutdown_script, NULL );
572
573         if ( can_shutdown )
574                 unbecome_root();
575
576         /********** END SeRemoteShutdownPrivilege BLOCK **********/
577
578         DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
579                 shutdown_script, ret));
580
581         return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
582 }
583
584 /*******************************************************************
585  _winreg_AbortSystemShutdown
586  ********************************************************************/
587
588 WERROR _winreg_AbortSystemShutdown(pipes_struct *p, struct winreg_AbortSystemShutdown *r)
589 {
590         const char *abort_shutdown_script;
591         int ret;
592         bool can_shutdown;
593
594         abort_shutdown_script = lp_abort_shutdown_script();
595
596         if (!*abort_shutdown_script)
597                 return WERR_ACCESS_DENIED;
598
599         can_shutdown = user_has_privileges( p->server_info->ptok,
600                                             &se_remote_shutdown );
601
602         /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
603
604         if ( can_shutdown )
605                 become_root();
606
607         ret = smbrun( abort_shutdown_script, NULL );
608
609         if ( can_shutdown )
610                 unbecome_root();
611
612         /********** END SeRemoteShutdownPrivilege BLOCK **********/
613
614         DEBUG(3,("_winreg_AbortSystemShutdown: Running the command `%s' gave %d\n",
615                 abort_shutdown_script, ret));
616
617         return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
618 }
619
620 /*******************************************************************
621  ********************************************************************/
622
623 static int validate_reg_filename(TALLOC_CTX *ctx, char **pp_fname )
624 {
625         char *p = NULL;
626         int num_services = lp_numservices();
627         int snum = -1;
628         const char *share_path;
629         char *fname = *pp_fname;
630
631         /* convert to a unix path, stripping the C:\ along the way */
632
633         if (!(p = valid_share_pathname(ctx, fname))) {
634                 return -1;
635         }
636
637         /* has to exist within a valid file share */
638
639         for (snum=0; snum<num_services; snum++) {
640                 if (!lp_snum_ok(snum) || lp_print_ok(snum)) {
641                         continue;
642                 }
643
644                 share_path = lp_pathname(snum);
645
646                 /* make sure we have a path (e.g. [homes] ) */
647                 if (strlen(share_path) == 0) {
648                         continue;
649                 }
650
651                 if (strncmp(share_path, p, strlen(share_path)) == 0) {
652                         break;
653                 }
654         }
655
656         *pp_fname = p;
657         return (snum < num_services) ? snum : -1;
658 }
659
660 /*******************************************************************
661  _winreg_RestoreKey
662  ********************************************************************/
663
664 WERROR _winreg_RestoreKey(pipes_struct *p, struct winreg_RestoreKey *r)
665 {
666         struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
667         char *fname = NULL;
668         int             snum;
669
670         if ( !regkey )
671                 return WERR_BADFID;
672
673         if ( !r->in.filename || !r->in.filename->name )
674                 return WERR_INVALID_PARAM;
675
676         fname = talloc_strdup(p->mem_ctx, r->in.filename->name);
677         if (!fname) {
678                 return WERR_NOMEM;
679         }
680
681         DEBUG(8,("_winreg_RestoreKey: verifying restore of key [%s] from "
682                  "\"%s\"\n", regkey->key->name, fname));
683
684         if ((snum = validate_reg_filename(p->mem_ctx, &fname)) == -1)
685                 return WERR_OBJECT_PATH_INVALID;
686
687         /* user must posses SeRestorePrivilege for this this proceed */
688
689         if ( !user_has_privileges( p->server_info->ptok, &se_restore ) )
690                 return WERR_ACCESS_DENIED;
691
692         DEBUG(2,("_winreg_RestoreKey: Restoring [%s] from %s in share %s\n",
693                  regkey->key->name, fname, lp_servicename(snum) ));
694
695         return reg_restorekey(regkey, fname);
696 }
697
698 /*******************************************************************
699  _winreg_SaveKey
700  ********************************************************************/
701
702 WERROR _winreg_SaveKey(pipes_struct *p, struct winreg_SaveKey *r)
703 {
704         struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
705         char *fname = NULL;
706         int snum = -1;
707
708         if ( !regkey )
709                 return WERR_BADFID;
710
711         if ( !r->in.filename || !r->in.filename->name )
712                 return WERR_INVALID_PARAM;
713
714         fname = talloc_strdup(p->mem_ctx, r->in.filename->name);
715         if (!fname) {
716                 return WERR_NOMEM;
717         }
718
719         DEBUG(8,("_winreg_SaveKey: verifying backup of key [%s] to \"%s\"\n",
720                  regkey->key->name, fname));
721
722         if ((snum = validate_reg_filename(p->mem_ctx, &fname)) == -1 )
723                 return WERR_OBJECT_PATH_INVALID;
724
725         DEBUG(2,("_winreg_SaveKey: Saving [%s] to %s in share %s\n",
726                  regkey->key->name, fname, lp_servicename(snum) ));
727
728         return reg_savekey(regkey, fname);
729 }
730
731 /*******************************************************************
732  _winreg_SaveKeyEx
733  ********************************************************************/
734
735 WERROR _winreg_SaveKeyEx(pipes_struct *p, struct winreg_SaveKeyEx *r)
736 {
737         /* fill in your code here if you think this call should
738            do anything */
739
740         p->rng_fault_state = True;
741         return WERR_NOT_SUPPORTED;
742 }
743
744 /*******************************************************************
745  _winreg_CreateKey
746  ********************************************************************/
747
748 WERROR _winreg_CreateKey( pipes_struct *p, struct winreg_CreateKey *r)
749 {
750         struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
751         struct registry_key *new_key;
752         WERROR result;
753
754         if ( !parent )
755                 return WERR_BADFID;
756
757         DEBUG(10, ("_winreg_CreateKey called with parent key '%s' and "
758                    "subkey name '%s'\n", parent->key->name, r->in.name.name));
759
760         result = reg_createkey(NULL, parent, r->in.name.name, r->in.access_mask,
761                                &new_key, r->out.action_taken);
762         if (!W_ERROR_IS_OK(result)) {
763                 return result;
764         }
765
766         if (!create_policy_hnd(p, r->out.new_handle, new_key)) {
767                 TALLOC_FREE(new_key);
768                 return WERR_BADFILE;
769         }
770
771         return WERR_OK;
772 }
773
774 /*******************************************************************
775  _winreg_SetValue
776  ********************************************************************/
777
778 WERROR _winreg_SetValue(pipes_struct *p, struct winreg_SetValue *r)
779 {
780         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
781         struct registry_value *val;
782         WERROR status;
783
784         if ( !key )
785                 return WERR_BADFID;
786
787         DEBUG(8,("_winreg_SetValue: Setting value for [%s:%s]\n",
788                          key->key->name, r->in.name.name));
789
790         status = registry_pull_value(p->mem_ctx, &val, r->in.type, r->in.data,
791                                                                  r->in.size, r->in.size);
792         if (!W_ERROR_IS_OK(status)) {
793                 return status;
794         }
795
796         return reg_setvalue(key, r->in.name.name, val);
797 }
798
799 /*******************************************************************
800  _winreg_DeleteKey
801  ********************************************************************/
802
803 WERROR _winreg_DeleteKey(pipes_struct *p, struct winreg_DeleteKey *r)
804 {
805         struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
806
807         if ( !parent )
808                 return WERR_BADFID;
809
810         return reg_deletekey(parent, r->in.key.name);
811 }
812
813
814 /*******************************************************************
815  _winreg_DeleteValue
816  ********************************************************************/
817
818 WERROR _winreg_DeleteValue(pipes_struct *p, struct winreg_DeleteValue *r)
819 {
820         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
821
822         if ( !key )
823                 return WERR_BADFID;
824
825         return reg_deletevalue(key, r->in.value.name);
826 }
827
828 /*******************************************************************
829  _winreg_GetKeySecurity
830  ********************************************************************/
831
832 WERROR _winreg_GetKeySecurity(pipes_struct *p, struct winreg_GetKeySecurity *r)
833 {
834         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
835         WERROR err;
836         struct security_descriptor *secdesc;
837         uint8 *data;
838         size_t len;
839
840         if ( !key )
841                 return WERR_BADFID;
842
843         /* access checks first */
844
845         if ( !(key->key->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
846                 return WERR_ACCESS_DENIED;
847
848         err = reg_getkeysecurity(p->mem_ctx, key, &secdesc);
849         if (!W_ERROR_IS_OK(err)) {
850                 return err;
851         }
852
853         err = ntstatus_to_werror(marshall_sec_desc(p->mem_ctx, secdesc,
854                                                    &data, &len));
855         if (!W_ERROR_IS_OK(err)) {
856                 return err;
857         }
858
859         if (len > r->out.sd->size) {
860                 r->out.sd->size = len;
861                 return WERR_INSUFFICIENT_BUFFER;
862         }
863
864         r->out.sd->size = len;
865         r->out.sd->len = len;
866         r->out.sd->data = data;
867
868         return WERR_OK;
869 }
870
871 /*******************************************************************
872  _winreg_SetKeySecurity
873  ********************************************************************/
874
875 WERROR _winreg_SetKeySecurity(pipes_struct *p, struct winreg_SetKeySecurity *r)
876 {
877         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
878         struct security_descriptor *secdesc;
879         WERROR err;
880
881         if ( !key )
882                 return WERR_BADFID;
883
884         /* access checks first */
885
886         if ( !(key->key->access_granted & STD_RIGHT_WRITE_DAC_ACCESS) )
887                 return WERR_ACCESS_DENIED;
888
889         err = ntstatus_to_werror(unmarshall_sec_desc(p->mem_ctx, r->in.sd->data,
890                                                      r->in.sd->len, &secdesc));
891         if (!W_ERROR_IS_OK(err)) {
892                 return err;
893         }
894
895         return reg_setkeysecurity(key, secdesc);
896 }
897
898 /*******************************************************************
899  _winreg_FlushKey
900  ********************************************************************/
901
902 WERROR _winreg_FlushKey(pipes_struct *p, struct winreg_FlushKey *r)
903 {
904         /* I'm just replying OK because there's not a lot
905            here I see to do i  --jerry */
906
907         return WERR_OK;
908 }
909
910 /*******************************************************************
911  _winreg_UnLoadKey
912  ********************************************************************/
913
914 WERROR _winreg_UnLoadKey(pipes_struct *p, struct winreg_UnLoadKey *r)
915 {
916         /* fill in your code here if you think this call should
917            do anything */
918
919         p->rng_fault_state = True;
920         return WERR_NOT_SUPPORTED;
921 }
922
923 /*******************************************************************
924  _winreg_ReplaceKey
925  ********************************************************************/
926
927 WERROR _winreg_ReplaceKey(pipes_struct *p, struct winreg_ReplaceKey *r)
928 {
929         /* fill in your code here if you think this call should
930            do anything */
931
932         p->rng_fault_state = True;
933         return WERR_NOT_SUPPORTED;
934 }
935
936 /*******************************************************************
937  _winreg_LoadKey
938  ********************************************************************/
939
940 WERROR _winreg_LoadKey(pipes_struct *p, struct winreg_LoadKey *r)
941 {
942         /* fill in your code here if you think this call should
943            do anything */
944
945         p->rng_fault_state = True;
946         return WERR_NOT_SUPPORTED;
947 }
948
949 /*******************************************************************
950  _winreg_NotifyChangeKeyValue
951  ********************************************************************/
952
953 WERROR _winreg_NotifyChangeKeyValue(pipes_struct *p, struct winreg_NotifyChangeKeyValue *r)
954 {
955         /* fill in your code here if you think this call should
956            do anything */
957
958         p->rng_fault_state = True;
959         return WERR_NOT_SUPPORTED;
960 }
961
962 /*******************************************************************
963  _winreg_QueryMultipleValues
964  ********************************************************************/
965
966 WERROR _winreg_QueryMultipleValues(pipes_struct *p, struct winreg_QueryMultipleValues *r)
967 {
968         /* fill in your code here if you think this call should
969            do anything */
970
971         p->rng_fault_state = True;
972         return WERR_NOT_SUPPORTED;
973 }
974
975 /*******************************************************************
976  _winreg_QueryMultipleValues2
977  ********************************************************************/
978
979 WERROR _winreg_QueryMultipleValues2(pipes_struct *p, struct winreg_QueryMultipleValues2 *r)
980 {
981         /* fill in your code here if you think this call should
982            do anything */
983
984         p->rng_fault_state = True;
985         return WERR_NOT_SUPPORTED;
986 }
987