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 );
223
uint8_t *outbuf = NULL;
224
uint32_t outbuf_size = 0;
227
bool free_buf = False;
228
bool free_prs = False;
233
if (r->in.value_name->name == NULL) {
234
return WERR_INVALID_PARAM;
237
if ((r->out.data_length == NULL) || (r->out.type == NULL) || (r->out.data_size == NULL)) {
238
return WERR_INVALID_PARAM;
241
DEBUG(7,("_winreg_QueryValue: policy key name = [%s]\n", regkey->key->name));
242
DEBUG(7,("_winreg_QueryValue: policy key type = [%08x]\n", regkey->key->type));
244
/* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */
245
if(regkey->key->type == REG_KEY_HKPD)
247
if (strequal(r->in.value_name->name, "Global")) {
248
if (!prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL))
250
status = reg_perfcount_get_hkpd(
251
&prs_hkpd, *r->in.data_size, &outbuf_size, NULL);
252
outbuf = (uint8_t *)prs_hkpd.data_p;
255
else if (strequal(r->in.value_name->name, "Counter 009")) {
256
outbuf_size = reg_perfcount_get_counter_names(
257
reg_perfcount_get_base_index(),
258
(char **)(void *)&outbuf);
261
else if (strequal(r->in.value_name->name, "Explain 009")) {
262
outbuf_size = reg_perfcount_get_counter_help(
263
reg_perfcount_get_base_index(),
264
(char **)(void *)&outbuf);
267
else if (isdigit(r->in.value_name->name[0])) {
268
/* we probably have a request for a specific object
270
if (!prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL))
272
status = reg_perfcount_get_hkpd(
273
&prs_hkpd, *r->in.data_size, &outbuf_size,
274
r->in.value_name->name);
275
outbuf = (uint8_t *)prs_hkpd.data_p;
279
DEBUG(3,("Unsupported key name [%s] for HKPD.\n",
280
r->in.value_name->name));
284
*r->out.type = REG_BINARY;
287
struct registry_value *val;
289
status = reg_queryvalue(p->mem_ctx, regkey, r->in.value_name->name,
291
if (!W_ERROR_IS_OK(status)) {
293
DEBUG(10,("_winreg_QueryValue: reg_queryvalue failed with: %s\n",
294
win_errstr(status)));
296
if (r->out.data_size) {
297
*r->out.data_size = 0;
299
if (r->out.data_length) {
300
*r->out.data_length = 0;
305
status = registry_push_value(p->mem_ctx, val, &val_blob);
306
if (!W_ERROR_IS_OK(status)) {
310
outbuf = val_blob.data;
311
outbuf_size = val_blob.length;
312
*r->out.type = val->type;
315
status = WERR_BADFILE;
317
if (*r->in.data_size < outbuf_size) {
318
*r->out.data_size = outbuf_size;
319
status = r->in.data ? WERR_MORE_DATA : WERR_OK;
321
*r->out.data_length = outbuf_size;
322
*r->out.data_size = outbuf_size;
324
memcpy(r->out.data, outbuf, outbuf_size);
329
if (free_prs) prs_mem_free(&prs_hkpd);
330
if (free_buf) SAFE_FREE(outbuf);
335
/*****************************************************************************
337
****************************************************************************/
339
WERROR _winreg_QueryInfoKey(pipes_struct *p, struct winreg_QueryInfoKey *r)
341
WERROR status = WERR_OK;
342
struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
347
r->out.classname->name = NULL;
349
status = reg_queryinfokey(regkey, r->out.num_subkeys, r->out.max_subkeylen,
350
r->out.max_classlen, r->out.num_values, r->out.max_valnamelen,
351
r->out.max_valbufsize, r->out.secdescsize,
352
r->out.last_changed_time);
353
if (!W_ERROR_IS_OK(status)) {
358
* These calculations account for the registry buffers being
359
* UTF-16. They are inexact at best, but so far they worked.
362
*r->out.max_subkeylen *= 2;
364
*r->out.max_valnamelen += 1;
365
*r->out.max_valnamelen *= 2;
371
/*****************************************************************************
373
****************************************************************************/
375
WERROR _winreg_GetVersion(pipes_struct *p, struct winreg_GetVersion *r)
377
struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
382
return reg_getversion(r->out.version);
386
/*****************************************************************************
388
****************************************************************************/
390
WERROR _winreg_EnumKey(pipes_struct *p, struct winreg_EnumKey *r)
393
struct registry_key *key = find_regkey_by_hnd( p, r->in.handle );
398
if ( !r->in.name || !r->in.keyclass )
399
return WERR_INVALID_PARAM;
401
DEBUG(8,("_reg_enum_key: enumerating key [%s]\n", key->key->name));
403
err = reg_enumkey(p->mem_ctx, key, r->in.enum_index, (char **)&r->out.name->name,
404
r->out.last_changed_time);
405
if (!W_ERROR_IS_OK(err)) {
408
r->out.keyclass->name = "";
412
/*****************************************************************************
414
****************************************************************************/
416
WERROR _winreg_EnumValue(pipes_struct *p, struct winreg_EnumValue *r)
419
struct registry_key *key = find_regkey_by_hnd( p, r->in.handle );
421
struct registry_value *val;
422
DATA_BLOB value_blob;
428
return WERR_INVALID_PARAM;
430
DEBUG(8,("_winreg_EnumValue: enumerating values for key [%s]\n",
433
err = reg_enumvalue(p->mem_ctx, key, r->in.enum_index, &valname, &val);
434
if (!W_ERROR_IS_OK(err)) {
438
err = registry_push_value(p->mem_ctx, val, &value_blob);
439
if (!W_ERROR_IS_OK(err)) {
443
if (r->out.name != NULL) {
444
r->out.name->name = valname;
447
if (r->out.type != NULL) {
448
*r->out.type = val->type;
451
if (r->out.value != NULL) {
452
if ((r->out.size == NULL) || (r->out.length == NULL)) {
453
return WERR_INVALID_PARAM;
456
if (value_blob.length > *r->out.size) {
457
return WERR_MORE_DATA;
460
memcpy( r->out.value, value_blob.data, value_blob.length );
463
if (r->out.length != NULL) {
464
*r->out.length = value_blob.length;
466
if (r->out.size != NULL) {
467
*r->out.size = value_blob.length;
473
/*******************************************************************
474
_winreg_InitiateSystemShutdown
475
********************************************************************/
477
WERROR _winreg_InitiateSystemShutdown(pipes_struct *p, struct winreg_InitiateSystemShutdown *r)
479
struct winreg_InitiateSystemShutdownEx s;
481
s.in.hostname = r->in.hostname;
482
s.in.message = r->in.message;
483
s.in.timeout = r->in.timeout;
484
s.in.force_apps = r->in.force_apps;
485
s.in.do_reboot = r->in.do_reboot;
488
/* thunk down to _winreg_InitiateSystemShutdownEx()
489
(just returns a status) */
491
return _winreg_InitiateSystemShutdownEx( p, &s );
494
/*******************************************************************
495
_winreg_InitiateSystemShutdownEx
496
********************************************************************/
498
#define SHUTDOWN_R_STRING "-r"
499
#define SHUTDOWN_F_STRING "-f"
502
WERROR _winreg_InitiateSystemShutdownEx(pipes_struct *p, struct winreg_InitiateSystemShutdownEx *r)
504
char *shutdown_script = NULL;
514
shutdown_script = talloc_strdup(p->mem_ctx, lp_shutdown_script());
515
if (!shutdown_script) {
518
if (!*shutdown_script) {
519
return WERR_ACCESS_DENIED;
522
/* pull the message string and perform necessary sanity checks on it */
524
if ( r->in.message && r->in.message->string ) {
525
if ( (msg = talloc_strdup(p->mem_ctx, r->in.message->string )) == NULL ) {
528
chkmsg = TALLOC_ARRAY(p->mem_ctx, char, strlen(msg)+1);
532
alpha_strcpy(chkmsg, msg, NULL, strlen(msg)+1);
535
fstr_sprintf(str_timeout, "%d", r->in.timeout);
536
fstr_sprintf(do_reboot, r->in.do_reboot ? SHUTDOWN_R_STRING : "");
537
fstr_sprintf(f, r->in.force_apps ? SHUTDOWN_F_STRING : "");
538
fstr_sprintf(str_reason, "%d", r->in.reason );
540
shutdown_script = talloc_all_string_sub(p->mem_ctx,
541
shutdown_script, "%z", chkmsg ? chkmsg : "");
542
if (!shutdown_script) {
545
shutdown_script = talloc_all_string_sub(p->mem_ctx,
546
shutdown_script, "%t", str_timeout);
547
if (!shutdown_script) {
550
shutdown_script = talloc_all_string_sub(p->mem_ctx,
551
shutdown_script, "%r", do_reboot);
552
if (!shutdown_script) {
555
shutdown_script = talloc_all_string_sub(p->mem_ctx,
556
shutdown_script, "%f", f);
557
if (!shutdown_script) {
560
shutdown_script = talloc_all_string_sub(p->mem_ctx,
561
shutdown_script, "%x", str_reason);
562
if (!shutdown_script) {
566
can_shutdown = user_has_privileges( p->server_info->ptok,
567
&se_remote_shutdown );
569
/* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
570
Take the error return from the script and provide it as the Windows return code. */
572
/********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
577
ret = smbrun( shutdown_script, NULL );
582
/********** END SeRemoteShutdownPrivilege BLOCK **********/
584
DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
585
shutdown_script, ret));
587
return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
590
/*******************************************************************
591
_winreg_AbortSystemShutdown
592
********************************************************************/
594
WERROR _winreg_AbortSystemShutdown(pipes_struct *p, struct winreg_AbortSystemShutdown *r)
596
const char *abort_shutdown_script;
600
abort_shutdown_script = lp_abort_shutdown_script();
602
if (!*abort_shutdown_script)
603
return WERR_ACCESS_DENIED;
605
can_shutdown = user_has_privileges( p->server_info->ptok,
606
&se_remote_shutdown );
608
/********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
613
ret = smbrun( abort_shutdown_script, NULL );
618
/********** END SeRemoteShutdownPrivilege BLOCK **********/
620
DEBUG(3,("_reg_abort_shutdown: Running the command `%s' gave %d\n",
621
abort_shutdown_script, ret));
623
return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
626
/*******************************************************************
627
********************************************************************/
629
static int validate_reg_filename(TALLOC_CTX *ctx, char **pp_fname )
632
int num_services = lp_numservices();
634
const char *share_path;
635
char *fname = *pp_fname;
637
/* convert to a unix path, stripping the C:\ along the way */
639
if (!(p = valid_share_pathname(ctx, fname))) {
643
/* has to exist within a valid file share */
645
for (snum=0; snum<num_services; snum++) {
646
if (!lp_snum_ok(snum) || lp_print_ok(snum)) {
650
share_path = lp_pathname(snum);
652
/* make sure we have a path (e.g. [homes] ) */
653
if (strlen(share_path) == 0) {
657
if (strncmp(share_path, p, strlen(share_path)) == 0) {
663
return (snum < num_services) ? snum : -1;
666
/*******************************************************************
668
********************************************************************/
670
WERROR _winreg_RestoreKey(pipes_struct *p, struct winreg_RestoreKey *r)
672
struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
679
if ( !r->in.filename || !r->in.filename->name )
680
return WERR_INVALID_PARAM;
682
fname = talloc_strdup(p->mem_ctx, r->in.filename->name);
687
DEBUG(8,("_winreg_RestoreKey: verifying restore of key [%s] from "
688
"\"%s\"\n", regkey->key->name, fname));
690
if ((snum = validate_reg_filename(p->mem_ctx, &fname)) == -1)
691
return WERR_OBJECT_PATH_INVALID;
693
/* user must posses SeRestorePrivilege for this this proceed */
695
if ( !user_has_privileges( p->server_info->ptok, &se_restore ) )
696
return WERR_ACCESS_DENIED;
698
DEBUG(2,("_winreg_RestoreKey: Restoring [%s] from %s in share %s\n",
699
regkey->key->name, fname, lp_servicename(snum) ));
701
return reg_restorekey(regkey, fname);
704
/*******************************************************************
706
********************************************************************/
708
WERROR _winreg_SaveKey(pipes_struct *p, struct winreg_SaveKey *r)
710
struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
717
if ( !r->in.filename || !r->in.filename->name )
718
return WERR_INVALID_PARAM;
720
fname = talloc_strdup(p->mem_ctx, r->in.filename->name);
725
DEBUG(8,("_winreg_SaveKey: verifying backup of key [%s] to \"%s\"\n",
726
regkey->key->name, fname));
728
if ((snum = validate_reg_filename(p->mem_ctx, &fname)) == -1 )
729
return WERR_OBJECT_PATH_INVALID;
731
DEBUG(2,("_winreg_SaveKey: Saving [%s] to %s in share %s\n",
732
regkey->key->name, fname, lp_servicename(snum) ));
734
return reg_savekey(regkey, fname);
737
/*******************************************************************
739
********************************************************************/
741
WERROR _winreg_SaveKeyEx(pipes_struct *p, struct winreg_SaveKeyEx *r)
743
/* fill in your code here if you think this call should
746
p->rng_fault_state = True;
747
return WERR_NOT_SUPPORTED;
750
/*******************************************************************
752
********************************************************************/
754
WERROR _winreg_CreateKey( pipes_struct *p, struct winreg_CreateKey *r)
756
struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
757
struct registry_key *new_key;
763
DEBUG(10, ("_winreg_CreateKey called with parent key '%s' and "
764
"subkey name '%s'\n", parent->key->name, r->in.name.name));
766
result = reg_createkey(NULL, parent, r->in.name.name, r->in.access_mask,
767
&new_key, r->out.action_taken);
768
if (!W_ERROR_IS_OK(result)) {
772
if (!create_policy_hnd(p, r->out.new_handle, new_key)) {
773
TALLOC_FREE(new_key);
780
/*******************************************************************
782
********************************************************************/
784
WERROR _winreg_SetValue(pipes_struct *p, struct winreg_SetValue *r)
786
struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
787
struct registry_value *val;
793
DEBUG(8,("_reg_set_value: Setting value for [%s:%s]\n",
794
key->key->name, r->in.name.name));
796
status = registry_pull_value(p->mem_ctx, &val, r->in.type, r->in.data,
797
r->in.size, r->in.size);
798
if (!W_ERROR_IS_OK(status)) {
802
return reg_setvalue(key, r->in.name.name, val);
805
/*******************************************************************
807
********************************************************************/
809
WERROR _winreg_DeleteKey(pipes_struct *p, struct winreg_DeleteKey *r)
811
struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
816
return reg_deletekey(parent, r->in.key.name);
820
/*******************************************************************
822
********************************************************************/
824
WERROR _winreg_DeleteValue(pipes_struct *p, struct winreg_DeleteValue *r)
826
struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
831
return reg_deletevalue(key, r->in.value.name);
834
/*******************************************************************
835
_winreg_GetKeySecurity
836
********************************************************************/
838
WERROR _winreg_GetKeySecurity(pipes_struct *p, struct winreg_GetKeySecurity *r)
840
struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
842
struct security_descriptor *secdesc;
849
/* access checks first */
851
if ( !(key->key->access_granted & STD_RIGHT_READ_CONTROL_ACCESS) )
852
return WERR_ACCESS_DENIED;
854
err = reg_getkeysecurity(p->mem_ctx, key, &secdesc);
855
if (!W_ERROR_IS_OK(err)) {
859
err = ntstatus_to_werror(marshall_sec_desc(p->mem_ctx, secdesc,
861
if (!W_ERROR_IS_OK(err)) {
865
if (len > r->out.sd->size) {
866
r->out.sd->size = len;
867
return WERR_INSUFFICIENT_BUFFER;
870
r->out.sd->size = len;
871
r->out.sd->len = len;
872
r->out.sd->data = data;
877
/*******************************************************************
878
_winreg_SetKeySecurity
879
********************************************************************/
881
WERROR _winreg_SetKeySecurity(pipes_struct *p, struct winreg_SetKeySecurity *r)
883
struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
884
struct security_descriptor *secdesc;
890
/* access checks first */
892
if ( !(key->key->access_granted & STD_RIGHT_WRITE_DAC_ACCESS) )
893
return WERR_ACCESS_DENIED;
895
err = ntstatus_to_werror(unmarshall_sec_desc(p->mem_ctx, r->in.sd->data,
896
r->in.sd->len, &secdesc));
897
if (!W_ERROR_IS_OK(err)) {
901
return reg_setkeysecurity(key, secdesc);
904
/*******************************************************************
906
********************************************************************/
908
WERROR _winreg_FlushKey(pipes_struct *p, struct winreg_FlushKey *r)
910
/* I'm just replying OK because there's not a lot
911
here I see to do i --jerry */
916
/*******************************************************************
918
********************************************************************/
920
WERROR _winreg_UnLoadKey(pipes_struct *p, struct winreg_UnLoadKey *r)
922
/* fill in your code here if you think this call should
925
p->rng_fault_state = True;
926
return WERR_NOT_SUPPORTED;
929
/*******************************************************************
931
********************************************************************/
933
WERROR _winreg_ReplaceKey(pipes_struct *p, struct winreg_ReplaceKey *r)
935
/* fill in your code here if you think this call should
938
p->rng_fault_state = True;
939
return WERR_NOT_SUPPORTED;
942
/*******************************************************************
944
********************************************************************/
946
WERROR _winreg_LoadKey(pipes_struct *p, struct winreg_LoadKey *r)
948
/* fill in your code here if you think this call should
951
p->rng_fault_state = True;
952
return WERR_NOT_SUPPORTED;
955
/*******************************************************************
956
_winreg_NotifyChangeKeyValue
957
********************************************************************/
959
WERROR _winreg_NotifyChangeKeyValue(pipes_struct *p, struct winreg_NotifyChangeKeyValue *r)
961
return WERR_NOT_SUPPORTED;
964
/*******************************************************************
965
_winreg_QueryMultipleValues
966
********************************************************************/
968
WERROR _winreg_QueryMultipleValues(pipes_struct *p, struct winreg_QueryMultipleValues *r)
970
/* fill in your code here if you think this call should
973
p->rng_fault_state = True;
974
return WERR_NOT_SUPPORTED;
977
/*******************************************************************
978
_winreg_QueryMultipleValues2
979
********************************************************************/
981
WERROR _winreg_QueryMultipleValues2(pipes_struct *p, struct winreg_QueryMultipleValues2 *r)
983
/* fill in your code here if you think this call should
986
p->rng_fault_state = True;
987
return WERR_NOT_SUPPORTED;