s4-winreg: Fix dcesrv_winreg_CreateKey after rename.
[bbaumbach/samba-autobuild/.git] / source4 / rpc_server / winreg / rpc_winreg.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    endpoint server for the winreg pipe
5
6    Copyright (C) 2004 Jelmer Vernooij, jelmer@samba.org
7    Copyright (C) 2008 Matthias Dieter Wallnöfer, mwallnoefer@yahoo.de
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "rpc_server/dcerpc_server.h"
25 #include "lib/registry/registry.h"
26 #include "librpc/gen_ndr/ndr_winreg.h"
27 #include "librpc/gen_ndr/ndr_security.h"
28 #include "libcli/security/security.h"
29
30 enum handle_types { HTYPE_REGVAL, HTYPE_REGKEY };
31
32 static NTSTATUS dcerpc_winreg_bind(struct dcesrv_call_state *dce_call,
33                                    const struct dcesrv_interface *iface)
34 {
35         struct registry_context *ctx;
36         WERROR err;
37
38         err = reg_open_samba(dce_call->context,
39                              &ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx,
40                              dce_call->conn->auth_state.session_info,
41                              NULL);
42
43         if (!W_ERROR_IS_OK(err)) {
44                 DEBUG(0, ("Error opening registry: %s\n", win_errstr(err)));
45                 return NT_STATUS_UNSUCCESSFUL;
46         }
47
48         dce_call->context->private_data = ctx;
49
50         return NT_STATUS_OK;
51 }
52
53 #define DCESRV_INTERFACE_WINREG_BIND dcerpc_winreg_bind
54
55 static WERROR dcesrv_winreg_openhive(struct dcesrv_call_state *dce_call,
56                                      TALLOC_CTX *mem_ctx, uint32_t hkey,
57                                      struct policy_handle **outh)
58 {
59         struct registry_context *ctx = dce_call->context->private_data;
60         struct dcesrv_handle *h;
61         WERROR result;
62
63         h = dcesrv_handle_new(dce_call->context, HTYPE_REGKEY);
64         W_ERROR_HAVE_NO_MEMORY(h);
65
66         result = reg_get_predefined_key(ctx, hkey,
67                                        (struct registry_key **)&h->data);
68         if (!W_ERROR_IS_OK(result)) {
69                 return result;
70         }
71         *outh = &h->wire_handle;
72
73         return result;
74 }
75
76 #define func_winreg_OpenHive(k,n) static WERROR dcesrv_winreg_Open ## k (struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct winreg_Open ## k *r) \
77 { \
78         return dcesrv_winreg_openhive (dce_call, mem_ctx, n, &r->out.handle);\
79 }
80
81 func_winreg_OpenHive(HKCR,HKEY_CLASSES_ROOT)
82 func_winreg_OpenHive(HKCU,HKEY_CURRENT_USER)
83 func_winreg_OpenHive(HKLM,HKEY_LOCAL_MACHINE)
84 func_winreg_OpenHive(HKPD,HKEY_PERFORMANCE_DATA)
85 func_winreg_OpenHive(HKU,HKEY_USERS)
86 func_winreg_OpenHive(HKCC,HKEY_CURRENT_CONFIG)
87 func_winreg_OpenHive(HKDD,HKEY_DYN_DATA)
88 func_winreg_OpenHive(HKPT,HKEY_PERFORMANCE_TEXT)
89 func_winreg_OpenHive(HKPN,HKEY_PERFORMANCE_NLSTEXT)
90
91 /*
92   winreg_CloseKey
93 */
94 static WERROR dcesrv_winreg_CloseKey(struct dcesrv_call_state *dce_call,
95                                      TALLOC_CTX *mem_ctx,
96                                      struct winreg_CloseKey *r)
97 {
98         struct dcesrv_handle *h;
99
100         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
101
102         talloc_unlink(dce_call->context, h);
103
104         ZERO_STRUCTP(r->out.handle);
105
106         return WERR_OK;
107 }
108
109 /*
110   winreg_CreateKey
111 */
112 static WERROR dcesrv_winreg_CreateKey(struct dcesrv_call_state *dce_call,
113                                       TALLOC_CTX *mem_ctx,
114                                       struct winreg_CreateKey *r)
115 {
116         struct dcesrv_handle *h, *newh;
117         struct security_descriptor sd;
118         struct registry_key *key;
119         WERROR result;
120
121         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
122         key = h->data;
123
124         newh = dcesrv_handle_new(dce_call->context, HTYPE_REGKEY);
125
126         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
127         {
128         case SECURITY_SYSTEM:
129         case SECURITY_ADMINISTRATOR:
130                 /* we support only non volatile keys */
131                 if (r->in.options != REG_OPTION_NON_VOLATILE) {
132                         return WERR_NOT_SUPPORTED;
133                 }
134
135                 /* the security descriptor is optional */
136                 if (r->in.secdesc != NULL) {
137                         DATA_BLOB sdblob;
138                         enum ndr_err_code ndr_err;
139                         sdblob.data = r->in.secdesc->sd.data;
140                         sdblob.length = r->in.secdesc->sd.len;
141                         if (sdblob.data == NULL) {
142                                 return WERR_INVALID_PARAM;
143                         }
144                         ndr_err = ndr_pull_struct_blob_all(&sdblob, mem_ctx, NULL, &sd,
145                                                            (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
146                         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
147                                 return WERR_INVALID_PARAM;
148                         }
149                 }
150                 
151                 result = reg_key_add_name(newh, key, r->in.name.name, NULL,
152                         r->in.secdesc?&sd:NULL, (struct registry_key **)&newh->data);
153
154                 r->out.action_taken = talloc(mem_ctx, enum winreg_CreateAction);
155                 if (r->out.action_taken == NULL) {
156                         talloc_free(newh);
157                         return WERR_NOMEM;
158                 }
159                 *r->out.action_taken = REG_ACTION_NONE;
160
161                 if (W_ERROR_IS_OK(result)) {
162                         r->out.new_handle = &newh->wire_handle;
163                         *r->out.action_taken = REG_CREATED_NEW_KEY;
164                 } else {
165                         talloc_free(newh);
166                 }
167
168                 return result;
169         default:
170                 return WERR_ACCESS_DENIED;
171         }
172 }
173
174
175 /*
176   winreg_DeleteKey
177 */
178 static WERROR dcesrv_winreg_DeleteKey(struct dcesrv_call_state *dce_call,
179                                       TALLOC_CTX *mem_ctx,
180                                       struct winreg_DeleteKey *r)
181 {
182         struct dcesrv_handle *h;
183         struct registry_key *key;
184         WERROR result;
185
186         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
187         key = h->data;
188
189         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
190         {
191         case SECURITY_SYSTEM:
192         case SECURITY_ADMINISTRATOR:
193                 result = reg_key_del(mem_ctx, key, r->in.key.name);
194                 talloc_unlink(dce_call->context, h);
195
196                 return result;
197         default:
198                 return WERR_ACCESS_DENIED;
199         }
200 }
201
202
203 /*
204   winreg_DeleteValue
205 */
206 static WERROR dcesrv_winreg_DeleteValue(struct dcesrv_call_state *dce_call,
207                                         TALLOC_CTX *mem_ctx,
208                                         struct winreg_DeleteValue *r)
209 {
210         struct dcesrv_handle *h;
211         struct registry_key *key;
212
213         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
214         key = h->data;
215
216         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
217         {
218         case SECURITY_SYSTEM:
219         case SECURITY_ADMINISTRATOR:
220                 return reg_del_value(mem_ctx, key, r->in.value.name);
221         default:
222                 return WERR_ACCESS_DENIED;
223         }
224 }
225
226
227 /*
228   winreg_EnumKey
229 */
230 static WERROR dcesrv_winreg_EnumKey(struct dcesrv_call_state *dce_call,
231                                     TALLOC_CTX *mem_ctx,
232                                     struct winreg_EnumKey *r)
233 {
234         struct dcesrv_handle *h;
235         struct registry_key *key;
236         const char *name, *classname;
237         NTTIME last_mod;
238         WERROR result;
239
240         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
241         key = h->data;
242
243         result = reg_key_get_subkey_by_index(mem_ctx, 
244                 key, r->in.enum_index, &name, &classname, &last_mod);
245
246         if (2*strlen_m_term(name) > r->in.name->size) {
247                 return WERR_MORE_DATA;
248         }
249
250         if (name != NULL) {
251                 r->out.name->name = name;
252                 r->out.name->length = 2*strlen_m_term(name);
253         } else {
254                 r->out.name->name = r->in.name->name;
255                 r->out.name->length = r->in.name->length;
256         }
257         r->out.name->size = r->in.name->size;
258
259         r->out.keyclass = r->in.keyclass;
260         if (classname != NULL) {
261                 r->out.keyclass->name = classname;
262                 r->out.keyclass->length = 2*strlen_m_term(classname);
263         } else {
264                 r->out.keyclass->name = r->in.keyclass->name;
265                 r->out.keyclass->length = r->in.keyclass->length;
266         }
267         r->out.keyclass->size = r->in.keyclass->size;
268
269         if (r->in.last_changed_time != NULL)
270                 r->out.last_changed_time = &last_mod;
271
272         return result;
273 }
274
275
276 /*
277   winreg_EnumValue
278 */
279 static WERROR dcesrv_winreg_EnumValue(struct dcesrv_call_state *dce_call,
280                                       TALLOC_CTX *mem_ctx,
281                                       struct winreg_EnumValue *r)
282 {
283         struct dcesrv_handle *h;
284         struct registry_key *key;
285         const char *data_name;
286         uint32_t data_type;
287         DATA_BLOB data;
288         WERROR result;
289
290         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
291         key = h->data;
292
293         result = reg_key_get_value_by_index(mem_ctx, key,
294                 r->in.enum_index, &data_name, &data_type, &data);
295
296         if (!W_ERROR_IS_OK(result)) {
297                 /* if the lookup wasn't successful, send client query back */
298                 data_name = r->in.name->name;
299                 data_type = *r->in.type;
300                 data.data = r->in.value;
301                 data.length = *r->in.length;
302         }
303
304         /* "data_name" is NULL when we query the default attribute */
305         if (data_name != NULL) {
306                 r->out.name->name = data_name;
307                 r->out.name->length = 2*strlen_m_term(data_name);
308         } else {
309                 r->out.name->name = r->in.name->name;
310                 r->out.name->length = r->in.name->length;
311         }
312         r->out.name->size = r->in.name->size;
313
314         r->out.type = talloc(mem_ctx, uint32_t);
315         if (!r->out.type) {
316                 return WERR_NOMEM;
317         }
318         *r->out.type = data_type;
319
320         /* check the client has enough room for the value */
321         if (r->in.value != NULL &&
322             r->in.size != NULL &&
323             data.length > *r->in.size) {
324                 return WERR_MORE_DATA;
325         }
326
327         if (r->in.value != NULL) {
328                 r->out.value = data.data;
329         }
330
331         if (r->in.size != NULL) {
332                 r->out.size = talloc(mem_ctx, uint32_t);
333                 *r->out.size = data.length;
334                 r->out.length = r->out.size;
335         }
336
337         return result;
338 }
339
340
341 /*
342   winreg_FlushKey
343 */
344 static WERROR dcesrv_winreg_FlushKey(struct dcesrv_call_state *dce_call,
345                                      TALLOC_CTX *mem_ctx,
346                                      struct winreg_FlushKey *r)
347 {
348         struct dcesrv_handle *h;
349         struct registry_key *key;
350
351         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
352         key = h->data;
353
354         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
355         {
356         case SECURITY_SYSTEM:
357         case SECURITY_ADMINISTRATOR:
358                 return reg_key_flush(key);
359         default:
360                 return WERR_ACCESS_DENIED;
361         }
362 }
363
364
365 /*
366   winreg_GetKeySecurity
367 */
368 static WERROR dcesrv_winreg_GetKeySecurity(struct dcesrv_call_state *dce_call,
369                                            TALLOC_CTX *mem_ctx,
370                                            struct winreg_GetKeySecurity *r)
371 {
372         struct dcesrv_handle *h;
373
374         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
375
376         return WERR_NOT_SUPPORTED;
377 }
378
379
380 /*
381   winreg_LoadKey
382 */
383 static WERROR dcesrv_winreg_LoadKey(struct dcesrv_call_state *dce_call,
384                                     TALLOC_CTX *mem_ctx,
385                                     struct winreg_LoadKey *r)
386 {
387         return WERR_NOT_SUPPORTED;
388 }
389
390
391 /*
392   winreg_NotifyChangeKeyValue
393 */
394 static WERROR dcesrv_winreg_NotifyChangeKeyValue(struct dcesrv_call_state *dce_call,
395                                                  TALLOC_CTX *mem_ctx,
396                                                  struct winreg_NotifyChangeKeyValue *r)
397 {
398         return WERR_NOT_SUPPORTED;
399 }
400
401
402 /*
403   winreg_OpenKey
404 */
405 static WERROR dcesrv_winreg_OpenKey(struct dcesrv_call_state *dce_call,
406                                     TALLOC_CTX *mem_ctx,
407                                     struct winreg_OpenKey *r)
408 {
409         struct dcesrv_handle *h, *newh;
410         struct registry_key *key;
411         WERROR result;
412
413         DCESRV_PULL_HANDLE_FAULT(h, r->in.parent_handle, HTYPE_REGKEY);
414         key = h->data;
415
416         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
417         {
418         case SECURITY_SYSTEM:
419         case SECURITY_ADMINISTRATOR:
420         case SECURITY_USER:
421                 if (r->in.keyname.name && strcmp(r->in.keyname.name, "") == 0) {
422                         newh = talloc_reference(dce_call->context, h);
423                         result = WERR_OK;
424                 } else {
425                         newh = dcesrv_handle_new(dce_call->context, HTYPE_REGKEY);
426                         result = reg_open_key(newh, key, r->in.keyname.name,
427                                 (struct registry_key **)&newh->data);
428                 }
429                 
430                 if (W_ERROR_IS_OK(result)) {
431                         r->out.handle = &newh->wire_handle;
432                 } else {
433                         talloc_free(newh);
434                 }
435                 return result;
436         default:
437                 return WERR_ACCESS_DENIED;
438         }
439 }
440
441
442 /*
443   winreg_QueryInfoKey
444 */
445 static WERROR dcesrv_winreg_QueryInfoKey(struct dcesrv_call_state *dce_call,
446                                          TALLOC_CTX *mem_ctx,
447                                          struct winreg_QueryInfoKey *r)
448 {
449         struct dcesrv_handle *h;
450         struct registry_key *key;
451         const char *classname = NULL;
452         WERROR result;
453
454         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
455         key = h->data;
456
457         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
458         {
459         case SECURITY_SYSTEM:
460         case SECURITY_ADMINISTRATOR:
461         case SECURITY_USER:
462                 result = reg_key_get_info(mem_ctx, key, &classname,
463                         r->out.num_subkeys, r->out.num_values,
464                         r->out.last_changed_time, r->out.max_subkeylen,
465                         r->out.max_valnamelen, r->out.max_valbufsize);
466
467                 if (r->out.max_subkeylen != NULL) {
468                         /* for UTF16 encoding */
469                         *r->out.max_subkeylen *= 2;
470                 }
471                 if (r->out.max_valnamelen != NULL) {
472                         /* for UTF16 encoding */
473                         *r->out.max_valnamelen *= 2;
474                 }
475
476                 if (classname != NULL) {
477                         r->out.classname->name = classname;
478                         r->out.classname->name_len = 2*strlen_m_term(classname);
479                 } else {
480                         r->out.classname->name = r->in.classname->name;
481                         r->out.classname->name_len = r->in.classname->name_len;
482                 }
483                 r->out.classname->name_size = r->in.classname->name_size;
484
485                 return result;
486         default:
487                 return WERR_ACCESS_DENIED;
488         }
489 }
490
491
492 /*
493   winreg_QueryValue
494 */
495 static WERROR dcesrv_winreg_QueryValue(struct dcesrv_call_state *dce_call,
496                                        TALLOC_CTX *mem_ctx,
497                                        struct winreg_QueryValue *r)
498 {
499         struct dcesrv_handle *h;
500         struct registry_key *key;
501         uint32_t value_type;
502         DATA_BLOB value_data;
503         WERROR result;
504
505         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
506         key = h->data;
507
508         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
509         {
510         case SECURITY_SYSTEM:
511         case SECURITY_ADMINISTRATOR:
512         case SECURITY_USER:
513                 if ((r->in.type == NULL) || (r->in.data_length == NULL) ||
514                     (r->in.data_size == NULL)) {
515                         return WERR_INVALID_PARAM;
516                 }
517
518                 result = reg_key_get_value_by_name(mem_ctx, key, 
519                          r->in.value_name->name, &value_type, &value_data);
520                 
521                 if (!W_ERROR_IS_OK(result)) {
522                         /* if the lookup wasn't successful, send client query back */
523                         value_type = *r->in.type;
524                         value_data.data = r->in.data;
525                         value_data.length = *r->in.data_length;
526                 } else {
527                         if ((r->in.data != NULL)
528                             && (*r->in.data_size < value_data.length)) {
529                                 result = WERR_MORE_DATA;
530                         }
531                 }
532
533                 r->out.type = talloc(mem_ctx, uint32_t);
534                 if (!r->out.type) {
535                         return WERR_NOMEM;
536                 }
537                 *r->out.type = value_type;
538                 r->out.data_length = talloc(mem_ctx, uint32_t);
539                 if (!r->out.data_length) {
540                         return WERR_NOMEM;
541                 }
542                 *r->out.data_length = value_data.length;
543                 r->out.data_size = talloc(mem_ctx, uint32_t);
544                 if (!r->out.data_size) {
545                         return WERR_NOMEM;
546                 }
547                 *r->out.data_size = value_data.length;
548                 r->out.data = value_data.data;
549
550                 return result;
551         default:
552                 return WERR_ACCESS_DENIED;
553         }
554 }
555
556
557 /*
558   winreg_ReplaceKey
559 */
560 static WERROR dcesrv_winreg_ReplaceKey(struct dcesrv_call_state *dce_call,
561                                        TALLOC_CTX *mem_ctx,
562                                        struct winreg_ReplaceKey *r)
563 {
564         return WERR_NOT_SUPPORTED;
565 }
566
567
568 /*
569   winreg_RestoreKey
570 */
571 static WERROR dcesrv_winreg_RestoreKey(struct dcesrv_call_state *dce_call,
572                                        TALLOC_CTX *mem_ctx,
573                                        struct winreg_RestoreKey *r)
574 {
575         return WERR_NOT_SUPPORTED;
576 }
577
578
579 /*
580   winreg_SaveKey
581 */
582 static WERROR dcesrv_winreg_SaveKey(struct dcesrv_call_state *dce_call,
583                                     TALLOC_CTX *mem_ctx,
584                                     struct winreg_SaveKey *r)
585 {
586         return WERR_NOT_SUPPORTED;
587 }
588
589
590 /*
591   winreg_SetKeySecurity
592 */
593 static WERROR dcesrv_winreg_SetKeySecurity(struct dcesrv_call_state *dce_call,
594                                            TALLOC_CTX *mem_ctx,
595                                            struct winreg_SetKeySecurity *r)
596 {
597         return WERR_NOT_SUPPORTED;
598 }
599
600
601 /*
602   winreg_SetValue
603 */
604 static WERROR dcesrv_winreg_SetValue(struct dcesrv_call_state *dce_call,
605                                      TALLOC_CTX *mem_ctx,
606                                      struct winreg_SetValue *r)
607 {
608         struct dcesrv_handle *h;
609         struct registry_key *key;
610         DATA_BLOB data;
611         WERROR result;
612
613         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
614         key = h->data;
615
616         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
617         {
618         case SECURITY_SYSTEM:
619         case SECURITY_ADMINISTRATOR:
620                 data.data = r->in.data;
621                 data.length = r->in.size;
622                 result = reg_val_set(key, r->in.name.name, r->in.type, data);
623                 return result;
624         default:
625                 return WERR_ACCESS_DENIED;
626         }
627 }
628
629
630 /*
631   winreg_UnLoadKey
632 */
633 static WERROR dcesrv_winreg_UnLoadKey(struct dcesrv_call_state *dce_call,
634                                       TALLOC_CTX *mem_ctx,
635                                       struct winreg_UnLoadKey *r)
636 {
637         return WERR_NOT_SUPPORTED;
638 }
639
640
641 /*
642   winreg_InitiateSystemShutdown
643 */
644 static WERROR dcesrv_winreg_InitiateSystemShutdown(struct dcesrv_call_state *dce_call,
645                                                    TALLOC_CTX *mem_ctx,
646                                                    struct winreg_InitiateSystemShutdown *r)
647 {
648         return WERR_NOT_SUPPORTED;
649 }
650
651
652 /*
653   winreg_AbortSystemShutdown
654 */
655 static WERROR dcesrv_winreg_AbortSystemShutdown(struct dcesrv_call_state *dce_call,
656                                                 TALLOC_CTX *mem_ctx,
657                                                 struct winreg_AbortSystemShutdown *r)
658 {
659         return WERR_NOT_SUPPORTED;
660 }
661
662
663 /*
664   winreg_GetVersion
665 */
666 static WERROR dcesrv_winreg_GetVersion(struct dcesrv_call_state *dce_call,
667                                        TALLOC_CTX *mem_ctx,
668                                        struct winreg_GetVersion *r)
669 {
670         struct dcesrv_handle *h;
671
672         DCESRV_PULL_HANDLE_FAULT(h, r->in.handle, HTYPE_REGKEY);
673
674         r->out.version = talloc(mem_ctx, uint32_t);
675         W_ERROR_HAVE_NO_MEMORY(r->out.version);
676
677         *r->out.version = 5;
678
679         return WERR_OK;
680 }
681
682
683 /*
684   winreg_QueryMultipleValues
685 */
686 static WERROR dcesrv_winreg_QueryMultipleValues(struct dcesrv_call_state *dce_call,
687                                                 TALLOC_CTX *mem_ctx,
688                                                 struct winreg_QueryMultipleValues *r)
689 {
690         return WERR_NOT_SUPPORTED;
691 }
692
693
694 /*
695   winreg_InitiateSystemShutdownEx
696 */
697 static WERROR dcesrv_winreg_InitiateSystemShutdownEx(struct dcesrv_call_state *dce_call,
698                                                      TALLOC_CTX *mem_ctx,
699                                                      struct winreg_InitiateSystemShutdownEx *r)
700 {
701         return WERR_NOT_SUPPORTED;
702 }
703
704
705 /*
706   winreg_SaveKeyEx
707 */
708 static WERROR dcesrv_winreg_SaveKeyEx(struct dcesrv_call_state *dce_call,
709                                       TALLOC_CTX *mem_ctx,
710                                       struct winreg_SaveKeyEx *r)
711 {
712         return WERR_NOT_SUPPORTED;
713 }
714
715
716 /*
717   winreg_QueryMultipleValues2
718 */
719 static WERROR dcesrv_winreg_QueryMultipleValues2(struct dcesrv_call_state *dce_call,
720                                                  TALLOC_CTX *mem_ctx,
721                                                  struct winreg_QueryMultipleValues2 *r)
722 {
723         return WERR_NOT_SUPPORTED;
724 }
725
726 /*
727   winreg_DeleteKeyEx
728 */
729 static WERROR dcesrv_winreg_DeleteKeyEx(struct dcesrv_call_state *dce_call,
730                                         TALLOC_CTX *mem_ctx,
731                                         struct winreg_DeleteKeyEx *r)
732 {
733         return WERR_NOT_SUPPORTED;
734 }
735
736 /* include the generated boilerplate */
737 #include "librpc/gen_ndr/ndr_winreg_s.c"