Merge branch 'selftest' of git://git.samba.org/jelmer/samba
[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
25 #undef DBGC_CLASS
26 #define DBGC_CLASS DBGC_RPC_SRV
27
28 /******************************************************************
29  free() function for struct registry_key
30  *****************************************************************/
31  
32 static void free_regkey(void *ptr)
33 {
34         struct registry_key *key = (struct registry_key *)ptr;
35         TALLOC_FREE(key);
36 }
37
38 /******************************************************************
39  Find a registry key handle and return a struct registry_key *
40  *****************************************************************/
41
42 static struct registry_key *find_regkey_by_hnd(pipes_struct *p,
43                                                POLICY_HND *hnd)
44 {
45         struct registry_key *regkey = NULL;
46
47         if(!find_policy_by_hnd(p,hnd,(void **)(void *)&regkey)) {
48                 DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: "));
49                 return NULL;
50         }
51
52         return regkey;
53 }
54
55 /*******************************************************************
56  Function for open a new registry handle and creating a handle 
57  Note that P should be valid & hnd should already have space
58  
59  When we open a key, we store the full path to the key as 
60  HK[LM|U]\<key>\<key>\...
61  *******************************************************************/
62  
63 static WERROR open_registry_key( pipes_struct *p, POLICY_HND *hnd, 
64                                  struct registry_key *parent,
65                                  const char *subkeyname,
66                                  uint32 access_desired  )
67 {
68         WERROR result = WERR_OK;
69         struct registry_key *key;
70
71         if (parent == NULL) {
72                 result = reg_openhive(NULL, subkeyname, access_desired,
73                                       p->pipe_user.nt_user_token, &key);
74         }
75         else {
76                 result = reg_openkey(NULL, parent, subkeyname, access_desired,
77                                      &key);
78         }
79
80         if ( !W_ERROR_IS_OK(result) ) {
81                 return result;
82         }
83         
84         if ( !create_policy_hnd( p, hnd, free_regkey, key ) ) {
85                 return WERR_BADFILE; 
86         }
87         
88         return WERR_OK;
89 }
90
91 /*******************************************************************
92  Function for open a new registry handle and creating a handle 
93  Note that P should be valid & hnd should already have space
94  *******************************************************************/
95
96 static bool close_registry_key(pipes_struct *p, POLICY_HND *hnd)
97 {
98         struct registry_key *regkey = find_regkey_by_hnd(p, hnd);
99         
100         if ( !regkey ) {
101                 DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n",
102                          OUR_HANDLE(hnd)));
103                 return False;
104         }
105         
106         close_policy_hnd(p, hnd);
107         
108         return True;
109 }
110
111 /********************************************************************
112  reg_close
113  ********************************************************************/
114
115 WERROR _winreg_CloseKey(pipes_struct *p, struct winreg_CloseKey *r)
116 {
117         /* close the policy handle */
118
119         if (!close_registry_key(p, r->in.handle))
120                 return WERR_BADFID; 
121
122         ZERO_STRUCTP(r->out.handle);
123
124         return WERR_OK;
125 }
126
127 /*******************************************************************
128  ********************************************************************/
129
130 WERROR _winreg_OpenHKLM(pipes_struct *p, struct winreg_OpenHKLM *r)
131 {
132         return open_registry_key(p, r->out.handle, NULL, KEY_HKLM, r->in.access_mask);
133 }
134
135 /*******************************************************************
136  ********************************************************************/
137
138 WERROR _winreg_OpenHKPD(pipes_struct *p, struct winreg_OpenHKPD *r)
139 {
140         return open_registry_key(p, r->out.handle, NULL, KEY_HKPD, r->in.access_mask);
141 }
142
143 /*******************************************************************
144  ********************************************************************/
145
146 WERROR _winreg_OpenHKPT(pipes_struct *p, struct winreg_OpenHKPT *r)
147 {
148         return open_registry_key(p, r->out.handle, NULL, KEY_HKPT, r->in.access_mask);
149 }
150
151 /*******************************************************************
152  ********************************************************************/
153
154 WERROR _winreg_OpenHKCR(pipes_struct *p, struct winreg_OpenHKCR *r)
155 {
156         return open_registry_key(p, r->out.handle, NULL, KEY_HKCR, r->in.access_mask);
157 }
158
159 /*******************************************************************
160  ********************************************************************/
161
162 WERROR _winreg_OpenHKU(pipes_struct *p, struct winreg_OpenHKU *r)
163 {
164         return open_registry_key(p, r->out.handle, NULL, KEY_HKU, r->in.access_mask);
165 }
166
167 /*******************************************************************
168  ********************************************************************/
169
170 WERROR _winreg_OpenHKCU(pipes_struct *p, struct winreg_OpenHKCU *r)
171 {
172         return open_registry_key(p, r->out.handle, NULL, KEY_HKCU, r->in.access_mask);
173 }
174
175 /*******************************************************************
176  ********************************************************************/
177
178 WERROR _winreg_OpenHKCC(pipes_struct *p, struct winreg_OpenHKCC *r)
179 {
180         return open_registry_key(p, r->out.handle, NULL, KEY_HKCC, r->in.access_mask);
181 }
182
183 /*******************************************************************
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  ********************************************************************/
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  reg_reply_open_entry
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  reg_reply_info
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  Implementation of REG_QUERY_KEY
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  Implementation of REG_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  Implementation of REG_ENUM_KEY
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  Implementation of REG_ENUM_VALUE
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  reg_shutdwon
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  reg_shutdown_ex
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->pipe_user.nt_user_token, &se_remote_shutdown );
560
561         /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
562            Take the error return from the script and provide it as the Windows return code. */
563
564         /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
565
566         if ( can_shutdown )
567                 become_root();
568
569         ret = smbrun( shutdown_script, NULL );
570
571         if ( can_shutdown )
572                 unbecome_root();
573
574         /********** END SeRemoteShutdownPrivilege BLOCK **********/
575
576         DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
577                 shutdown_script, ret));
578
579         return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
580 }
581
582 /*******************************************************************
583  reg_abort_shutdwon
584  ********************************************************************/
585
586 WERROR _winreg_AbortSystemShutdown(pipes_struct *p, struct winreg_AbortSystemShutdown *r)
587 {
588         const char *abort_shutdown_script;
589         int ret;
590         bool can_shutdown;
591
592         abort_shutdown_script = lp_abort_shutdown_script();
593
594         if (!*abort_shutdown_script)
595                 return WERR_ACCESS_DENIED;
596
597         can_shutdown = user_has_privileges( p->pipe_user.nt_user_token, &se_remote_shutdown );
598
599         /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
600
601         if ( can_shutdown )
602                 become_root();
603
604         ret = smbrun( abort_shutdown_script, NULL );
605
606         if ( can_shutdown )
607                 unbecome_root();
608
609         /********** END SeRemoteShutdownPrivilege BLOCK **********/
610
611         DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",
612                 abort_shutdown_script, ret));
613
614         return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
615 }
616
617 /*******************************************************************
618  ********************************************************************/
619
620 static int validate_reg_filename(TALLOC_CTX *ctx, char **pp_fname )
621 {
622         char *p = NULL;
623         int num_services = lp_numservices();
624         int snum = -1;
625         const char *share_path;
626         char *fname = *pp_fname;
627
628         /* convert to a unix path, stripping the C:\ along the way */
629
630         if (!(p = valid_share_pathname(ctx, fname))) {
631                 return -1;
632         }
633
634         /* has to exist within a valid file share */
635
636         for (snum=0; snum<num_services; snum++) {
637                 if (!lp_snum_ok(snum) || lp_print_ok(snum)) {
638                         continue;
639                 }
640
641                 share_path = lp_pathname(snum);
642
643                 /* make sure we have a path (e.g. [homes] ) */
644                 if (strlen(share_path) == 0) {
645                         continue;
646                 }
647
648                 if (strncmp(share_path, p, strlen(share_path)) == 0) {
649                         break;
650                 }
651         }
652
653         *pp_fname = p;
654         return (snum < num_services) ? snum : -1;
655 }
656
657 /*******************************************************************
658  ********************************************************************/
659
660 WERROR _winreg_RestoreKey(pipes_struct *p, struct winreg_RestoreKey *r)
661 {
662         struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
663         char *fname = NULL;
664         int             snum;
665
666         if ( !regkey )
667                 return WERR_BADFID;
668
669         if ( !r->in.filename || !r->in.filename->name )
670                 return WERR_INVALID_PARAM;
671
672         fname = talloc_strdup(p->mem_ctx, r->in.filename->name);
673         if (!fname) {
674                 return WERR_NOMEM;
675         }
676
677         DEBUG(8,("_winreg_RestoreKey: verifying restore of key [%s] from "
678                  "\"%s\"\n", regkey->key->name, fname));
679
680         if ((snum = validate_reg_filename(p->mem_ctx, &fname)) == -1)
681                 return WERR_OBJECT_PATH_INVALID;
682
683         /* user must posses SeRestorePrivilege for this this proceed */
684
685         if ( !user_has_privileges( p->pipe_user.nt_user_token, &se_restore ) )
686                 return WERR_ACCESS_DENIED;
687
688         DEBUG(2,("_winreg_RestoreKey: Restoring [%s] from %s in share %s\n",
689                  regkey->key->name, fname, lp_servicename(snum) ));
690
691         return reg_restorekey(regkey, fname);
692 }
693
694 WERROR _winreg_SaveKey(pipes_struct *p, struct winreg_SaveKey *r)
695 {
696         struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
697         char *fname = NULL;
698         int snum = -1;
699
700         if ( !regkey )
701                 return WERR_BADFID;
702
703         if ( !r->in.filename || !r->in.filename->name )
704                 return WERR_INVALID_PARAM;
705
706         fname = talloc_strdup(p->mem_ctx, r->in.filename->name);
707         if (!fname) {
708                 return WERR_NOMEM;
709         }
710
711         DEBUG(8,("_winreg_SaveKey: verifying backup of key [%s] to \"%s\"\n",
712                  regkey->key->name, fname));
713
714         if ((snum = validate_reg_filename(p->mem_ctx, &fname)) == -1 )
715                 return WERR_OBJECT_PATH_INVALID;
716
717         DEBUG(2,("_winreg_SaveKey: Saving [%s] to %s in share %s\n",
718                  regkey->key->name, fname, lp_servicename(snum) ));
719
720         return reg_savekey(regkey, fname);
721 }
722
723 /*******************************************************************
724  ********************************************************************/
725
726 WERROR _winreg_SaveKeyEx(pipes_struct *p, struct winreg_SaveKeyEx *r)
727 {
728         /* fill in your code here if you think this call should
729            do anything */
730
731         p->rng_fault_state = True;
732         return WERR_NOT_SUPPORTED;
733 }
734
735 /*******************************************************************
736  ********************************************************************/
737
738 WERROR _winreg_CreateKey( pipes_struct *p, struct winreg_CreateKey *r)
739 {
740         struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
741         struct registry_key *new_key;
742         WERROR result;
743
744         if ( !parent )
745                 return WERR_BADFID;
746
747         DEBUG(10, ("_winreg_CreateKey called with parent key '%s' and "
748                    "subkey name '%s'\n", parent->key->name, r->in.name.name));
749
750         result = reg_createkey(NULL, parent, r->in.name.name, r->in.access_mask,
751                                &new_key, r->out.action_taken);
752         if (!W_ERROR_IS_OK(result)) {
753                 return result;
754         }
755
756         if (!create_policy_hnd(p, r->out.new_handle, free_regkey, new_key)) {
757                 TALLOC_FREE(new_key);
758                 return WERR_BADFILE;
759         }
760
761         return WERR_OK;
762 }
763
764 /*******************************************************************
765  ********************************************************************/
766
767 WERROR _winreg_SetValue(pipes_struct *p, struct winreg_SetValue *r)
768 {
769         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
770         struct registry_value *val;
771         WERROR status;
772
773         if ( !key )
774                 return WERR_BADFID;
775
776         DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n", 
777                          key->key->name, r->in.name.name));
778
779         status = registry_pull_value(p->mem_ctx, &val, r->in.type, r->in.data, 
780                                                                  r->in.size, r->in.size);
781         if (!W_ERROR_IS_OK(status)) {
782                 return status;
783         }
784
785         return reg_setvalue(key, r->in.name.name, val);
786 }
787
788 /*******************************************************************
789  ********************************************************************/
790
791 WERROR _winreg_DeleteKey(pipes_struct *p, struct winreg_DeleteKey *r)
792 {
793         struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
794
795         if ( !parent )
796                 return WERR_BADFID;
797
798         return reg_deletekey(parent, r->in.key.name);
799 }
800
801
802 /*******************************************************************
803  ********************************************************************/
804
805 WERROR _winreg_DeleteValue(pipes_struct *p, struct winreg_DeleteValue *r)
806 {
807         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
808         
809         if ( !key )
810                 return WERR_BADFID;
811
812         return reg_deletevalue(key, r->in.value.name);
813 }
814
815 /*******************************************************************
816  ********************************************************************/
817
818 WERROR _winreg_GetKeySecurity(pipes_struct *p, struct winreg_GetKeySecurity *r)
819 {
820         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
821         WERROR err;
822         struct security_descriptor *secdesc;
823         uint8 *data;
824         size_t len;
825
826         if ( !key )
827                 return WERR_BADFID;
828                 
829         /* access checks first */
830         
831         if ( !(key->key->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
832                 return WERR_ACCESS_DENIED;
833
834         err = reg_getkeysecurity(p->mem_ctx, key, &secdesc);
835         if (!W_ERROR_IS_OK(err)) {
836                 return err;
837         }
838
839         err = ntstatus_to_werror(marshall_sec_desc(p->mem_ctx, secdesc,
840                                                    &data, &len));
841         if (!W_ERROR_IS_OK(err)) {
842                 return err;
843         }
844
845         if (len > r->out.sd->size) {
846                 r->out.sd->size = len;
847                 return WERR_INSUFFICIENT_BUFFER;
848         }
849
850         r->out.sd->size = len;
851         r->out.sd->len = len;
852         r->out.sd->data = data;
853                 
854         return WERR_OK;
855 }
856
857 /*******************************************************************
858  ********************************************************************/
859
860 WERROR _winreg_SetKeySecurity(pipes_struct *p, struct winreg_SetKeySecurity *r)
861 {
862         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
863         struct security_descriptor *secdesc;
864         WERROR err;
865
866         if ( !key )
867                 return WERR_BADFID;
868                 
869         /* access checks first */
870         
871         if ( !(key->key->access_granted & STD_RIGHT_WRITE_DAC_ACCESS) )
872                 return WERR_ACCESS_DENIED;
873
874         err = ntstatus_to_werror(unmarshall_sec_desc(p->mem_ctx, r->in.sd->data,
875                                                      r->in.sd->len, &secdesc));
876         if (!W_ERROR_IS_OK(err)) {
877                 return err;
878         }
879
880         return reg_setkeysecurity(key, secdesc);
881 }
882
883 /*******************************************************************
884  ********************************************************************/
885
886 WERROR _winreg_FlushKey(pipes_struct *p, struct winreg_FlushKey *r)
887 {
888         /* I'm just replying OK because there's not a lot 
889            here I see to do i  --jerry */
890         
891         return WERR_OK;
892 }
893
894 /*******************************************************************
895  ********************************************************************/
896
897 WERROR _winreg_UnLoadKey(pipes_struct *p, struct winreg_UnLoadKey *r)
898 {
899         /* fill in your code here if you think this call should
900            do anything */
901
902         p->rng_fault_state = True;
903         return WERR_NOT_SUPPORTED;
904 }
905
906 /*******************************************************************
907  ********************************************************************/
908
909 WERROR _winreg_ReplaceKey(pipes_struct *p, struct winreg_ReplaceKey *r)
910 {
911         /* fill in your code here if you think this call should
912            do anything */
913
914         p->rng_fault_state = True;
915         return WERR_NOT_SUPPORTED;
916 }
917
918 /*******************************************************************
919  ********************************************************************/
920
921 WERROR _winreg_LoadKey(pipes_struct *p, struct winreg_LoadKey *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  ********************************************************************/
932
933 WERROR _winreg_NotifyChangeKeyValue(pipes_struct *p, struct winreg_NotifyChangeKeyValue *r)
934 {
935         /* fill in your code here if you think this call should
936            do anything */
937
938         p->rng_fault_state = True;
939         return WERR_NOT_SUPPORTED;
940 }
941
942 /*******************************************************************
943  ********************************************************************/
944
945 WERROR _winreg_QueryMultipleValues(pipes_struct *p, struct winreg_QueryMultipleValues *r)
946 {
947         /* fill in your code here if you think this call should
948            do anything */
949
950         p->rng_fault_state = True;
951         return WERR_NOT_SUPPORTED;
952 }
953
954 /*******************************************************************
955  ********************************************************************/
956
957 WERROR _winreg_QueryMultipleValues2(pipes_struct *p, struct winreg_QueryMultipleValues2 *r)
958 {
959         /* fill in your code here if you think this call should
960            do anything */
961
962         p->rng_fault_state = True;
963         return WERR_NOT_SUPPORTED;
964 }
965