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