Merge branch 'master' of ssh://git.samba.org/data/git/samba
[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->server_info->ptok, &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->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  reg_abort_shutdwon
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  ********************************************************************/
661
662 WERROR _winreg_RestoreKey(pipes_struct *p, struct winreg_RestoreKey *r)
663 {
664         struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
665         char *fname = NULL;
666         int             snum;
667
668         if ( !regkey )
669                 return WERR_BADFID;
670
671         if ( !r->in.filename || !r->in.filename->name )
672                 return WERR_INVALID_PARAM;
673
674         fname = talloc_strdup(p->mem_ctx, r->in.filename->name);
675         if (!fname) {
676                 return WERR_NOMEM;
677         }
678
679         DEBUG(8,("_winreg_RestoreKey: verifying restore of key [%s] from "
680                  "\"%s\"\n", regkey->key->name, fname));
681
682         if ((snum = validate_reg_filename(p->mem_ctx, &fname)) == -1)
683                 return WERR_OBJECT_PATH_INVALID;
684
685         /* user must posses SeRestorePrivilege for this this proceed */
686
687         if ( !user_has_privileges( p->server_info->ptok, &se_restore ) )
688                 return WERR_ACCESS_DENIED;
689
690         DEBUG(2,("_winreg_RestoreKey: Restoring [%s] from %s in share %s\n",
691                  regkey->key->name, fname, lp_servicename(snum) ));
692
693         return reg_restorekey(regkey, fname);
694 }
695
696 WERROR _winreg_SaveKey(pipes_struct *p, struct winreg_SaveKey *r)
697 {
698         struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
699         char *fname = NULL;
700         int snum = -1;
701
702         if ( !regkey )
703                 return WERR_BADFID;
704
705         if ( !r->in.filename || !r->in.filename->name )
706                 return WERR_INVALID_PARAM;
707
708         fname = talloc_strdup(p->mem_ctx, r->in.filename->name);
709         if (!fname) {
710                 return WERR_NOMEM;
711         }
712
713         DEBUG(8,("_winreg_SaveKey: verifying backup of key [%s] to \"%s\"\n",
714                  regkey->key->name, fname));
715
716         if ((snum = validate_reg_filename(p->mem_ctx, &fname)) == -1 )
717                 return WERR_OBJECT_PATH_INVALID;
718
719         DEBUG(2,("_winreg_SaveKey: Saving [%s] to %s in share %s\n",
720                  regkey->key->name, fname, lp_servicename(snum) ));
721
722         return reg_savekey(regkey, fname);
723 }
724
725 /*******************************************************************
726  ********************************************************************/
727
728 WERROR _winreg_SaveKeyEx(pipes_struct *p, struct winreg_SaveKeyEx *r)
729 {
730         /* fill in your code here if you think this call should
731            do anything */
732
733         p->rng_fault_state = True;
734         return WERR_NOT_SUPPORTED;
735 }
736
737 /*******************************************************************
738  ********************************************************************/
739
740 WERROR _winreg_CreateKey( pipes_struct *p, struct winreg_CreateKey *r)
741 {
742         struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
743         struct registry_key *new_key;
744         WERROR result;
745
746         if ( !parent )
747                 return WERR_BADFID;
748
749         DEBUG(10, ("_winreg_CreateKey called with parent key '%s' and "
750                    "subkey name '%s'\n", parent->key->name, r->in.name.name));
751
752         result = reg_createkey(NULL, parent, r->in.name.name, r->in.access_mask,
753                                &new_key, r->out.action_taken);
754         if (!W_ERROR_IS_OK(result)) {
755                 return result;
756         }
757
758         if (!create_policy_hnd(p, r->out.new_handle, free_regkey, new_key)) {
759                 TALLOC_FREE(new_key);
760                 return WERR_BADFILE;
761         }
762
763         return WERR_OK;
764 }
765
766 /*******************************************************************
767  ********************************************************************/
768
769 WERROR _winreg_SetValue(pipes_struct *p, struct winreg_SetValue *r)
770 {
771         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
772         struct registry_value *val;
773         WERROR status;
774
775         if ( !key )
776                 return WERR_BADFID;
777
778         DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n", 
779                          key->key->name, r->in.name.name));
780
781         status = registry_pull_value(p->mem_ctx, &val, r->in.type, r->in.data, 
782                                                                  r->in.size, r->in.size);
783         if (!W_ERROR_IS_OK(status)) {
784                 return status;
785         }
786
787         return reg_setvalue(key, r->in.name.name, val);
788 }
789
790 /*******************************************************************
791  ********************************************************************/
792
793 WERROR _winreg_DeleteKey(pipes_struct *p, struct winreg_DeleteKey *r)
794 {
795         struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
796
797         if ( !parent )
798                 return WERR_BADFID;
799
800         return reg_deletekey(parent, r->in.key.name);
801 }
802
803
804 /*******************************************************************
805  ********************************************************************/
806
807 WERROR _winreg_DeleteValue(pipes_struct *p, struct winreg_DeleteValue *r)
808 {
809         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
810         
811         if ( !key )
812                 return WERR_BADFID;
813
814         return reg_deletevalue(key, r->in.value.name);
815 }
816
817 /*******************************************************************
818  ********************************************************************/
819
820 WERROR _winreg_GetKeySecurity(pipes_struct *p, struct winreg_GetKeySecurity *r)
821 {
822         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
823         WERROR err;
824         struct security_descriptor *secdesc;
825         uint8 *data;
826         size_t len;
827
828         if ( !key )
829                 return WERR_BADFID;
830                 
831         /* access checks first */
832         
833         if ( !(key->key->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
834                 return WERR_ACCESS_DENIED;
835
836         err = reg_getkeysecurity(p->mem_ctx, key, &secdesc);
837         if (!W_ERROR_IS_OK(err)) {
838                 return err;
839         }
840
841         err = ntstatus_to_werror(marshall_sec_desc(p->mem_ctx, secdesc,
842                                                    &data, &len));
843         if (!W_ERROR_IS_OK(err)) {
844                 return err;
845         }
846
847         if (len > r->out.sd->size) {
848                 r->out.sd->size = len;
849                 return WERR_INSUFFICIENT_BUFFER;
850         }
851
852         r->out.sd->size = len;
853         r->out.sd->len = len;
854         r->out.sd->data = data;
855                 
856         return WERR_OK;
857 }
858
859 /*******************************************************************
860  ********************************************************************/
861
862 WERROR _winreg_SetKeySecurity(pipes_struct *p, struct winreg_SetKeySecurity *r)
863 {
864         struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
865         struct security_descriptor *secdesc;
866         WERROR err;
867
868         if ( !key )
869                 return WERR_BADFID;
870                 
871         /* access checks first */
872         
873         if ( !(key->key->access_granted & STD_RIGHT_WRITE_DAC_ACCESS) )
874                 return WERR_ACCESS_DENIED;
875
876         err = ntstatus_to_werror(unmarshall_sec_desc(p->mem_ctx, r->in.sd->data,
877                                                      r->in.sd->len, &secdesc));
878         if (!W_ERROR_IS_OK(err)) {
879                 return err;
880         }
881
882         return reg_setkeysecurity(key, secdesc);
883 }
884
885 /*******************************************************************
886  ********************************************************************/
887
888 WERROR _winreg_FlushKey(pipes_struct *p, struct winreg_FlushKey *r)
889 {
890         /* I'm just replying OK because there's not a lot 
891            here I see to do i  --jerry */
892         
893         return WERR_OK;
894 }
895
896 /*******************************************************************
897  ********************************************************************/
898
899 WERROR _winreg_UnLoadKey(pipes_struct *p, struct winreg_UnLoadKey *r)
900 {
901         /* fill in your code here if you think this call should
902            do anything */
903
904         p->rng_fault_state = True;
905         return WERR_NOT_SUPPORTED;
906 }
907
908 /*******************************************************************
909  ********************************************************************/
910
911 WERROR _winreg_ReplaceKey(pipes_struct *p, struct winreg_ReplaceKey *r)
912 {
913         /* fill in your code here if you think this call should
914            do anything */
915
916         p->rng_fault_state = True;
917         return WERR_NOT_SUPPORTED;
918 }
919
920 /*******************************************************************
921  ********************************************************************/
922
923 WERROR _winreg_LoadKey(pipes_struct *p, struct winreg_LoadKey *r)
924 {
925         /* fill in your code here if you think this call should
926            do anything */
927
928         p->rng_fault_state = True;
929         return WERR_NOT_SUPPORTED;
930 }
931
932 /*******************************************************************
933  ********************************************************************/
934
935 WERROR _winreg_NotifyChangeKeyValue(pipes_struct *p, struct winreg_NotifyChangeKeyValue *r)
936 {
937         /* fill in your code here if you think this call should
938            do anything */
939
940         p->rng_fault_state = True;
941         return WERR_NOT_SUPPORTED;
942 }
943
944 /*******************************************************************
945  ********************************************************************/
946
947 WERROR _winreg_QueryMultipleValues(pipes_struct *p, struct winreg_QueryMultipleValues *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  ********************************************************************/
958
959 WERROR _winreg_QueryMultipleValues2(pipes_struct *p, struct winreg_QueryMultipleValues2 *r)
960 {
961         /* fill in your code here if you think this call should
962            do anything */
963
964         p->rng_fault_state = True;
965         return WERR_NOT_SUPPORTED;
966 }
967