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. */
25 #include "../librpc/gen_ndr/srv_winreg.h"
27 #include "registry/reg_api.h"
28 #include "registry/reg_perfcount.h"
31 #include "lib/privileges.h"
32 #include "libcli/security/secdesc.h"
35 #define DBGC_CLASS DBGC_RPC_SRV
37 /******************************************************************
38 Find a registry key handle and return a struct registry_key *
39 *****************************************************************/
41 static struct registry_key *find_regkey_by_hnd(struct pipes_struct *p,
42 struct policy_handle *hnd)
44 struct registry_key *regkey = NULL;
46 if(!find_policy_by_hnd(p,hnd,(void **)(void *)®key)) {
47 DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: "));
54 /*******************************************************************
55 Function for open a new registry handle and creating a handle
56 Note that P should be valid & hnd should already have space
58 When we open a key, we store the full path to the key as
59 HK[LM|U]\<key>\<key>\...
60 *******************************************************************/
62 static WERROR open_registry_key(struct pipes_struct *p,
63 struct policy_handle *hnd,
64 struct registry_key *parent,
65 const char *subkeyname,
66 uint32_t access_desired)
68 WERROR result = WERR_OK;
69 struct registry_key *key;
72 result = reg_openhive(p->mem_ctx, subkeyname, access_desired,
73 p->session_info->security_token, &key);
76 result = reg_openkey(p->mem_ctx, parent, subkeyname,
77 access_desired, &key);
80 if ( !W_ERROR_IS_OK(result) ) {
84 if ( !create_policy_hnd( p, hnd, key ) ) {
85 return WERR_FILE_NOT_FOUND;
91 /*******************************************************************
92 Function for open a new registry handle and creating a handle
93 Note that P should be valid & hnd should already have space
94 *******************************************************************/
96 static bool close_registry_key(struct pipes_struct *p,
97 struct policy_handle *hnd)
99 struct registry_key *regkey = find_regkey_by_hnd(p, hnd);
102 DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n",
107 close_policy_hnd(p, hnd);
112 /********************************************************************
114 ********************************************************************/
116 WERROR _winreg_CloseKey(struct pipes_struct *p,
117 struct winreg_CloseKey *r)
119 /* close the policy handle */
121 if (!close_registry_key(p, r->in.handle))
122 return WERR_INVALID_HANDLE;
124 ZERO_STRUCTP(r->out.handle);
129 /*******************************************************************
131 ********************************************************************/
133 WERROR _winreg_OpenHKLM(struct pipes_struct *p,
134 struct winreg_OpenHKLM *r)
136 return open_registry_key(p, r->out.handle, NULL, KEY_HKLM, r->in.access_mask);
139 /*******************************************************************
141 ********************************************************************/
143 WERROR _winreg_OpenHKPD(struct pipes_struct *p,
144 struct winreg_OpenHKPD *r)
146 return open_registry_key(p, r->out.handle, NULL, KEY_HKPD, r->in.access_mask);
149 /*******************************************************************
151 ********************************************************************/
153 WERROR _winreg_OpenHKPT(struct pipes_struct *p,
154 struct winreg_OpenHKPT *r)
156 return open_registry_key(p, r->out.handle, NULL, KEY_HKPT, r->in.access_mask);
159 /*******************************************************************
161 ********************************************************************/
163 WERROR _winreg_OpenHKCR(struct pipes_struct *p,
164 struct winreg_OpenHKCR *r)
166 return open_registry_key(p, r->out.handle, NULL, KEY_HKCR, r->in.access_mask);
169 /*******************************************************************
171 ********************************************************************/
173 WERROR _winreg_OpenHKU(struct pipes_struct *p,
174 struct winreg_OpenHKU *r)
176 return open_registry_key(p, r->out.handle, NULL, KEY_HKU, r->in.access_mask);
179 /*******************************************************************
181 ********************************************************************/
183 WERROR _winreg_OpenHKCU(struct pipes_struct *p,
184 struct winreg_OpenHKCU *r)
186 return open_registry_key(p, r->out.handle, NULL, KEY_HKCU, r->in.access_mask);
189 /*******************************************************************
191 ********************************************************************/
193 WERROR _winreg_OpenHKCC(struct pipes_struct *p,
194 struct winreg_OpenHKCC *r)
196 return open_registry_key(p, r->out.handle, NULL, KEY_HKCC, r->in.access_mask);
199 /*******************************************************************
201 ********************************************************************/
203 WERROR _winreg_OpenHKDD(struct pipes_struct *p,
204 struct winreg_OpenHKDD *r)
206 return open_registry_key(p, r->out.handle, NULL, KEY_HKDD, r->in.access_mask);
209 /*******************************************************************
211 ********************************************************************/
213 WERROR _winreg_OpenHKPN(struct pipes_struct *p,
214 struct winreg_OpenHKPN *r)
216 return open_registry_key(p, r->out.handle, NULL, KEY_HKPN, r->in.access_mask);
219 /*******************************************************************
221 ********************************************************************/
223 WERROR _winreg_OpenKey(struct pipes_struct *p,
224 struct winreg_OpenKey *r)
226 struct registry_key *parent = find_regkey_by_hnd(p, r->in.parent_handle );
229 return WERR_INVALID_HANDLE;
231 return open_registry_key(p, r->out.handle, parent, r->in.keyname.name, r->in.access_mask);
234 /*******************************************************************
236 ********************************************************************/
238 WERROR _winreg_QueryValue(struct pipes_struct *p,
239 struct winreg_QueryValue *r)
241 WERROR status = WERR_FILE_NOT_FOUND;
242 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
245 uint8_t *outbuf = NULL;
246 uint32_t outbuf_size = 0;
248 bool free_buf = False;
249 bool free_prs = False;
252 return WERR_INVALID_HANDLE;
254 if (r->in.value_name->name == NULL) {
255 return WERR_INVALID_PARAMETER;
258 if ((r->out.data_length == NULL) || (r->out.type == NULL) || (r->out.data_size == NULL)) {
259 return WERR_INVALID_PARAMETER;
262 DEBUG(7,("_winreg_QueryValue: policy key name = [%s]\n", regkey->key->name));
263 DEBUG(7,("_winreg_QueryValue: policy key type = [%08x]\n", regkey->key->type));
265 /* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */
266 if(regkey->key->type == REG_KEY_HKPD)
268 if (strequal(r->in.value_name->name, "Global")) {
269 if (!prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL))
270 return WERR_NOT_ENOUGH_MEMORY;
271 status = reg_perfcount_get_hkpd(
272 &prs_hkpd, *r->in.data_size, &outbuf_size, NULL);
273 outbuf = (uint8_t *)prs_hkpd.data_p;
276 else if (strequal(r->in.value_name->name, "Counter 009")) {
277 outbuf_size = reg_perfcount_get_counter_names(
278 reg_perfcount_get_base_index(),
279 (char **)(void *)&outbuf);
282 else if (strequal(r->in.value_name->name, "Explain 009")) {
283 outbuf_size = reg_perfcount_get_counter_help(
284 reg_perfcount_get_base_index(),
285 (char **)(void *)&outbuf);
288 else if (isdigit(r->in.value_name->name[0])) {
289 /* we probably have a request for a specific object
291 if (!prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL))
292 return WERR_NOT_ENOUGH_MEMORY;
293 status = reg_perfcount_get_hkpd(
294 &prs_hkpd, *r->in.data_size, &outbuf_size,
295 r->in.value_name->name);
296 outbuf = (uint8_t *)prs_hkpd.data_p;
300 DEBUG(3,("Unsupported key name [%s] for HKPD.\n",
301 r->in.value_name->name));
302 return WERR_FILE_NOT_FOUND;
305 *r->out.type = REG_BINARY;
308 struct registry_value *val;
310 status = reg_queryvalue(p->mem_ctx, regkey, r->in.value_name->name,
312 if (!W_ERROR_IS_OK(status)) {
314 DEBUG(10,("_winreg_QueryValue: reg_queryvalue failed with: %s\n",
315 win_errstr(status)));
317 if (r->out.data_size) {
318 *r->out.data_size = 0;
320 if (r->out.data_length) {
321 *r->out.data_length = 0;
326 outbuf = val->data.data;
327 outbuf_size = val->data.length;
328 *r->out.type = val->type;
331 status = WERR_FILE_NOT_FOUND;
333 if (*r->in.data_size < outbuf_size) {
334 *r->out.data_size = outbuf_size;
335 status = r->in.data ? WERR_MORE_DATA : WERR_OK;
337 *r->out.data_length = outbuf_size;
338 *r->out.data_size = outbuf_size;
340 memcpy(r->out.data, outbuf, outbuf_size);
345 if (free_prs) prs_mem_free(&prs_hkpd);
346 if (free_buf) SAFE_FREE(outbuf);
351 /*****************************************************************************
353 ****************************************************************************/
355 WERROR _winreg_QueryInfoKey(struct pipes_struct *p,
356 struct winreg_QueryInfoKey *r)
358 WERROR status = WERR_OK;
359 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
362 return WERR_INVALID_HANDLE;
364 r->out.classname->name = NULL;
366 status = reg_queryinfokey(regkey, r->out.num_subkeys, r->out.max_subkeylen,
367 r->out.max_classlen, r->out.num_values, r->out.max_valnamelen,
368 r->out.max_valbufsize, r->out.secdescsize,
369 r->out.last_changed_time);
370 if (!W_ERROR_IS_OK(status)) {
375 * These calculations account for the registry buffers being
376 * UTF-16. They are inexact at best, but so far they worked.
379 *r->out.max_subkeylen *= 2;
381 *r->out.max_valnamelen += 1;
382 *r->out.max_valnamelen *= 2;
388 /*****************************************************************************
390 ****************************************************************************/
392 WERROR _winreg_GetVersion(struct pipes_struct *p,
393 struct winreg_GetVersion *r)
395 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
398 return WERR_INVALID_HANDLE;
400 return reg_getversion(r->out.version);
404 /*****************************************************************************
406 ****************************************************************************/
408 WERROR _winreg_EnumKey(struct pipes_struct *p,
409 struct winreg_EnumKey *r)
411 WERROR err = WERR_OK;
412 struct registry_key *key = find_regkey_by_hnd( p, r->in.handle );
416 return WERR_INVALID_HANDLE;
418 if ( !r->in.name || !r->in.keyclass )
419 return WERR_INVALID_PARAMETER;
421 DEBUG(8,("_winreg_EnumKey: enumerating key [%s]\n", key->key->name));
423 err = reg_enumkey(p->mem_ctx, key, r->in.enum_index, &name,
424 r->out.last_changed_time);
425 if (!W_ERROR_IS_OK(err)) {
428 r->out.name->name = name;
429 r->out.keyclass->name = "";
433 /*****************************************************************************
435 ****************************************************************************/
437 WERROR _winreg_EnumValue(struct pipes_struct *p,
438 struct winreg_EnumValue *r)
440 WERROR err = WERR_OK;
441 struct registry_key *key = find_regkey_by_hnd( p, r->in.handle );
442 char *valname = NULL;
443 struct registry_value *val = NULL;
446 return WERR_INVALID_HANDLE;
449 return WERR_INVALID_PARAMETER;
451 DEBUG(8,("_winreg_EnumValue: enumerating values for key [%s]\n",
454 err = reg_enumvalue(p->mem_ctx, key, r->in.enum_index, &valname, &val);
455 if (!W_ERROR_IS_OK(err)) {
459 if (r->out.name != NULL) {
460 r->out.name->name = valname;
463 if (r->out.type != NULL) {
464 *r->out.type = val->type;
467 if (r->out.value != NULL) {
468 if ((r->out.size == NULL) || (r->out.length == NULL)) {
469 return WERR_INVALID_PARAMETER;
472 if (val->data.length > *r->out.size) {
473 return WERR_MORE_DATA;
476 memcpy( r->out.value, val->data.data, val->data.length );
479 if (r->out.length != NULL) {
480 *r->out.length = val->data.length;
482 if (r->out.size != NULL) {
483 *r->out.size = val->data.length;
489 /*******************************************************************
490 _winreg_InitiateSystemShutdown
491 ********************************************************************/
493 WERROR _winreg_InitiateSystemShutdown(struct pipes_struct *p,
494 struct winreg_InitiateSystemShutdown *r)
496 struct winreg_InitiateSystemShutdownEx s;
498 s.in.hostname = r->in.hostname;
499 s.in.message = r->in.message;
500 s.in.timeout = r->in.timeout;
501 s.in.force_apps = r->in.force_apps;
502 s.in.do_reboot = r->in.do_reboot;
505 /* thunk down to _winreg_InitiateSystemShutdownEx()
506 (just returns a status) */
508 return _winreg_InitiateSystemShutdownEx( p, &s );
511 /*******************************************************************
512 _winreg_InitiateSystemShutdownEx
513 ********************************************************************/
515 #define SHUTDOWN_R_STRING "-r"
516 #define SHUTDOWN_F_STRING "-f"
519 WERROR _winreg_InitiateSystemShutdownEx(struct pipes_struct *p,
520 struct winreg_InitiateSystemShutdownEx *r)
522 const struct loadparm_substitution *lp_sub =
523 loadparm_s3_global_substitution();
524 char *shutdown_script = NULL;
531 bool can_shutdown = false;
533 shutdown_script = lp_shutdown_script(p->mem_ctx, lp_sub);
534 if (!shutdown_script) {
535 return WERR_NOT_ENOUGH_MEMORY;
537 if (!*shutdown_script) {
538 return WERR_ACCESS_DENIED;
541 /* pull the message string and perform necessary sanity checks on it */
543 if ( r->in.message && r->in.message->string ) {
544 chkmsg = talloc_alpha_strcpy(p->mem_ctx,
545 r->in.message->string,
547 if (chkmsg == NULL) {
548 return WERR_NOT_ENOUGH_MEMORY;
552 fstr_sprintf(str_timeout, "%d", r->in.timeout);
553 fstr_sprintf(do_reboot, r->in.do_reboot ? SHUTDOWN_R_STRING : "");
554 fstr_sprintf(f, r->in.force_apps ? SHUTDOWN_F_STRING : "");
555 fstr_sprintf(str_reason, "%d", r->in.reason );
557 shutdown_script = talloc_all_string_sub(p->mem_ctx,
558 shutdown_script, "%z", chkmsg ? chkmsg : "");
559 if (!shutdown_script) {
560 return WERR_NOT_ENOUGH_MEMORY;
562 shutdown_script = talloc_all_string_sub(p->mem_ctx,
563 shutdown_script, "%t", str_timeout);
564 if (!shutdown_script) {
565 return WERR_NOT_ENOUGH_MEMORY;
567 shutdown_script = talloc_all_string_sub(p->mem_ctx,
568 shutdown_script, "%r", do_reboot);
569 if (!shutdown_script) {
570 return WERR_NOT_ENOUGH_MEMORY;
572 shutdown_script = talloc_all_string_sub(p->mem_ctx,
573 shutdown_script, "%f", f);
574 if (!shutdown_script) {
575 return WERR_NOT_ENOUGH_MEMORY;
577 shutdown_script = talloc_all_string_sub(p->mem_ctx,
578 shutdown_script, "%x", str_reason);
579 if (!shutdown_script) {
580 return WERR_NOT_ENOUGH_MEMORY;
583 can_shutdown = security_token_has_privilege(p->session_info->security_token, SEC_PRIV_REMOTE_SHUTDOWN);
585 /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
586 Take the error return from the script and provide it as the Windows return code. */
588 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
593 ret = smbrun(shutdown_script, NULL, NULL);
598 /********** END SeRemoteShutdownPrivilege BLOCK **********/
600 DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
601 shutdown_script, ret));
603 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
606 /*******************************************************************
607 _winreg_AbortSystemShutdown
608 ********************************************************************/
610 WERROR _winreg_AbortSystemShutdown(struct pipes_struct *p,
611 struct winreg_AbortSystemShutdown *r)
613 const char *abort_shutdown_script = NULL;
614 const struct loadparm_substitution *lp_sub =
615 loadparm_s3_global_substitution();
617 bool can_shutdown = false;
619 abort_shutdown_script = lp_abort_shutdown_script(talloc_tos(), lp_sub);
620 if (!*abort_shutdown_script)
621 return WERR_ACCESS_DENIED;
623 can_shutdown = security_token_has_privilege(p->session_info->security_token, SEC_PRIV_REMOTE_SHUTDOWN);
625 /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
630 ret = smbrun(abort_shutdown_script, NULL, NULL);
635 /********** END SeRemoteShutdownPrivilege BLOCK **********/
637 DEBUG(3,("_winreg_AbortSystemShutdown: Running the command `%s' gave %d\n",
638 abort_shutdown_script, ret));
640 return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
643 /*******************************************************************
645 ********************************************************************/
647 WERROR _winreg_RestoreKey(struct pipes_struct *p,
648 struct winreg_RestoreKey *r)
650 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
653 return WERR_INVALID_HANDLE;
655 return WERR_BAD_PATHNAME;
658 /*******************************************************************
660 ********************************************************************/
662 WERROR _winreg_SaveKey(struct pipes_struct *p,
663 struct winreg_SaveKey *r)
665 struct registry_key *regkey = find_regkey_by_hnd( p, r->in.handle );
668 return WERR_INVALID_HANDLE;
670 return WERR_BAD_PATHNAME;
673 /*******************************************************************
675 ********************************************************************/
677 WERROR _winreg_SaveKeyEx(struct pipes_struct *p,
678 struct winreg_SaveKeyEx *r)
680 /* fill in your code here if you think this call should
683 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
684 return WERR_NOT_SUPPORTED;
687 /*******************************************************************
689 ********************************************************************/
691 WERROR _winreg_CreateKey(struct pipes_struct *p,
692 struct winreg_CreateKey *r)
694 struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
695 struct registry_key *new_key = NULL;
696 WERROR result = WERR_OK;
699 return WERR_INVALID_HANDLE;
701 DEBUG(10, ("_winreg_CreateKey called with parent key '%s' and "
702 "subkey name '%s'\n", parent->key->name, r->in.name.name));
704 result = reg_createkey(NULL, parent, r->in.name.name, r->in.access_mask,
705 &new_key, r->out.action_taken);
706 if (!W_ERROR_IS_OK(result)) {
710 if (!create_policy_hnd(p, r->out.new_handle, new_key)) {
711 TALLOC_FREE(new_key);
712 return WERR_FILE_NOT_FOUND;
718 /*******************************************************************
720 ********************************************************************/
722 WERROR _winreg_SetValue(struct pipes_struct *p,
723 struct winreg_SetValue *r)
725 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
726 struct registry_value *val = NULL;
729 return WERR_INVALID_HANDLE;
731 DEBUG(8,("_winreg_SetValue: Setting value for [%s:%s]\n",
732 key->key->name, r->in.name.name));
734 val = talloc_zero(p->mem_ctx, struct registry_value);
736 return WERR_NOT_ENOUGH_MEMORY;
739 val->type = r->in.type;
740 val->data = data_blob_talloc(p->mem_ctx, r->in.data, r->in.size);
742 return reg_setvalue(key, r->in.name.name, val);
745 /*******************************************************************
747 ********************************************************************/
749 WERROR _winreg_DeleteKey(struct pipes_struct *p,
750 struct winreg_DeleteKey *r)
752 struct registry_key *parent = find_regkey_by_hnd(p, r->in.handle);
755 return WERR_INVALID_HANDLE;
757 return reg_deletekey(parent, r->in.key.name);
761 /*******************************************************************
763 ********************************************************************/
765 WERROR _winreg_DeleteValue(struct pipes_struct *p,
766 struct winreg_DeleteValue *r)
768 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
771 return WERR_INVALID_HANDLE;
773 return reg_deletevalue(key, r->in.value.name);
776 /*******************************************************************
777 _winreg_GetKeySecurity
778 ********************************************************************/
780 WERROR _winreg_GetKeySecurity(struct pipes_struct *p,
781 struct winreg_GetKeySecurity *r)
783 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
784 WERROR err = WERR_OK;
785 struct security_descriptor *secdesc = NULL;
786 uint8_t *data = NULL;
790 return WERR_INVALID_HANDLE;
792 /* access checks first */
794 if ( !(key->key->access_granted & SEC_STD_READ_CONTROL) )
795 return WERR_ACCESS_DENIED;
797 err = reg_getkeysecurity(p->mem_ctx, key, &secdesc);
798 if (!W_ERROR_IS_OK(err)) {
802 err = ntstatus_to_werror(marshall_sec_desc(p->mem_ctx, secdesc,
804 if (!W_ERROR_IS_OK(err)) {
808 if (len > r->out.sd->size) {
809 r->out.sd->size = len;
810 return WERR_INSUFFICIENT_BUFFER;
813 r->out.sd->size = len;
814 r->out.sd->len = len;
815 r->out.sd->data = data;
820 /*******************************************************************
821 _winreg_SetKeySecurity
822 ********************************************************************/
824 WERROR _winreg_SetKeySecurity(struct pipes_struct *p,
825 struct winreg_SetKeySecurity *r)
827 struct registry_key *key = find_regkey_by_hnd(p, r->in.handle);
828 struct security_descriptor *secdesc = NULL;
829 WERROR err = WERR_OK;
832 return WERR_INVALID_HANDLE;
834 /* access checks first */
836 if ( !(key->key->access_granted & SEC_STD_WRITE_DAC) )
837 return WERR_ACCESS_DENIED;
839 err = ntstatus_to_werror(unmarshall_sec_desc(p->mem_ctx, r->in.sd->data,
840 r->in.sd->len, &secdesc));
841 if (!W_ERROR_IS_OK(err)) {
845 return reg_setkeysecurity(key, secdesc);
848 /*******************************************************************
850 ********************************************************************/
852 WERROR _winreg_FlushKey(struct pipes_struct *p,
853 struct winreg_FlushKey *r)
855 /* I'm just replying OK because there's not a lot
856 here I see to do i --jerry */
861 /*******************************************************************
863 ********************************************************************/
865 WERROR _winreg_UnLoadKey(struct pipes_struct *p,
866 struct winreg_UnLoadKey *r)
868 /* fill in your code here if you think this call should
871 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
872 return WERR_NOT_SUPPORTED;
875 /*******************************************************************
877 ********************************************************************/
879 WERROR _winreg_ReplaceKey(struct pipes_struct *p,
880 struct winreg_ReplaceKey *r)
882 /* fill in your code here if you think this call should
885 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
886 return WERR_NOT_SUPPORTED;
889 /*******************************************************************
891 ********************************************************************/
893 WERROR _winreg_LoadKey(struct pipes_struct *p,
894 struct winreg_LoadKey *r)
896 /* fill in your code here if you think this call should
899 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
900 return WERR_NOT_SUPPORTED;
903 /*******************************************************************
904 _winreg_NotifyChangeKeyValue
905 ********************************************************************/
907 WERROR _winreg_NotifyChangeKeyValue(struct pipes_struct *p,
908 struct winreg_NotifyChangeKeyValue *r)
910 return WERR_NOT_SUPPORTED;
913 /*******************************************************************
914 _winreg_QueryMultipleValues
915 ********************************************************************/
917 WERROR _winreg_QueryMultipleValues(struct pipes_struct *p,
918 struct winreg_QueryMultipleValues *r)
920 struct winreg_QueryMultipleValues2 r2;
923 r2.in.key_handle = r->in.key_handle;
924 r2.in.values_in = r->in.values_in;
925 r2.in.num_values = r->in.num_values;
926 r2.in.offered = r->in.buffer_size;
927 r2.in.buffer = r->in.buffer;
928 r2.out.values_out = r->out.values_out;
929 r2.out.needed = &needed;
930 r2.out.buffer = r->out.buffer;
932 return _winreg_QueryMultipleValues2(p, &r2);
935 /*******************************************************************
936 ********************************************************************/
938 static WERROR construct_multiple_entry(TALLOC_CTX *mem_ctx,
939 const char *valuename,
940 uint32_t value_length,
942 enum winreg_Type type,
943 struct QueryMultipleValue *r)
945 r->ve_valuename = talloc_zero(mem_ctx, struct winreg_ValNameBuf);
946 if (r->ve_valuename == NULL) {
947 return WERR_NOT_ENOUGH_MEMORY;
950 r->ve_valuename->name = talloc_strdup(r->ve_valuename, valuename ? valuename : "");
951 if (r->ve_valuename->name == NULL) {
952 return WERR_NOT_ENOUGH_MEMORY;
955 r->ve_valuename->size = strlen_m_term(r->ve_valuename->name)*2;
956 r->ve_valuelen = value_length;
957 r->ve_valueptr = offset;
963 /*******************************************************************
964 _winreg_QueryMultipleValues2
965 ********************************************************************/
967 WERROR _winreg_QueryMultipleValues2(struct pipes_struct *p,
968 struct winreg_QueryMultipleValues2 *r)
970 struct registry_key *regkey = find_regkey_by_hnd(p, r->in.key_handle);
971 struct registry_value *vals = NULL;
972 const char **names = NULL;
973 uint32_t offset = 0, num_vals = 0;
974 DATA_BLOB result = data_blob_null;
976 WERROR err = WERR_OK;
979 return WERR_INVALID_HANDLE;
982 names = talloc_zero_array(p->mem_ctx, const char *, r->in.num_values);
984 return WERR_NOT_ENOUGH_MEMORY;
987 for (i=0; i < r->in.num_values; i++) {
988 if (r->in.values_in[i].ve_valuename &&
989 r->in.values_in[i].ve_valuename->name) {
990 names[i] = talloc_strdup(names,
991 r->in.values_in[i].ve_valuename->name);
992 if (names[i] == NULL) {
993 return WERR_NOT_ENOUGH_MEMORY;
998 err = reg_querymultiplevalues(p->mem_ctx, regkey,
999 r->in.num_values, names,
1001 if (!W_ERROR_IS_OK(err)) {
1005 result = data_blob_talloc(p->mem_ctx, NULL, 0);
1007 for (i=0; i < r->in.num_values; i++) {
1008 const char *valuename = NULL;
1010 if (vals[i].data.length > 0) {
1011 if (!data_blob_append(p->mem_ctx, &result,
1013 vals[i].data.length)) {
1014 return WERR_NOT_ENOUGH_MEMORY;
1018 if (r->in.values_in[i].ve_valuename &&
1019 r->in.values_in[i].ve_valuename->name) {
1020 valuename = r->in.values_in[i].ve_valuename->name;
1023 err = construct_multiple_entry(r->out.values_out,
1025 vals[i].data.length,
1028 &r->out.values_out[i]);
1029 if (!W_ERROR_IS_OK(err)) {
1033 offset += vals[i].data.length;
1036 *r->out.needed = result.length;
1038 if (r->in.num_values != num_vals) {
1039 return WERR_FILE_NOT_FOUND;
1042 if (*r->in.offered >= *r->out.needed) {
1043 if (r->out.buffer) {
1044 memcpy(r->out.buffer, result.data, MIN(result.length, *r->in.offered));
1048 return WERR_MORE_DATA;
1052 /*******************************************************************
1054 ********************************************************************/
1056 WERROR _winreg_DeleteKeyEx(struct pipes_struct *p,
1057 struct winreg_DeleteKeyEx *r)
1059 /* fill in your code here if you think this call should
1062 p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1063 return WERR_NOT_SUPPORTED;