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