Patches for more python support for registry API

Jelmer Vernooij jelmer at samba.org
Sat May 12 19:41:36 MDT 2012


Hey Wilco, :)

Am 10/05/12 15:13, schrieb Wilco Baan Hofman:
> I've made some patches for the registry library in samba.
>
> One which extends the python registry API to also have key/value
> iteration and traversing to subkeys, getting key values and key
> information.
>
> The second patches the regf backend to return the class name in the unix
> character set, like the other backends do.
>
> Can somebody sign off on these and commit them?
Thanks! Any chance you can add some tests?

This looks good in general; some more comments below:

> @@ -459,10 +460,11 @@ static WERROR regf_get_info(TALLOC_CTX *mem_ctx,
>   		if (private_data->nk->clsname_offset != -1) {
>   			DATA_BLOB data = hbin_get(private_data->hive,
>   						  private_data->nk->clsname_offset);
> -			*classname = talloc_strndup(mem_ctx,
> -						    (char*)data.data,
> -						    private_data->nk->clsname_length);
> -			W_ERROR_HAVE_NO_MEMORY(*classname);
> +			success = convert_string_talloc(mem_ctx, CH_UTF16, CH_UNIX, data.data,
> +			                                private_data->nk->clsname_length,
> +			                                classname, NULL);
> +			if (!success)
> +				return WERR_INVALID_DATATYPE;
>
WERR_INVALID_DATATYPE seems like an odd error in this case.

> +static PyObject *py_hive_get_value(PyObject *self, PyObject *args)
> +{
> +	struct hive_key *key = PyHiveKey_AsHiveKey(self);
> +	const char *name;
> +	DATA_BLOB data;
> +	uint32_t type;
> +	PyObject *value;
> +	PyObject *PyData;
> +	const char *string;
> +	WERROR result;
> +	bool success;
> +
> +	if (!PyArg_ParseTuple(args, "s", &name))
> +		return NULL;
> +
> +	result = key->ops->get_value_by_name(key, key, name, &type, &data);
> +	PyErr_WERROR_IS_ERR_RAISE(result);
> +
> +	switch (type) {
> +		case REG_SZ:
> +		case REG_EXPAND_SZ:
> +		case REG_LINK:
> +			success = convert_string_talloc(key, CH_UTF16, CH_UTF8,
> +			                                data.data, data.length, &string, NULL);
> +			if (!success)
> +				PyErr_SetWERROR(WERR_INVALID_DATATYPE);
Please free data.data on errors.
> +
> +			PyData = PyString_FromString(string);
PyString_FromString can return NULL, in which case you should return 
NULL from here (and free data.data).
> +			break;
> +		case REG_BINARY:
> +		case REG_MULTI_SZ: /* FIXME Could use parsing */
> +		case REG_NONE:
> +			PyData = PyString_FromStringAndSize((char *)data.data, data.length);
PyString_FromStringAndSize can return NULL.
> +			break;
> +		case REG_DWORD:
> +		case REG_DWORD_BIG_ENDIAN:
> +			PyData = PyLong_FromUnsignedLong(*(uint32_t *)data.data);
likewise
> +			break;
> +		case REG_QWORD:
> +			PyData = PyLong_FromUnsignedLong(*(uint64_t *)data.data);
likewise
> +			break;
> +		default:
> +			PyErr_SetWERROR(WERR_INVALID_DATATYPE);
In this case, data.data should be freed.
> +			return NULL;
> +	}
> +
> +	value = PyDict_New();
PYDict_New() can return NULL.
> +	PyDict_SetItemString(value, "type", PyLong_FromUnsignedLong(type));
PyLong_FromUnsignedLong can return NULL
> +	PyDict_SetItemString(value, "data", PyData);
Returning a dictionary in this case is a bit odd. Is there any reason 
for not returning a tuple ? That's a lot more useful to callers.

> +
> +typedef struct {
> +	PyObject_HEAD
> +		uint32_t current_idx;
> +	PyObject *iteratee;
> +} PyValueIteratorObject;
> +
> +
> +static PyObject *py_hive_value_iter_next(PyValueIteratorObject *self) {
Please add the { on a separate line (see the coding style).
> +	struct hive_key *key = PyHiveKey_AsHiveKey(self->iteratee);
> +	WERROR result;
> +	const char *name;
> +
> +	result = key->ops->enum_value(key, key, self->current_idx, &name, NULL, NULL);
> +	if (W_ERROR_EQUAL(result,WERR_NO_MORE_ITEMS))
Please add a space after a comma.
> +		return NULL;
> +	PyErr_WERROR_IS_ERR_RAISE(result);
> +
> +	self->current_idx++;
> +
> +	return PyString_FromString(name);
> +}

> +static PyObject *py_hive_subkey_iter_next(PySubkeyIteratorObject *self) {
Likewise about { on a new line.
> +static PyObject *py_hive_get_key_info(PyObject *self, PyObject *args)
> +{
> +	struct hive_key *key = PyHiveKey_AsHiveKey(self);
> +	WERROR result;
> +	const char *class_name;
> +	uint32_t num_subkeys;
> +	uint32_t num_values;
> +	NTTIME last_change_time;
> +	uint32_t max_subkey_name_len;
> +	uint32_t max_value_name_len;
> +	uint32_t max_value_buf_size;
> +	PyObject *dict;
> +	time_t last_change_time_unix;
> +
> +	result = key->ops->get_key_info(key, key, &class_name, &num_subkeys,
> +			&num_values, &last_change_time, &max_subkey_name_len,
> +			&max_value_name_len, &max_value_buf_size);
> +	PyErr_WERROR_IS_ERR_RAISE(result);
> +
> +
> +	/* Convert the NT time to unix time so it can be used directly with the python time module */
> +	last_change_time_unix = nt_time_to_unix(last_change_time);
> +
> +	dict = PyDict_New();
PyDict_New can return NULL.
> +
> +	PyDict_SetItemString(dict, "class_name", PyString_FromString(class_name));
> +	PyDict_SetItemString(dict, "num_subkeys", PyLong_FromUnsignedLong(num_subkeys));
> +	PyDict_SetItemString(dict, "num_values", PyLong_FromUnsignedLong(num_subkeys));
> +	PyDict_SetItemString(dict, "last_change_time", PyLong_FromUnsignedLong(last_change_time_unix));
> +	PyDict_SetItemString(dict, "max_subkey_name_len", PyLong_FromUnsignedLong(num_subkeys));
> +	PyDict_SetItemString(dict, "max_value_name_len", PyLong_FromUnsignedLong(num_subkeys));
> +	PyDict_SetItemString(dict, "max_value_buf_size", PyLong_FromUnsignedLong(num_subkeys));
Likewise for the various calls here.
> 		"Delete a subkey" },
> @@ -240,6 +457,12 @@ static PyMethodDef hive_key_methods[] = {
>                    "Delete a value" },
>   	{ "set_value", py_hive_key_set_value, METH_VARARGS, "S.set_value(name, type, data) -> None\n"
>                    "Set a value" },
> +	{ "get_subkey", py_hive_get_subkey, METH_VARARGS, "S.get_subkey(name) -> HiveKey\n"
> +                 "Get a subkey object" },
> +	{ "get_value", py_hive_get_value, METH_VARARGS, "S.get_value(name) -> Dict\n"
> +                 "Get type and data of value" },
> +	{ "get_info", py_hive_get_key_info, METH_VARARGS, "S.get_info() -> Dict\n"
> +                 "Get info for the current key" },
>
The "Dict" data type in Python has a lower case "d".

Cheers,

Jelmer


More information about the samba-technical mailing list