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