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"
27 #define DBGC_CLASS DBGC_RPC_SRV
29 /******************************************************************
30 Find a registry key handle and return a struct registry_key *
31 *****************************************************************/
33 static struct registry_key *find_regkey_by_hnd(pipes_struct *p,
34 struct policy_handle *hnd)
36 struct registry_key *regkey = NULL;
38 if(!find_policy_by_hnd(p,hnd,(void **)(void *)®key)) {
39 DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: "));
46 /*******************************************************************
47 Function for open a new registry handle and creating a handle
48 Note that P should be valid & hnd should already have space
50 When we open a key, we store the full path to the key as
51 HK[LM|U]\<key>\<key>\...
52 *******************************************************************/
54 static WERROR open_registry_key( pipes_struct *p, struct policy_handle *hnd,
55 struct registry_key *parent,
56 const char *subkeyname,
57 uint32 access_desired )
59 WERROR result = WERR_OK;
60 struct registry_key *key;
63 result = reg_openhive(p->mem_ctx, subkeyname, access_desired,
64 p->server_info->ptok, &key);
67 result = reg_openkey(p->mem_ctx, parent, subkeyname,
68 access_desired, &key);
71 if ( !W_ERROR_IS_OK(result) ) {
75 if ( !create_policy_hnd( p, hnd, key ) ) {
82 /*******************************************************************
83 Function for open a new registry handle and creating a handle
84 Note that P should be valid & hnd should already have space
85 *******************************************************************/
87 static bool close_registry_key(pipes_struct *p, struct policy_handle *hnd)
89 struct registry_key *regkey = find_regkey_by_hnd(p, hnd);
92 DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n",
97 close_policy_hnd(p, hnd);
102 /********************************************************************
104 ********************************************************************/
106 WERROR _winreg_CloseKey(pipes_struct *p, struct winreg_CloseKey *r)
108 /* close the policy handle */
110 if (!close_registry_key(p, r->in.handle))
113 ZERO_STRUCTP(r->out.handle);
118 /*******************************************************************
120 ********************************************************************/
122 WERROR _winreg_OpenHKLM(pipes_struct *p, struct winreg_OpenHKLM *r)
124 return open_registry_key(p, r->out.handle, NULL, KEY_HKLM, r->in.access_mask);
127 /*******************************************************************
129 ********************************************************************/
131 WERROR _winreg_OpenHKPD(pipes_struct *p, struct winreg_OpenHKPD *r)
133 return open_registry_key(p, r->out.handle, NULL, KEY_HKPD, r->in.access_mask);
136 /*******************************************************************
138 ********************************************************************/
140 WERROR _winreg_OpenHKPT(pipes_struct *p, struct winreg_OpenHKPT *r)
142 return open_registry_key(p, r->out.handle, NULL, KEY_HKPT, r->in.access_mask);
145 /*******************************************************************
147 ********************************************************************/
149 WERROR _winreg_OpenHKCR(pipes_struct *p, struct winreg_OpenHKCR *r)
151 return open_registry_key(p, r->out.handle, NULL, KEY_HKCR, r->in.access_mask);
154 /*******************************************************************
156 ********************************************************************/
158 WERROR _winreg_OpenHKU(pipes_struct *p, struct winreg_OpenHKU *r)
160 return open_registry_key(p, r->out.handle, NULL, KEY_HKU, r->in.access_mask);
163 /*******************************************************************
165 ********************************************************************/
167 WERROR _winreg_OpenHKCU(pipes_struct *p, struct winreg_OpenHKCU *r)
169 return open_registry_key(p, r->out.handle, NULL, KEY_HKCU, r->in.access_mask);
172 /*******************************************************************
174 ********************************************************************/
176 WERROR _winreg_OpenHKCC(pipes_struct *p, struct winreg_OpenHKCC *r)
178 return open_registry_key(p, r->out.handle, NULL, KEY_HKCC, r->in.access_mask);
181 /*******************************************************************
183 ********************************************************************/
185 WERROR _winreg_OpenHKDD(pipes_struct *p, struct winreg_OpenHKDD *r)
187 return open_registry_key(p, r->out.handle, NULL, KEY_HKDD, r->in.access_mask);
190 /*******************************************************************
192 ********************************************************************/
194 WERROR _winreg_OpenHKPN(pipes_struct *p, struct winreg_OpenHKPN *r)
196 return open_registry_key(p, r->out.handle, NULL, KEY_HKPN, r->in.access_mask);
199 /*******************************************************************
201 ********************************************************************/
203 WERROR _winreg_OpenKey(pipes_struct *p, struct winreg_OpenKey *r)
205 struct registry_key *parent = find_regkey_by_hnd(p, r->in.parent_handle );
210 return open_registry_key(p, r->out.handle, parent, r->in.keyname.name, r->in.access_mask);
213 /*******************************************************************
215 ********************************************************************/
217 WERROR _winreg_QueryValue(pipes_struct *p, struct winreg_QueryValue *r)
219 WERROR status = WERR_BADFILE;
220 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
224 uint32_t outbuf_size;
227 bool free_buf = False;
228 bool free_prs = False;
233 if ((r->out.data_length == NULL) || (r->out.type == NULL)) {
234 return WERR_INVALID_PARAM;
237 *r->out.data_length = *r->out.type = REG_NONE;
239 DEBUG(7,("_winreg_QueryValue: policy key name = [%s]\n", regkey->key->name));
240 DEBUG(7,("_winreg_QueryValue: policy key type = [%08x]\n", regkey->key->type));
242 /* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */
243 if(regkey->key->type == REG_KEY_HKPD)
245 if (strequal(r->in.value_name->name, "Global")) {
246 if (!prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL))
248 status = reg_perfcount_get_hkpd(
249 &prs_hkpd, *r->in.data_size, &outbuf_size, NULL);
250 outbuf = (uint8_t *)prs_hkpd.data_p;
253 else if (strequal(r->in.value_name->name, "Counter 009")) {
254 outbuf_size = reg_perfcount_get_counter_names(
255 reg_perfcount_get_base_index(),
256 (char **)(void *)&outbuf);
259 else if (strequal(r->in.value_name->name, "Explain 009")) {
260 outbuf_size = reg_perfcount_get_counter_help(
261 reg_perfcount_get_base_index(),
262 (char **)(void *)&outbuf);
265 else if (isdigit(r->in.value_name->name[0])) {
266 /* we probably have a request for a specific object
268 if (!prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL))
270 status = reg_perfcount_get_hkpd(
271 &prs_hkpd, *r->in.data_size, &outbuf_size,
272 r->in.value_name->name);
273 outbuf = (uint8_t *)prs_hkpd.data_p;
277 DEBUG(3,("Unsupported key name [%s] for HKPD.\n",
278 r->in.value_name->name));
282 *r->out.type = REG_BINARY;
285 struct registry_value *val;
287 status = reg_queryvalue(p->mem_ctx, regkey, r->in.value_name->name,
289 if (!W_ERROR_IS_OK(status)) {
291 DEBUG(10,("_winreg_QueryValue: reg_queryvalue failed with: %s\n",
292 win_errstr(status)));
294 if (r->out.data_size) {
295 *r->out.data_size = 0;
297 if (r->out.data_length) {
298 *r->out.data_length = 0;
303 status = registry_push_value(p->mem_ctx, val, &val_blob);
304 if (!W_ERROR_IS_OK(status)) {
308 outbuf = val_blob.data;
309 outbuf_size = val_blob.length;
310 *r->out.type = val->type;
313 *r->out.data_length = outbuf_size;
315 if ( *r->in.data_size == 0 || !r->out.data ) {
317 } else if ( *r->out.data_length > *r->in.data_size ) {
318 status = WERR_MORE_DATA;
320 memcpy( r->out.data, outbuf, *r->out.data_length );
324 *r->out.data_size = *r->out.data_length;
326 if (free_prs) prs_mem_free(&prs_hkpd);
327 if (free_buf) SAFE_FREE(outbuf);
332 /*****************************************************************************
334 ****************************************************************************/
336 WERROR _winreg_QueryInfoKey(pipes_struct *p, struct winreg_QueryInfoKey *r)
338 WERROR status = WERR_OK;
339 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
344 r->out.classname->name = NULL;
346 status = reg_queryinfokey(regkey, r->out.num_subkeys, r->out.max_subkeylen,
347 r->out.max_classlen, r->out.num_values, r->out.max_valnamelen,
348 r->out.max_valbufsize, r->out.secdescsize,
349 r->out.last_changed_time);
350 if (!W_ERROR_IS_OK(status)) {
355 * These calculations account for the registry buffers being
356 * UTF-16. They are inexact at best, but so far they worked.
359 *r->out.max_subkeylen *= 2;
361 *r->out.max_valnamelen += 1;
362 *r->out.max_valnamelen *= 2;
368 /*****************************************************************************
370 ****************************************************************************/
372 WERROR _winreg_GetVersion(pipes_struct *p, struct winreg_GetVersion *r)
374 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
379 return reg_getversion(r->out.version);
383 /*****************************************************************************
385 ****************************************************************************/
387 WERROR _winreg_EnumKey(pipes_struct *p, struct winreg_EnumKey *r)
390 struct registry_key *key = find_regkey_by_hnd( p, r->in.handle );
395 if ( !r->in.name || !r->in.keyclass )
396 return WERR_INVALID_PARAM;
398 DEBUG(8,("_reg_enum_key: enumerating key [%s]\n", key->key->name));
400 err = reg_enumkey(p->mem_ctx, key, r->in.enum_index, (char **)&r->out.name->name,
401 r->out.last_changed_time);
402 if (!W_ERROR_IS_OK(err)) {
405 r->out.keyclass->name = "";
409 /*****************************************************************************
411 ****************************************************************************/
413 WERROR _winreg_EnumValue(pipes_struct *p, struct winreg_EnumValue *r)
416 struct registry_key *key = find_regkey_by_hnd( p, r->in.handle );
418 struct registry_value *val;
419 DATA_BLOB value_blob;
425 return WERR_INVALID_PARAM;
427 DEBUG(8,("_winreg_EnumValue: enumerating values for key [%s]\n",
430 err = reg_enumvalue(p->mem_ctx, key, r->in.enum_index, &valname, &val);
431 if (!W_ERROR_IS_OK(err)) {
435 err = registry_push_value(p->mem_ctx, val, &value_blob);
436 if (!W_ERROR_IS_OK(err)) {
440 if (r->out.name != NULL) {
441 r->out.name->name = valname;
444 if (r->out.type != NULL) {
445 *r->out.type = val->type;
448 if (r->out.value != NULL) {
449 if ((r->out.size == NULL) || (r->out.length == NULL)) {
450 return WERR_INVALID_PARAM;
453 if (value_blob.length > *r->out.size) {
454 return WERR_MORE_DATA;
457 memcpy( r->out.value, value_blob.data, value_blob.length );
460 if (r->out.length != NULL) {
461 *r->out.length = value_blob.length;
463 if (r->out.size != NULL) {
464 *r->out.size = value_blob.length;
470 /*******************************************************************
471 _winreg_InitiateSystemShutdown
472 ********************************************************************/
474 WERROR _winreg_InitiateSystemShutdown(pipes_struct *p, struct winreg_InitiateSystemShutdown *r)
476 struct winreg_InitiateSystemShutdownEx s;
478 s.in.hostname = r->in.hostname;
479 s.in.message = r->in.message;
480 s.in.timeout = r->in.timeout;
481 s.in.force_apps = r->in.force_apps;
482 s.in.do_reboot = r->in.do_reboot;
485 /* thunk down to _winreg_InitiateSystemShutdownEx()
486 (just returns a status) */
488 return _winreg_InitiateSystemShutdownEx( p, &s );
491 /*******************************************************************
492 _winreg_InitiateSystemShutdownEx
493 ********************************************************************/
495 #define SHUTDOWN_R_STRING "-r"
496 #define SHUTDOWN_F_STRING "-f"
499 WERROR _winreg_InitiateSystemShutdownEx(pipes_struct *p, struct winreg_InitiateSystemShutdownEx *r)
501 char *shutdown_script = NULL;
511 shutdown_script = talloc_strdup(p->mem_ctx, lp_shutdown_script());
512 if (!shutdown_script) {
515 if (!*shutdown_script) {
516 return WERR_ACCESS_DENIED;
519 /* pull the message string and perform necessary sanity checks on it */
521 if ( r->in.message && r->in.message->string ) {
522 if ( (msg = talloc_strdup(p->mem_ctx, r->in.message->string )) == NULL ) {
525 chkmsg = TALLOC_ARRAY(p->mem_ctx, char, strlen(msg)+1);
529 alpha_strcpy(chkmsg, msg, NULL, strlen(msg)+1);
532 fstr_sprintf(str_timeout, "%d", r->in.timeout);
533 fstr_sprintf(do_reboot, r->in.do_reboot ? SHUTDOWN_R_STRING : "");
534 fstr_sprintf(f, r->in.force_apps ? SHUTDOWN_F_STRING : "");
535 fstr_sprintf(str_reason, "%d", r->in.reason );
537 shutdown_script = talloc_all_string_sub(p->mem_ctx,
538 shutdown_script, "%z", chkmsg ? chkmsg : "");
539 if (!shutdown_script) {
542 shutdown_script = talloc_all_string_sub(p->mem_ctx,
543 shutdown_script, "%t", str_timeout);
544 if (!shutdown_script) {
547 shutdown_script = talloc_all_string_sub(p->mem_ctx,
548 shutdown_script, "%r", do_reboot);
549 if (!shutdown_script) {
552 shutdown_script = talloc_all_string_sub(p->mem_ctx,
553 shutdown_script, "%f", f);
554 if (!shutdown_script) {
557 shutdown_script = talloc_all_string_sub(p->mem_ctx,
558 shutdown_script, "%x", str_reason);
559 if (!shutdown_script) {
563 can_shutdown = user_has_privileges( p->server_info->ptok,
564 &se_remote_shutdown );
566 /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
567 Take the error return from the script and provide it as the Windows return code. */
569 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
574 ret = smbrun( shutdown_script, NULL );
579 /********** END SeRemoteShutdownPrivilege BLOCK **********/
581 DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
582 shutdown_script, ret));
584 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
587 /*******************************************************************
588 _winreg_AbortSystemShutdown
589 ********************************************************************/
591 WERROR _winreg_AbortSystemShutdown(pipes_struct *p, struct winreg_AbortSystemShutdown *r)
593 const char *abort_shutdown_script;
597 abort_shutdown_script = lp_abort_shutdown_script();
599 if (!*abort_shutdown_script)
600 return WERR_ACCESS_DENIED;
602 can_shutdown = user_has_privileges( p->server_info->ptok,
603 &se_remote_shutdown );
605 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
610 ret = smbrun( abort_shutdown_script, NULL );
615 /********** END SeRemoteShutdownPrivilege BLOCK **********/
617 DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",
618 abort_shutdown_script, ret));
620 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
623 /*******************************************************************
624 ********************************************************************/
626 static int validate_reg_filename(TALLOC_CTX *ctx, char **pp_fname )
629 int num_services = lp_numservices();
631 const char *share_path;
632 char *fname = *pp_fname;
634 /* convert to a unix path, stripping the C:\ along the way */
636 if (!(p = valid_share_pathname(ctx, fname))) {
640 /* has to exist within a valid file share */
642 for (snum=0; snum<num_services; snum++) {
643 if (!lp_snum_ok(snum) || lp_print_ok(snum)) {
647 share_path = lp_pathname(snum);
649 /* make sure we have a path (e.g. [homes] ) */
650 if (strlen(share_path) == 0) {
654 if (strncmp(share_path, p, strlen(share_path)) == 0) {
660 return (snum < num_services) ? snum : -1;
663 /*******************************************************************
665 ********************************************************************/
667 WERROR _winreg_RestoreKey(pipes_struct *p, struct winreg_RestoreKey *r)
669 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
676 if ( !r->in.filename || !r->in.filename->name )
677 return WERR_INVALID_PARAM;
679 fname = talloc_strdup(p->mem_ctx, r->in.filename->name);
684 DEBUG(8,("_winreg_RestoreKey: verifying restore of key [%s] from "
685 "\"%s\"\n", regkey->key->name, fname));
687 if ((snum = validate_reg_filename(p->mem_ctx, &fname)) == -1)
688 return WERR_OBJECT_PATH_INVALID;
690 /* user must posses SeRestorePrivilege for this this proceed */
692 if ( !user_has_privileges( p->server_info->ptok, &se_restore ) )
693 return WERR_ACCESS_DENIED;
695 DEBUG(2,("_winreg_RestoreKey: Restoring [%s] from %s in share %s\n",
696 regkey->key->name, fname, lp_servicename(snum) ));
698 return reg_restorekey(regkey, fname);
701 /*******************************************************************
703 ********************************************************************/
705 WERROR _winreg_SaveKey(pipes_struct *p, struct winreg_SaveKey *r)
707 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
714 if ( !r->in.filename || !r->in.filename->name )
715 return WERR_INVALID_PARAM;
717 fname = talloc_strdup(p->mem_ctx, r->in.filename->name);
722 DEBUG(8,("_winreg_SaveKey: verifying backup of key [%s] to \"%s\"\n",
723 regkey->key->name, fname));
725 if ((snum = validate_reg_filename(p->mem_ctx, &fname)) == -1 )
726 return WERR_OBJECT_PATH_INVALID;
728 DEBUG(2,("_winreg_SaveKey: Saving [%s] to %s in share %s\n",
729 regkey->key->name, fname, lp_servicename(snum) ));
731 return reg_savekey(regkey, fname);
734 /*******************************************************************
736 ********************************************************************/
738 WERROR _winreg_SaveKeyEx(pipes_struct *p, struct winreg_SaveKeyEx *r)
740 /* fill in your code here if you think this call should
743 p->rng_fault_state = True;
744 return WERR_NOT_SUPPORTED;
747 /*******************************************************************
749 ********************************************************************/
751 WERROR _winreg_CreateKey( pipes_struct *p, struct winreg_CreateKey *r)
753 struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
754 struct registry_key *new_key;
760 DEBUG(10, ("_winreg_CreateKey called with parent key '%s' and "
761 "subkey name '%s'\n", parent->key->name, r->in.name.name));
763 result = reg_createkey(NULL, parent, r->in.name.name, r->in.access_mask,
764 &new_key, r->out.action_taken);
765 if (!W_ERROR_IS_OK(result)) {
769 if (!create_policy_hnd(p, r->out.new_handle, new_key)) {
770 TALLOC_FREE(new_key);
777 /*******************************************************************
779 ********************************************************************/
781 WERROR _winreg_SetValue(pipes_struct *p, struct winreg_SetValue *r)
783 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
784 struct registry_value *val;
790 DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n",
791 key->key->name, r->in.name.name));
793 status = registry_pull_value(p->mem_ctx, &val, r->in.type, r->in.data,
794 r->in.size, r->in.size);
795 if (!W_ERROR_IS_OK(status)) {
799 return reg_setvalue(key, r->in.name.name, val);
802 /*******************************************************************
804 ********************************************************************/
806 WERROR _winreg_DeleteKey(pipes_struct *p, struct winreg_DeleteKey *r)
808 struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
813 return reg_deletekey(parent, r->in.key.name);
817 /*******************************************************************
819 ********************************************************************/
821 WERROR _winreg_DeleteValue(pipes_struct *p, struct winreg_DeleteValue *r)
823 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
828 return reg_deletevalue(key, r->in.value.name);
831 /*******************************************************************
832 _winreg_GetKeySecurity
833 ********************************************************************/
835 WERROR _winreg_GetKeySecurity(pipes_struct *p, struct winreg_GetKeySecurity *r)
837 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
839 struct security_descriptor *secdesc;
846 /* access checks first */
848 if ( !(key->key->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
849 return WERR_ACCESS_DENIED;
851 err = reg_getkeysecurity(p->mem_ctx, key, &secdesc);
852 if (!W_ERROR_IS_OK(err)) {
856 err = ntstatus_to_werror(marshall_sec_desc(p->mem_ctx, secdesc,
858 if (!W_ERROR_IS_OK(err)) {
862 if (len > r->out.sd->size) {
863 r->out.sd->size = len;
864 return WERR_INSUFFICIENT_BUFFER;
867 r->out.sd->size = len;
868 r->out.sd->len = len;
869 r->out.sd->data = data;
874 /*******************************************************************
875 _winreg_SetKeySecurity
876 ********************************************************************/
878 WERROR _winreg_SetKeySecurity(pipes_struct *p, struct winreg_SetKeySecurity *r)
880 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
881 struct security_descriptor *secdesc;
887 /* access checks first */
889 if ( !(key->key->access_granted & STD_RIGHT_WRITE_DAC_ACCESS) )
890 return WERR_ACCESS_DENIED;
892 err = ntstatus_to_werror(unmarshall_sec_desc(p->mem_ctx, r->in.sd->data,
893 r->in.sd->len, &secdesc));
894 if (!W_ERROR_IS_OK(err)) {
898 return reg_setkeysecurity(key, secdesc);
901 /*******************************************************************
903 ********************************************************************/
905 WERROR _winreg_FlushKey(pipes_struct *p, struct winreg_FlushKey *r)
907 /* I'm just replying OK because there's not a lot
908 here I see to do i --jerry */
913 /*******************************************************************
915 ********************************************************************/
917 WERROR _winreg_UnLoadKey(pipes_struct *p, struct winreg_UnLoadKey *r)
919 /* fill in your code here if you think this call should
922 p->rng_fault_state = True;
923 return WERR_NOT_SUPPORTED;
926 /*******************************************************************
928 ********************************************************************/
930 WERROR _winreg_ReplaceKey(pipes_struct *p, struct winreg_ReplaceKey *r)
932 /* fill in your code here if you think this call should
935 p->rng_fault_state = True;
936 return WERR_NOT_SUPPORTED;
939 /*******************************************************************
941 ********************************************************************/
943 WERROR _winreg_LoadKey(pipes_struct *p, struct winreg_LoadKey *r)
945 /* fill in your code here if you think this call should
948 p->rng_fault_state = True;
949 return WERR_NOT_SUPPORTED;
952 /*******************************************************************
953 _winreg_NotifyChangeKeyValue
954 ********************************************************************/
956 WERROR _winreg_NotifyChangeKeyValue(pipes_struct *p, struct winreg_NotifyChangeKeyValue *r)
958 /* fill in your code here if you think this call should
961 p->rng_fault_state = True;
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;