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