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