diff options
-rw-r--r-- | source3/rpc_client/cli_winreg.c | 179 | ||||
-rw-r--r-- | source3/rpc_client/cli_winreg.h | 35 |
2 files changed, 214 insertions, 0 deletions
diff --git a/source3/rpc_client/cli_winreg.c b/source3/rpc_client/cli_winreg.c index 69982dadc6..821efe4e21 100644 --- a/source3/rpc_client/cli_winreg.c +++ b/source3/rpc_client/cli_winreg.c @@ -702,4 +702,183 @@ NTSTATUS dcerpc_winreg_enum_keys(TALLOC_CTX *mem_ctx, return status; } +NTSTATUS dcerpc_winreg_enumvals(TALLOC_CTX *mem_ctx, + struct dcerpc_binding_handle *h, + struct policy_handle *key_hnd, + uint32_t *pnum_values, + const char ***pnames, + enum winreg_Type **_type, + DATA_BLOB **pdata, + WERROR *pwerr) +{ + TALLOC_CTX *tmp_ctx; + uint32_t num_subkeys = 0, max_subkeylen = 0, max_classlen = 0; + uint32_t num_values = 0, max_valnamelen = 0, max_valbufsize = 0; + uint32_t secdescsize = 0; + uint32_t i; + NTTIME last_changed_time = 0; + struct winreg_String classname; + + const char **enum_names = NULL; + enum winreg_Type *enum_types = NULL; + DATA_BLOB *enum_data_blobs = NULL; + + + WERROR result = WERR_OK; + NTSTATUS status = NT_STATUS_OK; + + tmp_ctx = talloc_stackframe(); + if (tmp_ctx == NULL) { + + status = NT_STATUS_NO_MEMORY; + *pwerr = ntstatus_to_werror(status); + return status; + } + + ZERO_STRUCT(classname); + + status = dcerpc_winreg_QueryInfoKey(h, + tmp_ctx, + key_hnd, + &classname, + &num_subkeys, + &max_subkeylen, + &max_classlen, + &num_values, + &max_valnamelen, + &max_valbufsize, + &secdescsize, + &last_changed_time, + &result); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("dcerpc_winreg_enumvals: Could not query info: %s\n", + nt_errstr(status))); + goto error; + } + if (!W_ERROR_IS_OK(result)) { + DEBUG(0, ("dcerpc_winreg_enumvals: Could not query info: %s\n", + win_errstr(result))); + *pwerr = result; + goto error; + } + + if (num_values == 0) { + *pnum_values = 0; + TALLOC_FREE(tmp_ctx); + *pwerr = WERR_OK; + return status; + } + + enum_names = talloc_zero_array(tmp_ctx, const char *, num_values); + + if (enum_names == NULL) { + *pwerr = WERR_NOMEM; + goto error; + } + + enum_types = talloc_zero_array(tmp_ctx, enum winreg_Type, num_values); + + if (enum_types == NULL) { + *pwerr = WERR_NOMEM; + goto error; + } + + enum_data_blobs = talloc_zero_array(tmp_ctx, DATA_BLOB, num_values); + + if (enum_data_blobs == NULL) { + *pwerr = WERR_NOMEM; + goto error; + } + + for (i = 0; i < num_values; i++) { + const char *name; + struct winreg_ValNameBuf name_buf; + enum winreg_Type type = REG_NONE; + uint8_t *data; + uint32_t data_size; + uint32_t length; + char n = '\0'; + + + name_buf.name = &n; + name_buf.size = max_valnamelen + 2; + name_buf.length = 0; + + data_size = max_valbufsize; + data = NULL; + if (data_size) { + data = (uint8_t *) TALLOC(tmp_ctx, data_size); + } + length = 0; + + status = dcerpc_winreg_EnumValue(h, + tmp_ctx, + key_hnd, + i, + &name_buf, + &type, + data, + data_size ? &data_size : NULL, + &length, + &result); + if (W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS) ) { + result = WERR_OK; + status = NT_STATUS_OK; + break; + } + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("dcerpc_winreg_enumvals: Could not enumerate values: %s\n", + nt_errstr(status))); + goto error; + } + if (!W_ERROR_IS_OK(result)) { + DEBUG(0, ("dcerpc_winreg_enumvals: Could not enumerate values: %s\n", + win_errstr(result))); + *pwerr = result; + goto error; + } + + if (name_buf.name == NULL) { + result = WERR_INVALID_PARAMETER; + *pwerr = result; + goto error; + } + + name = talloc_strdup(enum_names, name_buf.name); + if (name == NULL) { + result = WERR_NOMEM; + *pwerr = result; + goto error; + } + /* place name, type and datablob in the enum return params */ + + enum_data_blobs[i] = data_blob_talloc(enum_data_blobs, data, length); + enum_names[i] = name; + enum_types[i] = type; + + } + /* move to the main mem context */ + *pnum_values = num_values; + if (pnames) { + *pnames = talloc_move(mem_ctx, &enum_names); + } + /* can this fail in any way? */ + if (_type) { + *_type = talloc_move(mem_ctx, &enum_types); + } + + if (pdata){ + *pdata = talloc_move(mem_ctx, &enum_data_blobs); + } + + + result = WERR_OK; + + error: + TALLOC_FREE(tmp_ctx); + *pwerr = result; + + return status; +} /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */ diff --git a/source3/rpc_client/cli_winreg.h b/source3/rpc_client/cli_winreg.h index 413aba5425..f4af4ce849 100644 --- a/source3/rpc_client/cli_winreg.h +++ b/source3/rpc_client/cli_winreg.h @@ -378,6 +378,41 @@ NTSTATUS dcerpc_winreg_enum_keys(TALLOC_CTX *mem_ctx, uint32_t *pnum_subkeys, const char ***psubkeys, WERROR *pwerr); +/** + * @internal + * + * @brief Enumerate values of an opened key handle and retrieve the data. + * + * @param[in] mem_ctx The memory context to use. + * + * @param[in] winreg_handle The binding handle for the rpc connection. + * + * @param[in] key_hnd The opened key handle. + * + * @param[out] pnum_values A pointer to store the number of values we found. + * + * @param[out] pnames A pointer to store all the names of the values we found. + * + * @param[out] _type A pointer to store all the types coresponding with the + * values found. + * @param[out] pdata A pointer to store the data coresponding to the values. + * + * @param[out] pwerr A pointer to the WERROR. WERR_OK on success + * WERR_OK on success, the corresponding DOS error + * code if something's gone wrong. + * + * @return NT_STATUS_OK on success or a corresponding error if + * there was a problem on the connection. + */ + +NTSTATUS dcerpc_winreg_enumvals(TALLOC_CTX *mem_ctx, + struct dcerpc_binding_handle *h, + struct policy_handle *key_hnd, + uint32_t *pnum_values, + const char ***pnames, + enum winreg_Type **_type, + DATA_BLOB **pdata, + WERROR *pwerr); #endif /* CLI_WINREG_H */ |