2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
5 * Copyright (C) Gerald Carter 2002-2006.
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.
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.
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/>.
21 /* Implementation of registry functions. */
24 #include "../librpc/gen_ndr/srv_winreg.h"
28 #define DBGC_CLASS DBGC_RPC_SRV
30 /******************************************************************
31 Find a registry key handle and return a struct registry_key *
32 *****************************************************************/
34 static struct registry_key *find_regkey_by_hnd(pipes_struct *p,
35 struct policy_handle *hnd)
37 struct registry_key *regkey = NULL;
39 if(!find_policy_by_hnd(p,hnd,(void **)(void *)®key)) {
40 DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: "));
47 /*******************************************************************
48 Function for open a new registry handle and creating a handle
49 Note that P should be valid & hnd should already have space
51 When we open a key, we store the full path to the key as
52 HK[LM|U]\<key>\<key>\...
53 *******************************************************************/
55 static WERROR open_registry_key( pipes_struct *p, struct policy_handle *hnd,
56 struct registry_key *parent,
57 const char *subkeyname,
58 uint32 access_desired )
60 WERROR result = WERR_OK;
61 struct registry_key *key;
64 result = reg_openhive(p->mem_ctx, subkeyname, access_desired,
65 p->server_info->ptok, &key);
68 result = reg_openkey(p->mem_ctx, parent, subkeyname,
69 access_desired, &key);
72 if ( !W_ERROR_IS_OK(result) ) {
76 if ( !create_policy_hnd( p, hnd, key ) ) {
83 /*******************************************************************
84 Function for open a new registry handle and creating a handle
85 Note that P should be valid & hnd should already have space
86 *******************************************************************/
88 static bool close_registry_key(pipes_struct *p, struct policy_handle *hnd)
90 struct registry_key *regkey = find_regkey_by_hnd(p, hnd);
93 DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n",
98 close_policy_hnd(p, hnd);
103 /********************************************************************
105 ********************************************************************/
107 WERROR _winreg_CloseKey(pipes_struct *p, struct winreg_CloseKey *r)
109 /* close the policy handle */
111 if (!close_registry_key(p, r->in.handle))
114 ZERO_STRUCTP(r->out.handle);
119 /*******************************************************************
121 ********************************************************************/
123 WERROR _winreg_OpenHKLM(pipes_struct *p, struct winreg_OpenHKLM *r)
125 return open_registry_key(p, r->out.handle, NULL, KEY_HKLM, r->in.access_mask);
128 /*******************************************************************
130 ********************************************************************/
132 WERROR _winreg_OpenHKPD(pipes_struct *p, struct winreg_OpenHKPD *r)
134 return open_registry_key(p, r->out.handle, NULL, KEY_HKPD, r->in.access_mask);
137 /*******************************************************************
139 ********************************************************************/
141 WERROR _winreg_OpenHKPT(pipes_struct *p, struct winreg_OpenHKPT *r)
143 return open_registry_key(p, r->out.handle, NULL, KEY_HKPT, r->in.access_mask);
146 /*******************************************************************
148 ********************************************************************/
150 WERROR _winreg_OpenHKCR(pipes_struct *p, struct winreg_OpenHKCR *r)
152 return open_registry_key(p, r->out.handle, NULL, KEY_HKCR, r->in.access_mask);
155 /*******************************************************************
157 ********************************************************************/
159 WERROR _winreg_OpenHKU(pipes_struct *p, struct winreg_OpenHKU *r)
161 return open_registry_key(p, r->out.handle, NULL, KEY_HKU, r->in.access_mask);
164 /*******************************************************************
166 ********************************************************************/
168 WERROR _winreg_OpenHKCU(pipes_struct *p, struct winreg_OpenHKCU *r)
170 return open_registry_key(p, r->out.handle, NULL, KEY_HKCU, r->in.access_mask);
173 /*******************************************************************
175 ********************************************************************/
177 WERROR _winreg_OpenHKCC(pipes_struct *p, struct winreg_OpenHKCC *r)
179 return open_registry_key(p, r->out.handle, NULL, KEY_HKCC, r->in.access_mask);
182 /*******************************************************************
184 ********************************************************************/
186 WERROR _winreg_OpenHKDD(pipes_struct *p, struct winreg_OpenHKDD *r)
188 return open_registry_key(p, r->out.handle, NULL, KEY_HKDD, r->in.access_mask);
191 /*******************************************************************
193 ********************************************************************/
195 WERROR _winreg_OpenHKPN(pipes_struct *p, struct winreg_OpenHKPN *r)
197 return open_registry_key(p, r->out.handle, NULL, KEY_HKPN, r->in.access_mask);
200 /*******************************************************************
202 ********************************************************************/
204 WERROR _winreg_OpenKey(pipes_struct *p, struct winreg_OpenKey *r)
206 struct registry_key *parent = find_regkey_by_hnd(p, r->in.parent_handle );
211 return open_registry_key(p, r->out.handle, parent, r->in.keyname.name, r->in.access_mask);
214 /*******************************************************************
216 ********************************************************************/
218 WERROR _winreg_QueryValue(pipes_struct *p, struct winreg_QueryValue *r)
220 WERROR status = WERR_BADFILE;
221 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
225 uint32_t outbuf_size;
228 bool free_buf = False;
229 bool free_prs = False;
234 if (r->in.value_name->name == NULL) {
235 return WERR_INVALID_PARAM;
238 if ((r->out.data_length == NULL) || (r->out.type == NULL) || (r->out.data_size == NULL)) {
239 return WERR_INVALID_PARAM;
242 DEBUG(7,("_winreg_QueryValue: policy key name = [%s]\n", regkey->key->name));
243 DEBUG(7,("_winreg_QueryValue: policy key type = [%08x]\n", regkey->key->type));
245 /* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */
246 if(regkey->key->type == REG_KEY_HKPD)
248 if (strequal(r->in.value_name->name, "Global")) {
249 if (!prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL))
251 status = reg_perfcount_get_hkpd(
252 &prs_hkpd, *r->in.data_size, &outbuf_size, NULL);
253 outbuf = (uint8_t *)prs_hkpd.data_p;
256 else if (strequal(r->in.value_name->name, "Counter 009")) {
257 outbuf_size = reg_perfcount_get_counter_names(
258 reg_perfcount_get_base_index(),
259 (char **)(void *)&outbuf);
262 else if (strequal(r->in.value_name->name, "Explain 009")) {
263 outbuf_size = reg_perfcount_get_counter_help(
264 reg_perfcount_get_base_index(),
265 (char **)(void *)&outbuf);
268 else if (isdigit(r->in.value_name->name[0])) {
269 /* we probably have a request for a specific object
271 if (!prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL))
273 status = reg_perfcount_get_hkpd(
274 &prs_hkpd, *r->in.data_size, &outbuf_size,
275 r->in.value_name->name);
276 outbuf = (uint8_t *)prs_hkpd.data_p;
280 DEBUG(3,("Unsupported key name [%s] for HKPD.\n",
281 r->in.value_name->name));
285 *r->out.type = REG_BINARY;
288 struct registry_value *val;
290 status = reg_queryvalue(p->mem_ctx, regkey, r->in.value_name->name,
292 if (!W_ERROR_IS_OK(status)) {
294 DEBUG(10,("_winreg_QueryValue: reg_queryvalue failed with: %s\n",
295 win_errstr(status)));
297 if (r->out.data_size) {
298 *r->out.data_size = 0;
300 if (r->out.data_length) {
301 *r->out.data_length = 0;
306 status = registry_push_value(p->mem_ctx, val, &val_blob);
307 if (!W_ERROR_IS_OK(status)) {
311 outbuf = val_blob.data;
312 outbuf_size = val_blob.length;
313 *r->out.type = val->type;
316 status = WERR_BADFILE;
318 if (*r->in.data_size < outbuf_size) {
319 *r->out.data_size = outbuf_size;
320 status = r->in.data ? WERR_MORE_DATA : WERR_OK;
322 *r->out.data_length = outbuf_size;
323 *r->out.data_size = outbuf_size;
325 memcpy(r->out.data, outbuf, outbuf_size);
330 if (free_prs) prs_mem_free(&prs_hkpd);
331 if (free_buf) SAFE_FREE(outbuf);
336 /*****************************************************************************
338 ****************************************************************************/
340 WERROR _winreg_QueryInfoKey(pipes_struct *p, struct winreg_QueryInfoKey *r)
342 WERROR status = WERR_OK;
343 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
348 r->out.classname->name = NULL;
350 status = reg_queryinfokey(regkey, r->out.num_subkeys, r->out.max_subkeylen,
351 r->out.max_classlen, r->out.num_values, r->out.max_valnamelen,
352 r->out.max_valbufsize, r->out.secdescsize,
353 r->out.last_changed_time);
354 if (!W_ERROR_IS_OK(status)) {
359 * These calculations account for the registry buffers being
360 * UTF-16. They are inexact at best, but so far they worked.
363 *r->out.max_subkeylen *= 2;
365 *r->out.max_valnamelen += 1;
366 *r->out.max_valnamelen *= 2;
372 /*****************************************************************************
374 ****************************************************************************/
376 WERROR _winreg_GetVersion(pipes_struct *p, struct winreg_GetVersion *r)
378 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
383 return reg_getversion(r->out.version);
387 /*****************************************************************************
389 ****************************************************************************/
391 WERROR _winreg_EnumKey(pipes_struct *p, struct winreg_EnumKey *r)
394 struct registry_key *key = find_regkey_by_hnd( p, r->in.handle );
399 if ( !r->in.name || !r->in.keyclass )
400 return WERR_INVALID_PARAM;
402 DEBUG(8,("_winreg_EnumKey: enumerating key [%s]\n", key->key->name));
404 err = reg_enumkey(p->mem_ctx, key, r->in.enum_index, (char **)&r->out.name->name,
405 r->out.last_changed_time);
406 if (!W_ERROR_IS_OK(err)) {
409 r->out.keyclass->name = "";
413 /*****************************************************************************
415 ****************************************************************************/
417 WERROR _winreg_EnumValue(pipes_struct *p, struct winreg_EnumValue *r)
420 struct registry_key *key = find_regkey_by_hnd( p, r->in.handle );
422 struct registry_value *val;
423 DATA_BLOB value_blob;
429 return WERR_INVALID_PARAM;
431 DEBUG(8,("_winreg_EnumValue: enumerating values for key [%s]\n",
434 err = reg_enumvalue(p->mem_ctx, key, r->in.enum_index, &valname, &val);
435 if (!W_ERROR_IS_OK(err)) {
439 err = registry_push_value(p->mem_ctx, val, &value_blob);
440 if (!W_ERROR_IS_OK(err)) {
444 if (r->out.name != NULL) {
445 r->out.name->name = valname;
448 if (r->out.type != NULL) {
449 *r->out.type = val->type;
452 if (r->out.value != NULL) {
453 if ((r->out.size == NULL) || (r->out.length == NULL)) {
454 return WERR_INVALID_PARAM;
457 if (value_blob.length > *r->out.size) {
458 return WERR_MORE_DATA;
461 memcpy( r->out.value, value_blob.data, value_blob.length );
464 if (r->out.length != NULL) {
465 *r->out.length = value_blob.length;
467 if (r->out.size != NULL) {
468 *r->out.size = value_blob.length;
474 /*******************************************************************
475 _winreg_InitiateSystemShutdown
476 ********************************************************************/
478 WERROR _winreg_InitiateSystemShutdown(pipes_struct *p, struct winreg_InitiateSystemShutdown *r)
480 struct winreg_InitiateSystemShutdownEx s;
482 s.in.hostname = r->in.hostname;
483 s.in.message = r->in.message;
484 s.in.timeout = r->in.timeout;
485 s.in.force_apps = r->in.force_apps;
486 s.in.do_reboot = r->in.do_reboot;
489 /* thunk down to _winreg_InitiateSystemShutdownEx()
490 (just returns a status) */
492 return _winreg_InitiateSystemShutdownEx( p, &s );
495 /*******************************************************************
496 _winreg_InitiateSystemShutdownEx
497 ********************************************************************/
499 #define SHUTDOWN_R_STRING "-r"
500 #define SHUTDOWN_F_STRING "-f"
503 WERROR _winreg_InitiateSystemShutdownEx(pipes_struct *p, struct winreg_InitiateSystemShutdownEx *r)
505 char *shutdown_script = NULL;
515 shutdown_script = talloc_strdup(p->mem_ctx, lp_shutdown_script());
516 if (!shutdown_script) {
519 if (!*shutdown_script) {
520 return WERR_ACCESS_DENIED;
523 /* pull the message string and perform necessary sanity checks on it */
525 if ( r->in.message && r->in.message->string ) {
526 if ( (msg = talloc_strdup(p->mem_ctx, r->in.message->string )) == NULL ) {
529 chkmsg = TALLOC_ARRAY(p->mem_ctx, char, strlen(msg)+1);
533 alpha_strcpy(chkmsg, msg, NULL, strlen(msg)+1);
536 fstr_sprintf(str_timeout, "%d", r->in.timeout);
537 fstr_sprintf(do_reboot, r->in.do_reboot ? SHUTDOWN_R_STRING : "");
538 fstr_sprintf(f, r->in.force_apps ? SHUTDOWN_F_STRING : "");
539 fstr_sprintf(str_reason, "%d", r->in.reason );
541 shutdown_script = talloc_all_string_sub(p->mem_ctx,
542 shutdown_script, "%z", chkmsg ? chkmsg : "");
543 if (!shutdown_script) {
546 shutdown_script = talloc_all_string_sub(p->mem_ctx,
547 shutdown_script, "%t", str_timeout);
548 if (!shutdown_script) {
551 shutdown_script = talloc_all_string_sub(p->mem_ctx,
552 shutdown_script, "%r", do_reboot);
553 if (!shutdown_script) {
556 shutdown_script = talloc_all_string_sub(p->mem_ctx,
557 shutdown_script, "%f", f);
558 if (!shutdown_script) {
561 shutdown_script = talloc_all_string_sub(p->mem_ctx,
562 shutdown_script, "%x", str_reason);
563 if (!shutdown_script) {
567 can_shutdown = user_has_privileges( p->server_info->ptok,
568 &se_remote_shutdown );
570 /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
571 Take the error return from the script and provide it as the Windows return code. */
573 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
578 ret = smbrun( shutdown_script, NULL );
583 /********** END SeRemoteShutdownPrivilege BLOCK **********/
585 DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
586 shutdown_script, ret));
588 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
591 /*******************************************************************
592 _winreg_AbortSystemShutdown
593 ********************************************************************/
595 WERROR _winreg_AbortSystemShutdown(pipes_struct *p, struct winreg_AbortSystemShutdown *r)
597 const char *abort_shutdown_script;
601 abort_shutdown_script = lp_abort_shutdown_script();
603 if (!*abort_shutdown_script)
604 return WERR_ACCESS_DENIED;
606 can_shutdown = user_has_privileges( p->server_info->ptok,
607 &se_remote_shutdown );
609 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
614 ret = smbrun( abort_shutdown_script, NULL );
619 /********** END SeRemoteShutdownPrivilege BLOCK **********/
621 DEBUG(3,("_winreg_AbortSystemShutdown: Running the command `%s' gave %d\n",
622 abort_shutdown_script, ret));
624 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
627 /*******************************************************************
628 ********************************************************************/
630 static int validate_reg_filename(TALLOC_CTX *ctx, char **pp_fname )
633 int num_services = lp_numservices();
635 const char *share_path;
636 char *fname = *pp_fname;
638 /* convert to a unix path, stripping the C:\ along the way */
640 if (!(p = valid_share_pathname(ctx, fname))) {
644 /* has to exist within a valid file share */
646 for (snum=0; snum<num_services; snum++) {
647 if (!lp_snum_ok(snum) || lp_print_ok(snum)) {
651 share_path = lp_pathname(snum);
653 /* make sure we have a path (e.g. [homes] ) */
654 if (strlen(share_path) == 0) {
658 if (strncmp(share_path, p, strlen(share_path)) == 0) {
664 return (snum < num_services) ? snum : -1;
667 /*******************************************************************
669 ********************************************************************/
671 WERROR _winreg_RestoreKey(pipes_struct *p, struct winreg_RestoreKey *r)
673 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
680 if ( !r->in.filename || !r->in.filename->name )
681 return WERR_INVALID_PARAM;
683 fname = talloc_strdup(p->mem_ctx, r->in.filename->name);
688 DEBUG(8,("_winreg_RestoreKey: verifying restore of key [%s] from "
689 "\"%s\"\n", regkey->key->name, fname));
691 if ((snum = validate_reg_filename(p->mem_ctx, &fname)) == -1)
692 return WERR_OBJECT_PATH_INVALID;
694 /* user must posses SeRestorePrivilege for this this proceed */
696 if ( !user_has_privileges( p->server_info->ptok, &se_restore ) )
697 return WERR_ACCESS_DENIED;
699 DEBUG(2,("_winreg_RestoreKey: Restoring [%s] from %s in share %s\n",
700 regkey->key->name, fname, lp_servicename(snum) ));
702 return reg_restorekey(regkey, fname);
705 /*******************************************************************
707 ********************************************************************/
709 WERROR _winreg_SaveKey(pipes_struct *p, struct winreg_SaveKey *r)
711 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
718 if ( !r->in.filename || !r->in.filename->name )
719 return WERR_INVALID_PARAM;
721 fname = talloc_strdup(p->mem_ctx, r->in.filename->name);
726 DEBUG(8,("_winreg_SaveKey: verifying backup of key [%s] to \"%s\"\n",
727 regkey->key->name, fname));
729 if ((snum = validate_reg_filename(p->mem_ctx, &fname)) == -1 )
730 return WERR_OBJECT_PATH_INVALID;
732 DEBUG(2,("_winreg_SaveKey: Saving [%s] to %s in share %s\n",
733 regkey->key->name, fname, lp_servicename(snum) ));
735 return reg_savekey(regkey, fname);
738 /*******************************************************************
740 ********************************************************************/
742 WERROR _winreg_SaveKeyEx(pipes_struct *p, struct winreg_SaveKeyEx *r)
744 /* fill in your code here if you think this call should
747 p->rng_fault_state = True;
748 return WERR_NOT_SUPPORTED;
751 /*******************************************************************
753 ********************************************************************/
755 WERROR _winreg_CreateKey( pipes_struct *p, struct winreg_CreateKey *r)
757 struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
758 struct registry_key *new_key;
764 DEBUG(10, ("_winreg_CreateKey called with parent key '%s' and "
765 "subkey name '%s'\n", parent->key->name, r->in.name.name));
767 result = reg_createkey(NULL, parent, r->in.name.name, r->in.access_mask,
768 &new_key, r->out.action_taken);
769 if (!W_ERROR_IS_OK(result)) {
773 if (!create_policy_hnd(p, r->out.new_handle, new_key)) {
774 TALLOC_FREE(new_key);
781 /*******************************************************************
783 ********************************************************************/
785 WERROR _winreg_SetValue(pipes_struct *p, struct winreg_SetValue *r)
787 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
788 struct registry_value *val;
794 DEBUG(8,("_winreg_SetValue: Setting value for [%s:%s]\n",
795 key->key->name, r->in.name.name));
797 status = registry_pull_value(p->mem_ctx, &val, r->in.type, r->in.data,
798 r->in.size, r->in.size);
799 if (!W_ERROR_IS_OK(status)) {
803 return reg_setvalue(key, r->in.name.name, val);
806 /*******************************************************************
808 ********************************************************************/
810 WERROR _winreg_DeleteKey(pipes_struct *p, struct winreg_DeleteKey *r)
812 struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
817 return reg_deletekey(parent, r->in.key.name);
821 /*******************************************************************
823 ********************************************************************/
825 WERROR _winreg_DeleteValue(pipes_struct *p, struct winreg_DeleteValue *r)
827 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
832 return reg_deletevalue(key, r->in.value.name);
835 /*******************************************************************
836 _winreg_GetKeySecurity
837 ********************************************************************/
839 WERROR _winreg_GetKeySecurity(pipes_struct *p, struct winreg_GetKeySecurity *r)
841 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
843 struct security_descriptor *secdesc;
850 /* access checks first */
852 if ( !(key->key->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
853 return WERR_ACCESS_DENIED;
855 err = reg_getkeysecurity(p->mem_ctx, key, &secdesc);
856 if (!W_ERROR_IS_OK(err)) {
860 err = ntstatus_to_werror(marshall_sec_desc(p->mem_ctx, secdesc,
862 if (!W_ERROR_IS_OK(err)) {
866 if (len > r->out.sd->size) {
867 r->out.sd->size = len;
868 return WERR_INSUFFICIENT_BUFFER;
871 r->out.sd->size = len;
872 r->out.sd->len = len;
873 r->out.sd->data = data;
878 /*******************************************************************
879 _winreg_SetKeySecurity
880 ********************************************************************/
882 WERROR _winreg_SetKeySecurity(pipes_struct *p, struct winreg_SetKeySecurity *r)
884 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
885 struct security_descriptor *secdesc;
891 /* access checks first */
893 if ( !(key->key->access_granted & STD_RIGHT_WRITE_DAC_ACCESS) )
894 return WERR_ACCESS_DENIED;
896 err = ntstatus_to_werror(unmarshall_sec_desc(p->mem_ctx, r->in.sd->data,
897 r->in.sd->len, &secdesc));
898 if (!W_ERROR_IS_OK(err)) {
902 return reg_setkeysecurity(key, secdesc);
905 /*******************************************************************
907 ********************************************************************/
909 WERROR _winreg_FlushKey(pipes_struct *p, struct winreg_FlushKey *r)
911 /* I'm just replying OK because there's not a lot
912 here I see to do i --jerry */
917 /*******************************************************************
919 ********************************************************************/
921 WERROR _winreg_UnLoadKey(pipes_struct *p, struct winreg_UnLoadKey *r)
923 /* fill in your code here if you think this call should
926 p->rng_fault_state = True;
927 return WERR_NOT_SUPPORTED;
930 /*******************************************************************
932 ********************************************************************/
934 WERROR _winreg_ReplaceKey(pipes_struct *p, struct winreg_ReplaceKey *r)
936 /* fill in your code here if you think this call should
939 p->rng_fault_state = True;
940 return WERR_NOT_SUPPORTED;
943 /*******************************************************************
945 ********************************************************************/
947 WERROR _winreg_LoadKey(pipes_struct *p, struct winreg_LoadKey *r)
949 /* fill in your code here if you think this call should
952 p->rng_fault_state = True;
953 return WERR_NOT_SUPPORTED;
956 /*******************************************************************
957 _winreg_NotifyChangeKeyValue
958 ********************************************************************/
960 WERROR _winreg_NotifyChangeKeyValue(pipes_struct *p, struct winreg_NotifyChangeKeyValue *r)
962 return WERR_NOT_SUPPORTED;
965 /*******************************************************************
966 _winreg_QueryMultipleValues
967 ********************************************************************/
969 WERROR _winreg_QueryMultipleValues(pipes_struct *p, struct winreg_QueryMultipleValues *r)
971 /* fill in your code here if you think this call should
974 p->rng_fault_state = True;
975 return WERR_NOT_SUPPORTED;
978 /*******************************************************************
979 _winreg_QueryMultipleValues2
980 ********************************************************************/
982 WERROR _winreg_QueryMultipleValues2(pipes_struct *p, struct winreg_QueryMultipleValues2 *r)
984 /* fill in your code here if you think this call should
987 p->rng_fault_state = True;
988 return WERR_NOT_SUPPORTED;
991 /*******************************************************************
993 ********************************************************************/
995 WERROR _winreg_DeleteKeyEx(pipes_struct *p, struct winreg_DeleteKeyEx *r)
997 /* fill in your code here if you think this call should
1000 p->rng_fault_state = True;
1001 return WERR_NOT_SUPPORTED;