4 Windows Registry access module for Python.
6 * Simple registry access written by Mark Hammond in win32api
8 * Bill Tutt expanded the support significantly not long after.
9 * Numerous other people have submitted patches since then.
10 * Ripped from win32api module 03-Feb-2000 by Mark Hammond, and
11 basic Unicode support added.
16 #include "structmember.h"
17 #include "malloc.h" /* for alloca */
20 static BOOL
PyHKEY_AsHKEY(PyObject
*ob
, HKEY
*pRes
, BOOL bNoneOK
);
21 static PyObject
*PyHKEY_FromHKEY(HKEY h
);
22 static BOOL
PyHKEY_Close(PyObject
*obHandle
);
24 static char errNotAHandle
[] = "Object is not a handle";
26 /* The win32api module reports the function name that failed,
27 but this concept is not in the Python core.
28 Hopefully it will one day, and in the meantime I dont
29 want to lose this info...
31 #define PyErr_SetFromWindowsErrWithFunction(rc, fnname) \
32 PyErr_SetFromWindowsErr(rc)
34 /* Forward declares */
37 PyDoc_STRVAR(module_doc
,
38 "This module provides access to the Windows registry API.\n"
42 "CloseKey() - Closes a registry key.\n"
43 "ConnectRegistry() - Establishes a connection to a predefined registry handle\n"
44 " on another computer.\n"
45 "CreateKey() - Creates the specified key, or opens it if it already exists.\n"
46 "DeleteKey() - Deletes the specified key.\n"
47 "DeleteValue() - Removes a named value from the specified registry key.\n"
48 "EnumKey() - Enumerates subkeys of the specified open registry key.\n"
49 "EnumValue() - Enumerates values of the specified open registry key.\n"
50 "ExpandEnvironmentStrings() - Expand the env strings in a REG_EXPAND_SZ string.\n"
51 "FlushKey() - Writes all the attributes of the specified key to the registry.\n"
52 "LoadKey() - Creates a subkey under HKEY_USER or HKEY_LOCAL_MACHINE and stores\n"
53 " registration information from a specified file into that subkey.\n"
54 "OpenKey() - Alias for <om win32api.RegOpenKeyEx>\n"
55 "OpenKeyEx() - Opens the specified key.\n"
56 "QueryValue() - Retrieves the value associated with the unnamed value for a\n"
57 " specified key in the registry.\n"
58 "QueryValueEx() - Retrieves the type and data for a specified value name\n"
59 " associated with an open registry key.\n"
60 "QueryInfoKey() - Returns information about the specified key.\n"
61 "SaveKey() - Saves the specified key, and all its subkeys a file.\n"
62 "SetValue() - Associates a value with a specified key.\n"
63 "SetValueEx() - Stores data in the value field of an open registry key.\n"
67 "HKEYType -- type object for HKEY objects\n"
68 "error -- exception raised for Win32 errors\n"
70 "Integer constants:\n"
71 "Many constants are defined - see the documentation for each function\n"
72 "to see what constants are used, and where.");
75 PyDoc_STRVAR(CloseKey_doc
,
76 "CloseKey(hkey) - Closes a previously opened registry key.\n"
78 "The hkey argument specifies a previously opened key.\n"
80 "Note that if the key is not closed using this method, it will be\n"
81 "closed when the hkey object is destroyed by Python.");
83 PyDoc_STRVAR(ConnectRegistry_doc
,
84 "key = ConnectRegistry(computer_name, key) - "
85 "Establishes a connection to a predefined registry handle on another computer.\n"
87 "computer_name is the name of the remote computer, of the form \\\\computername.\n"
88 " If None, the local computer is used.\n"
89 "key is the predefined handle to connect to.\n"
91 "The return value is the handle of the opened key.\n"
92 "If the function fails, an EnvironmentError exception is raised.");
94 PyDoc_STRVAR(CreateKey_doc
,
95 "key = CreateKey(key, sub_key) - Creates or opens the specified key.\n"
97 "key is an already open key, or one of the predefined HKEY_* constants\n"
98 "sub_key is a string that names the key this method opens or creates.\n"
99 " If key is one of the predefined keys, sub_key may be None. In that case,\n"
100 " the handle returned is the same key handle passed in to the function.\n"
102 "If the key already exists, this function opens the existing key\n"
104 "The return value is the handle of the opened key.\n"
105 "If the function fails, an exception is raised.");
107 PyDoc_STRVAR(DeleteKey_doc
,
108 "DeleteKey(key, sub_key) - Deletes the specified key.\n"
110 "key is an already open key, or any one of the predefined HKEY_* constants.\n"
111 "sub_key is a string that must be a subkey of the key identified by the key parameter.\n"
112 " This value must not be None, and the key may not have subkeys.\n"
114 "This method can not delete keys with subkeys.\n"
116 "If the method succeeds, the entire key, including all of its values,\n"
117 "is removed. If the method fails, an EnvironmentError exception is raised.");
119 PyDoc_STRVAR(DeleteValue_doc
,
120 "DeleteValue(key, value) - Removes a named value from a registry key.\n"
122 "key is an already open key, or any one of the predefined HKEY_* constants.\n"
123 "value is a string that identifies the value to remove.");
125 PyDoc_STRVAR(EnumKey_doc
,
126 "string = EnumKey(key, index) - Enumerates subkeys of an open registry key.\n"
128 "key is an already open key, or any one of the predefined HKEY_* constants.\n"
129 "index is an integer that identifies the index of the key to retrieve.\n"
131 "The function retrieves the name of one subkey each time it is called.\n"
132 "It is typically called repeatedly until an EnvironmentError exception is\n"
133 "raised, indicating no more values are available.");
135 PyDoc_STRVAR(EnumValue_doc
,
136 "tuple = EnumValue(key, index) - Enumerates values of an open registry key.\n"
137 "key is an already open key, or any one of the predefined HKEY_* constants.\n"
138 "index is an integer that identifies the index of the value to retrieve.\n"
140 "The function retrieves the name of one subkey each time it is called.\n"
141 "It is typically called repeatedly, until an EnvironmentError exception\n"
142 "is raised, indicating no more values.\n"
144 "The result is a tuple of 3 items:\n"
145 "value_name is a string that identifies the value.\n"
146 "value_data is an object that holds the value data, and whose type depends\n"
147 " on the underlying registry type.\n"
148 "data_type is an integer that identifies the type of the value data.");
150 PyDoc_STRVAR(ExpandEnvironmentStrings_doc
,
151 "string = ExpandEnvironmentStrings(string) - Expand environment vars.\n");
153 PyDoc_STRVAR(FlushKey_doc
,
154 "FlushKey(key) - Writes all the attributes of a key to the registry.\n"
156 "key is an already open key, or any one of the predefined HKEY_* constants.\n"
158 "It is not necessary to call RegFlushKey to change a key.\n"
159 "Registry changes are flushed to disk by the registry using its lazy flusher.\n"
160 "Registry changes are also flushed to disk at system shutdown.\n"
161 "Unlike CloseKey(), the FlushKey() method returns only when all the data has\n"
162 "been written to the registry.\n"
163 "An application should only call FlushKey() if it requires absolute certainty that registry changes are on disk.\n"
164 "If you don't know whether a FlushKey() call is required, it probably isn't.");
166 PyDoc_STRVAR(LoadKey_doc
,
167 "LoadKey(key, sub_key, file_name) - Creates a subkey under the specified key\n"
168 "and stores registration information from a specified file into that subkey.\n"
170 "key is an already open key, or any one of the predefined HKEY_* constants.\n"
171 "sub_key is a string that identifies the sub_key to load\n"
172 "file_name is the name of the file to load registry data from.\n"
173 " This file must have been created with the SaveKey() function.\n"
174 " Under the file allocation table (FAT) file system, the filename may not\n"
175 "have an extension.\n"
177 "A call to LoadKey() fails if the calling process does not have the\n"
178 "SE_RESTORE_PRIVILEGE privilege.\n"
180 "If key is a handle returned by ConnectRegistry(), then the path specified\n"
181 "in fileName is relative to the remote computer.\n"
183 "The docs imply key must be in the HKEY_USER or HKEY_LOCAL_MACHINE tree");
185 PyDoc_STRVAR(OpenKey_doc
,
186 "key = OpenKey(key, sub_key, res = 0, sam = KEY_READ) - Opens the specified key.\n"
188 "key is an already open key, or any one of the predefined HKEY_* constants.\n"
189 "sub_key is a string that identifies the sub_key to open\n"
190 "res is a reserved integer, and must be zero. Default is zero.\n"
191 "sam is an integer that specifies an access mask that describes the desired\n"
192 " security access for the key. Default is KEY_READ\n"
194 "The result is a new handle to the specified key\n"
195 "If the function fails, an EnvironmentError exception is raised.");
197 PyDoc_STRVAR(OpenKeyEx_doc
, "See OpenKey()");
199 PyDoc_STRVAR(QueryInfoKey_doc
,
200 "tuple = QueryInfoKey(key) - Returns information about a key.\n"
202 "key is an already open key, or any one of the predefined HKEY_* constants.\n"
204 "The result is a tuple of 3 items:"
205 "An integer that identifies the number of sub keys this key has.\n"
206 "An integer that identifies the number of values this key has.\n"
207 "A long integer that identifies when the key was last modified (if available)\n"
208 " as 100's of nanoseconds since Jan 1, 1600.");
210 PyDoc_STRVAR(QueryValue_doc
,
211 "string = QueryValue(key, sub_key) - retrieves the unnamed value for a key.\n"
213 "key is an already open key, or any one of the predefined HKEY_* constants.\n"
214 "sub_key is a string that holds the name of the subkey with which the value\n"
215 " is associated. If this parameter is None or empty, the function retrieves\n"
216 " the value set by the SetValue() method for the key identified by key."
218 "Values in the registry have name, type, and data components. This method\n"
219 "retrieves the data for a key's first value that has a NULL name.\n"
220 "But the underlying API call doesn't return the type, Lame Lame Lame, DONT USE THIS!!!");
222 PyDoc_STRVAR(QueryValueEx_doc
,
223 "value,type_id = QueryValueEx(key, value_name) - Retrieves the type and data for a specified value name associated with an open registry key.\n"
225 "key is an already open key, or any one of the predefined HKEY_* constants.\n"
226 "value_name is a string indicating the value to query");
228 PyDoc_STRVAR(SaveKey_doc
,
229 "SaveKey(key, file_name) - Saves the specified key, and all its subkeys to the specified file.\n"
231 "key is an already open key, or any one of the predefined HKEY_* constants.\n"
232 "file_name is the name of the file to save registry data to.\n"
233 " This file cannot already exist. If this filename includes an extension,\n"
234 " it cannot be used on file allocation table (FAT) file systems by the\n"
235 " LoadKey(), ReplaceKey() or RestoreKey() methods.\n"
237 "If key represents a key on a remote computer, the path described by\n"
238 "file_name is relative to the remote computer.\n"
239 "The caller of this method must possess the SeBackupPrivilege security privilege.\n"
240 "This function passes NULL for security_attributes to the API.");
242 PyDoc_STRVAR(SetValue_doc
,
243 "SetValue(key, sub_key, type, value) - Associates a value with a specified key.\n"
245 "key is an already open key, or any one of the predefined HKEY_* constants.\n"
246 "sub_key is a string that names the subkey with which the value is associated.\n"
247 "type is an integer that specifies the type of the data. Currently this\n"
248 " must be REG_SZ, meaning only strings are supported.\n"
249 "value is a string that specifies the new value.\n"
251 "If the key specified by the sub_key parameter does not exist, the SetValue\n"
252 "function creates it.\n"
254 "Value lengths are limited by available memory. Long values (more than\n"
255 "2048 bytes) should be stored as files with the filenames stored in \n"
256 "the configuration registry. This helps the registry perform efficiently.\n"
258 "The key identified by the key parameter must have been opened with\n"
259 "KEY_SET_VALUE access.");
261 PyDoc_STRVAR(SetValueEx_doc
,
262 "SetValueEx(key, value_name, reserved, type, value) - Stores data in the value field of an open registry key.\n"
264 "key is an already open key, or any one of the predefined HKEY_* constants.\n"
265 "value_name is a string containing the name of the value to set, or None\n"
266 "type is an integer that specifies the type of the data. This should be one of:\n"
267 " REG_BINARY -- Binary data in any form.\n"
268 " REG_DWORD -- A 32-bit number.\n"
269 " REG_DWORD_LITTLE_ENDIAN -- A 32-bit number in little-endian format.\n"
270 " REG_DWORD_BIG_ENDIAN -- A 32-bit number in big-endian format.\n"
271 " REG_EXPAND_SZ -- A null-terminated string that contains unexpanded references\n"
272 " to environment variables (for example, %PATH%).\n"
273 " REG_LINK -- A Unicode symbolic link.\n"
274 " REG_MULTI_SZ -- An sequence of null-terminated strings, terminated by\n"
275 " two null characters. Note that Python handles this\n"
276 " termination automatically.\n"
277 " REG_NONE -- No defined value type.\n"
278 " REG_RESOURCE_LIST -- A device-driver resource list.\n"
279 " REG_SZ -- A null-terminated string.\n"
280 "reserved can be anything - zero is always passed to the API.\n"
281 "value is a string that specifies the new value.\n"
283 "This method can also set additional value and type information for the\n"
284 "specified key. The key identified by the key parameter must have been\n"
285 "opened with KEY_SET_VALUE access.\n"
287 "To open the key, use the CreateKeyEx() or OpenKeyEx() methods.\n"
289 "Value lengths are limited by available memory. Long values (more than\n"
290 "2048 bytes) should be stored as files with the filenames stored in \n"
291 "the configuration registry. This helps the registry perform efficiently.");
293 /* PyHKEY docstrings */
294 PyDoc_STRVAR(PyHKEY_doc
,
295 "PyHKEY Object - A Python object, representing a win32 registry key.\n"
297 "This object wraps a Windows HKEY object, automatically closing it when\n"
298 "the object is destroyed. To guarantee cleanup, you can call either\n"
299 "the Close() method on the PyHKEY, or the CloseKey() method.\n"
301 "All functions which accept a handle object also accept an integer - \n"
302 "however, use of the handle object is encouraged.\n"
305 "Close() - Closes the underlying handle.\n"
306 "Detach() - Returns the integer Win32 handle, detaching it from the object\n"
309 "handle - The integer Win32 handle.\n"
312 "__nonzero__ - Handles with an open object return true, otherwise false.\n"
313 "__int__ - Converting a handle to an integer returns the Win32 handle.\n"
314 "__cmp__ - Handle objects are compared using the handle value.");
317 PyDoc_STRVAR(PyHKEY_Close_doc
,
318 "key.Close() - Closes the underlying Windows handle.\n"
320 "If the handle is already closed, no error is raised.");
322 PyDoc_STRVAR(PyHKEY_Detach_doc
,
323 "int = key.Detach() - Detaches the Windows handle from the handle object.\n"
325 "The result is the value of the handle before it is detached. If the\n"
326 "handle is already detached, this will return zero.\n"
328 "After calling this function, the handle is effectively invalidated,\n"
329 "but the handle is not closed. You would call this function when you\n"
330 "need the underlying win32 handle to exist beyond the lifetime of the\n"
332 "On 64 bit windows, the result of this function is a long integer");
335 /************************************************************************
337 The PyHKEY object definition
339 ************************************************************************/
345 #define PyHKEY_Check(op) ((op)->ob_type == &PyHKEY_Type)
347 static char *failMsg
= "bad operand type";
350 PyHKEY_unaryFailureFunc(PyObject
*ob
)
352 PyErr_SetString(PyExc_TypeError
, failMsg
);
356 PyHKEY_binaryFailureFunc(PyObject
*ob1
, PyObject
*ob2
)
358 PyErr_SetString(PyExc_TypeError
, failMsg
);
362 PyHKEY_ternaryFailureFunc(PyObject
*ob1
, PyObject
*ob2
, PyObject
*ob3
)
364 PyErr_SetString(PyExc_TypeError
, failMsg
);
369 PyHKEY_deallocFunc(PyObject
*ob
)
371 /* Can not call PyHKEY_Close, as the ob->tp_type
372 has already been cleared, thus causing the type
375 PyHKEYObject
*obkey
= (PyHKEYObject
*)ob
;
377 RegCloseKey((HKEY
)obkey
->hkey
);
382 PyHKEY_nonzeroFunc(PyObject
*ob
)
384 return ((PyHKEYObject
*)ob
)->hkey
!= 0;
388 PyHKEY_intFunc(PyObject
*ob
)
390 PyHKEYObject
*pyhkey
= (PyHKEYObject
*)ob
;
391 return PyLong_FromVoidPtr(pyhkey
->hkey
);
395 PyHKEY_printFunc(PyObject
*ob
, FILE *fp
, int flags
)
397 PyHKEYObject
*pyhkey
= (PyHKEYObject
*)ob
;
399 wsprintf(resBuf
, "<PyHKEY at %p (%p)>",
406 PyHKEY_strFunc(PyObject
*ob
)
408 PyHKEYObject
*pyhkey
= (PyHKEYObject
*)ob
;
410 wsprintf(resBuf
, "<PyHKEY:%p>", pyhkey
->hkey
);
411 return PyString_FromString(resBuf
);
415 PyHKEY_compareFunc(PyObject
*ob1
, PyObject
*ob2
)
417 PyHKEYObject
*pyhkey1
= (PyHKEYObject
*)ob1
;
418 PyHKEYObject
*pyhkey2
= (PyHKEYObject
*)ob2
;
419 return pyhkey1
== pyhkey2
? 0 :
420 (pyhkey1
< pyhkey2
? -1 : 1);
424 PyHKEY_hashFunc(PyObject
*ob
)
426 /* Just use the address.
427 XXX - should we use the handle value?
429 return _Py_HashPointer(ob
);
433 static PyNumberMethods PyHKEY_NumberMethods
=
435 PyHKEY_binaryFailureFunc
, /* nb_add */
436 PyHKEY_binaryFailureFunc
, /* nb_subtract */
437 PyHKEY_binaryFailureFunc
, /* nb_multiply */
438 PyHKEY_binaryFailureFunc
, /* nb_divide */
439 PyHKEY_binaryFailureFunc
, /* nb_remainder */
440 PyHKEY_binaryFailureFunc
, /* nb_divmod */
441 PyHKEY_ternaryFailureFunc
, /* nb_power */
442 PyHKEY_unaryFailureFunc
, /* nb_negative */
443 PyHKEY_unaryFailureFunc
, /* nb_positive */
444 PyHKEY_unaryFailureFunc
, /* nb_absolute */
445 PyHKEY_nonzeroFunc
, /* nb_nonzero */
446 PyHKEY_unaryFailureFunc
, /* nb_invert */
447 PyHKEY_binaryFailureFunc
, /* nb_lshift */
448 PyHKEY_binaryFailureFunc
, /* nb_rshift */
449 PyHKEY_binaryFailureFunc
, /* nb_and */
450 PyHKEY_binaryFailureFunc
, /* nb_xor */
451 PyHKEY_binaryFailureFunc
, /* nb_or */
452 0, /* nb_coerce (allowed to be zero) */
453 PyHKEY_intFunc
, /* nb_int */
454 PyHKEY_unaryFailureFunc
, /* nb_long */
455 PyHKEY_unaryFailureFunc
, /* nb_float */
456 PyHKEY_unaryFailureFunc
, /* nb_oct */
457 PyHKEY_unaryFailureFunc
, /* nb_hex */
461 /* fwd declare __getattr__ */
462 static PyObject
*PyHKEY_getattr(PyObject
*self
, const char *name
);
464 /* The type itself */
465 PyTypeObject PyHKEY_Type
=
467 PyVarObject_HEAD_INIT(0, 0) /* fill in type at module init */
469 sizeof(PyHKEYObject
),
471 PyHKEY_deallocFunc
, /* tp_dealloc */
472 PyHKEY_printFunc
, /* tp_print */
473 PyHKEY_getattr
, /* tp_getattr */
475 PyHKEY_compareFunc
, /* tp_compare */
477 &PyHKEY_NumberMethods
, /* tp_as_number */
478 0, /* tp_as_sequence */
479 0, /* tp_as_mapping */
480 PyHKEY_hashFunc
, /* tp_hash */
482 PyHKEY_strFunc
, /* tp_str */
485 0, /* tp_as_buffer */
487 PyHKEY_doc
, /* tp_doc */
490 #define OFF(e) offsetof(PyHKEYObject, e)
492 static struct memberlist PyHKEY_memberlist
[] = {
493 {"handle", T_INT
, OFF(hkey
)},
494 {NULL
} /* Sentinel */
497 /************************************************************************
499 The PyHKEY object methods
501 ************************************************************************/
503 PyHKEY_CloseMethod(PyObject
*self
, PyObject
*args
)
505 if (!PyArg_ParseTuple(args
, ":Close"))
507 if (!PyHKEY_Close(self
))
514 PyHKEY_DetachMethod(PyObject
*self
, PyObject
*args
)
517 PyHKEYObject
*pThis
= (PyHKEYObject
*)self
;
518 if (!PyArg_ParseTuple(args
, ":Detach"))
520 ret
= (void*)pThis
->hkey
;
522 return PyLong_FromVoidPtr(ret
);
526 PyHKEY_Enter(PyObject
*self
)
533 PyHKEY_Exit(PyObject
*self
, PyObject
*args
)
535 if (!PyHKEY_Close(self
))
541 static struct PyMethodDef PyHKEY_methods
[] = {
542 {"Close", PyHKEY_CloseMethod
, METH_VARARGS
, PyHKEY_Close_doc
},
543 {"Detach", PyHKEY_DetachMethod
, METH_VARARGS
, PyHKEY_Detach_doc
},
544 {"__enter__", (PyCFunction
)PyHKEY_Enter
, METH_NOARGS
, NULL
},
545 {"__exit__", PyHKEY_Exit
, METH_VARARGS
, NULL
},
549 /*static*/ PyObject
*
550 PyHKEY_getattr(PyObject
*self
, const char *name
)
554 res
= Py_FindMethod(PyHKEY_methods
, self
, name
);
558 if (strcmp(name
, "handle") == 0)
559 return PyLong_FromVoidPtr(((PyHKEYObject
*)self
)->hkey
);
560 return PyMember_Get((char *)self
, PyHKEY_memberlist
, name
);
563 /************************************************************************
564 The public PyHKEY API (well, not public yet :-)
565 ************************************************************************/
567 PyHKEY_New(HKEY hInit
)
569 PyHKEYObject
*key
= PyObject_NEW(PyHKEYObject
, &PyHKEY_Type
);
572 return (PyObject
*)key
;
576 PyHKEY_Close(PyObject
*ob_handle
)
581 if (!PyHKEY_Check(ob_handle
)) {
582 PyErr_SetString(PyExc_TypeError
, "bad operand type");
585 key
= (PyHKEYObject
*)ob_handle
;
586 rc
= key
->hkey
? RegCloseKey((HKEY
)key
->hkey
) : ERROR_SUCCESS
;
588 if (rc
!= ERROR_SUCCESS
)
589 PyErr_SetFromWindowsErrWithFunction(rc
, "RegCloseKey");
590 return rc
== ERROR_SUCCESS
;
594 PyHKEY_AsHKEY(PyObject
*ob
, HKEY
*pHANDLE
, BOOL bNoneOK
)
600 "None is not a valid HKEY in this context");
605 else if (PyHKEY_Check(ob
)) {
606 PyHKEYObject
*pH
= (PyHKEYObject
*)ob
;
609 else if (PyInt_Check(ob
) || PyLong_Check(ob
)) {
610 /* We also support integers */
612 *pHANDLE
= (HKEY
)PyLong_AsVoidPtr(ob
);
613 if (PyErr_Occurred())
619 "The object is not a PyHKEY object");
626 PyHKEY_FromHKEY(HKEY h
)
630 /* Inline PyObject_New */
631 op
= (PyHKEYObject
*) PyObject_MALLOC(sizeof(PyHKEYObject
));
633 return PyErr_NoMemory();
634 PyObject_INIT(op
, &PyHKEY_Type
);
636 return (PyObject
*)op
;
640 /************************************************************************
642 ************************************************************************/
644 PyWinObject_CloseHKEY(PyObject
*obHandle
)
647 if (PyHKEY_Check(obHandle
)) {
648 ok
= PyHKEY_Close(obHandle
);
650 #if SIZEOF_LONG >= SIZEOF_HKEY
651 else if (PyInt_Check(obHandle
)) {
652 long rc
= RegCloseKey((HKEY
)PyInt_AsLong(obHandle
));
653 ok
= (rc
== ERROR_SUCCESS
);
655 PyErr_SetFromWindowsErrWithFunction(rc
, "RegCloseKey");
658 else if (PyLong_Check(obHandle
)) {
659 long rc
= RegCloseKey((HKEY
)PyLong_AsVoidPtr(obHandle
));
660 ok
= (rc
== ERROR_SUCCESS
);
662 PyErr_SetFromWindowsErrWithFunction(rc
, "RegCloseKey");
668 "A handle must be a HKEY object or an integer");
676 Private Helper functions for the registry interfaces
678 ** Note that fixupMultiSZ and countString have both had changes
679 ** made to support "incorrect strings". The registry specification
680 ** calls for strings to be terminated with 2 null bytes. It seems
681 ** some commercial packages install strings which dont conform,
682 ** causing this code to fail - however, "regedit" etc still work
683 ** with these strings (ie only we dont!).
686 fixupMultiSZ(char **str
, char *data
, int len
)
693 for (P
= data
, i
= 0; P
< Q
&& *P
!= '\0'; P
++, i
++) {
695 for(; *P
!= '\0'; P
++)
701 countStrings(char *data
, int len
)
705 char *Q
= data
+ len
;
707 for (P
= data
, strings
= 0; P
< Q
&& *P
!= '\0'; P
++, strings
++)
708 for (; P
< Q
&& *P
!= '\0'; P
++)
713 /* Convert PyObject into Registry data.
714 Allocates space as needed. */
716 Py2Reg(PyObject
*value
, DWORD typ
, BYTE
**retDataBuf
, DWORD
*retDataSize
)
721 if (value
!= Py_None
&& !PyInt_Check(value
))
723 *retDataBuf
= (BYTE
*)PyMem_NEW(DWORD
, 1);
724 if (*retDataBuf
==NULL
){
728 *retDataSize
= sizeof(DWORD
);
729 if (value
== Py_None
) {
731 memcpy(*retDataBuf
, &zero
, sizeof(DWORD
));
735 &PyInt_AS_LONG((PyIntObject
*)value
),
742 if (value
== Py_None
)
745 if (PyUnicode_Check(value
)) {
746 value
= PyUnicode_AsEncodedString(
754 if (!PyString_Check(value
))
756 *retDataSize
= 1 + strlen(
758 (PyStringObject
*)value
));
760 *retDataBuf
= (BYTE
*)PyMem_NEW(DWORD
, *retDataSize
);
761 if (*retDataBuf
==NULL
){
765 if (value
== Py_None
)
766 strcpy((char *)*retDataBuf
, "");
768 strcpy((char *)*retDataBuf
,
770 (PyStringObject
*)value
));
779 PyObject
**obs
= NULL
;
781 if (value
== Py_None
)
784 if (!PyList_Check(value
))
786 i
= PyList_Size(value
);
788 obs
= malloc(sizeof(PyObject
*) * i
);
789 memset(obs
, 0, sizeof(PyObject
*) * i
);
790 for (j
= 0; j
< i
; j
++)
794 (PyListObject
*)value
,j
);
795 if (PyString_Check(t
)) {
798 } else if (PyUnicode_Check(t
)) {
799 obs
[j
] = PyUnicode_AsEncodedString(
809 (PyStringObject
*)obs
[j
]));
812 *retDataSize
= size
+ 1;
813 *retDataBuf
= (BYTE
*)PyMem_NEW(char,
815 if (*retDataBuf
==NULL
){
819 P
= (char *)*retDataBuf
;
821 for (j
= 0; j
< i
; j
++)
827 (PyStringObject
*)t
));
830 (PyStringObject
*)t
));
833 /* And doubly-terminate the list... */
839 for (j
= 0; j
< i
; j
++)
847 /* ALSO handle ALL unknown data types here. Even if we can't
848 support it natively, we should handle the bits. */
850 if (value
== Py_None
)
854 PyBufferProcs
*pb
= value
->ob_type
->tp_as_buffer
;
856 PyErr_Format(PyExc_TypeError
,
857 "Objects of type '%s' can not "
858 "be used as binary registry values",
859 value
->ob_type
->tp_name
);
862 *retDataSize
= (*pb
->bf_getreadbuffer
)(value
, 0, &src_buf
);
863 *retDataBuf
= (BYTE
*)PyMem_NEW(char,
865 if (*retDataBuf
==NULL
){
869 memcpy(*retDataBuf
, src_buf
, *retDataSize
);
876 /* Convert Registry data into PyObject*/
878 Reg2Py(char *retDataBuf
, DWORD retDataSize
, DWORD typ
)
884 if (retDataSize
== 0)
885 obData
= Py_BuildValue("i", 0);
887 obData
= Py_BuildValue("i",
892 /* retDataBuf may or may not have a trailing NULL in
894 if (retDataSize
&& retDataBuf
[retDataSize
-1] == '\0')
898 obData
= PyUnicode_DecodeMBCS(retDataBuf
,
903 if (retDataSize
== 0)
904 obData
= PyList_New(0);
908 int s
= countStrings(retDataBuf
, retDataSize
);
909 char **str
= (char **)malloc(sizeof(char *)*s
);
911 return PyErr_NoMemory();
913 fixupMultiSZ(str
, retDataBuf
, retDataSize
);
914 obData
= PyList_New(s
);
917 for (index
= 0; index
< s
; index
++)
919 size_t len
= _mbstrlen(str
[index
]);
921 PyErr_SetString(PyExc_OverflowError
,
922 "registry string is too long for a Python string");
926 PyList_SetItem(obData
,
928 PyUnicode_DecodeMBCS(
929 (const char *)str
[index
],
939 /* ALSO handle ALL unknown data types here. Even if we can't
940 support it natively, we should handle the bits. */
942 if (retDataSize
== 0) {
947 obData
= Py_BuildValue("s#",
958 /* The Python methods */
961 PyCloseKey(PyObject
*self
, PyObject
*args
)
964 if (!PyArg_ParseTuple(args
, "O:CloseKey", &obKey
))
966 if (!PyHKEY_Close(obKey
))
973 PyConnectRegistry(PyObject
*self
, PyObject
*args
)
977 char *szCompName
= NULL
;
980 if (!PyArg_ParseTuple(args
, "zO:ConnectRegistry", &szCompName
, &obKey
))
982 if (!PyHKEY_AsHKEY(obKey
, &hKey
, FALSE
))
984 Py_BEGIN_ALLOW_THREADS
985 rc
= RegConnectRegistry(szCompName
, hKey
, &retKey
);
987 if (rc
!= ERROR_SUCCESS
)
988 return PyErr_SetFromWindowsErrWithFunction(rc
,
990 return PyHKEY_FromHKEY(retKey
);
994 PyCreateKey(PyObject
*self
, PyObject
*args
)
1001 if (!PyArg_ParseTuple(args
, "Oz:CreateKey", &obKey
, &subKey
))
1003 if (!PyHKEY_AsHKEY(obKey
, &hKey
, FALSE
))
1005 rc
= RegCreateKey(hKey
, subKey
, &retKey
);
1006 if (rc
!= ERROR_SUCCESS
)
1007 return PyErr_SetFromWindowsErrWithFunction(rc
, "CreateKey");
1008 return PyHKEY_FromHKEY(retKey
);
1012 PyDeleteKey(PyObject
*self
, PyObject
*args
)
1018 if (!PyArg_ParseTuple(args
, "Os:DeleteKey", &obKey
, &subKey
))
1020 if (!PyHKEY_AsHKEY(obKey
, &hKey
, FALSE
))
1022 rc
= RegDeleteKey(hKey
, subKey
);
1023 if (rc
!= ERROR_SUCCESS
)
1024 return PyErr_SetFromWindowsErrWithFunction(rc
, "RegDeleteKey");
1030 PyDeleteValue(PyObject
*self
, PyObject
*args
)
1036 if (!PyArg_ParseTuple(args
, "Oz:DeleteValue", &obKey
, &subKey
))
1038 if (!PyHKEY_AsHKEY(obKey
, &hKey
, FALSE
))
1040 Py_BEGIN_ALLOW_THREADS
1041 rc
= RegDeleteValue(hKey
, subKey
);
1042 Py_END_ALLOW_THREADS
1043 if (rc
!=ERROR_SUCCESS
)
1044 return PyErr_SetFromWindowsErrWithFunction(rc
,
1051 PyEnumKey(PyObject
*self
, PyObject
*args
)
1058 char tmpbuf
[256]; /* max key name length is 255 */
1059 DWORD len
= sizeof(tmpbuf
); /* includes NULL terminator */
1061 if (!PyArg_ParseTuple(args
, "Oi:EnumKey", &obKey
, &index
))
1063 if (!PyHKEY_AsHKEY(obKey
, &hKey
, FALSE
))
1066 Py_BEGIN_ALLOW_THREADS
1067 rc
= RegEnumKeyEx(hKey
, index
, tmpbuf
, &len
, NULL
, NULL
, NULL
, NULL
);
1068 Py_END_ALLOW_THREADS
1069 if (rc
!= ERROR_SUCCESS
)
1070 return PyErr_SetFromWindowsErrWithFunction(rc
, "RegEnumKeyEx");
1072 retStr
= PyString_FromStringAndSize(tmpbuf
, len
);
1073 return retStr
; /* can be NULL */
1077 PyEnumValue(PyObject
*self
, PyObject
*args
)
1091 if (!PyArg_ParseTuple(args
, "Oi:EnumValue", &obKey
, &index
))
1093 if (!PyHKEY_AsHKEY(obKey
, &hKey
, FALSE
))
1096 if ((rc
= RegQueryInfoKey(hKey
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
1098 &retValueSize
, &retDataSize
, NULL
, NULL
))
1100 return PyErr_SetFromWindowsErrWithFunction(rc
,
1102 ++retValueSize
; /* include null terminators */
1104 retValueBuf
= (char *)PyMem_Malloc(retValueSize
);
1105 if (retValueBuf
== NULL
)
1106 return PyErr_NoMemory();
1107 retDataBuf
= (char *)PyMem_Malloc(retDataSize
);
1108 if (retDataBuf
== NULL
) {
1109 PyMem_Free(retValueBuf
);
1110 return PyErr_NoMemory();
1113 Py_BEGIN_ALLOW_THREADS
1114 rc
= RegEnumValue(hKey
,
1122 Py_END_ALLOW_THREADS
1124 if (rc
!= ERROR_SUCCESS
) {
1125 retVal
= PyErr_SetFromWindowsErrWithFunction(rc
,
1129 obData
= Reg2Py(retDataBuf
, retDataSize
, typ
);
1130 if (obData
== NULL
) {
1134 retVal
= Py_BuildValue("sOi", retValueBuf
, obData
, typ
);
1137 PyMem_Free(retValueBuf
);
1138 PyMem_Free(retDataBuf
);
1143 PyExpandEnvironmentStrings(PyObject
*self
, PyObject
*args
)
1145 Py_UNICODE
*retValue
= NULL
;
1151 if (!PyArg_ParseTuple(args
, "u:ExpandEnvironmentStrings", &src
))
1154 retValueSize
= ExpandEnvironmentStringsW(src
, retValue
, 0);
1155 if (retValueSize
== 0) {
1156 return PyErr_SetFromWindowsErrWithFunction(retValueSize
,
1157 "ExpandEnvironmentStrings");
1159 retValue
= (Py_UNICODE
*)PyMem_Malloc(retValueSize
* sizeof(Py_UNICODE
));
1160 if (retValue
== NULL
) {
1161 return PyErr_NoMemory();
1164 rc
= ExpandEnvironmentStringsW(src
, retValue
, retValueSize
);
1166 PyMem_Free(retValue
);
1167 return PyErr_SetFromWindowsErrWithFunction(retValueSize
,
1168 "ExpandEnvironmentStrings");
1170 o
= PyUnicode_FromUnicode(retValue
, wcslen(retValue
));
1171 PyMem_Free(retValue
);
1176 PyFlushKey(PyObject
*self
, PyObject
*args
)
1181 if (!PyArg_ParseTuple(args
, "O:FlushKey", &obKey
))
1183 if (!PyHKEY_AsHKEY(obKey
, &hKey
, FALSE
))
1185 Py_BEGIN_ALLOW_THREADS
1186 rc
= RegFlushKey(hKey
);
1187 Py_END_ALLOW_THREADS
1188 if (rc
!= ERROR_SUCCESS
)
1189 return PyErr_SetFromWindowsErrWithFunction(rc
, "RegFlushKey");
1194 PyLoadKey(PyObject
*self
, PyObject
*args
)
1202 if (!PyArg_ParseTuple(args
, "Oss:LoadKey", &obKey
, &subKey
, &fileName
))
1204 if (!PyHKEY_AsHKEY(obKey
, &hKey
, FALSE
))
1206 Py_BEGIN_ALLOW_THREADS
1207 rc
= RegLoadKey(hKey
, subKey
, fileName
);
1208 Py_END_ALLOW_THREADS
1209 if (rc
!= ERROR_SUCCESS
)
1210 return PyErr_SetFromWindowsErrWithFunction(rc
, "RegLoadKey");
1216 PyOpenKey(PyObject
*self
, PyObject
*args
)
1225 REGSAM sam
= KEY_READ
;
1226 if (!PyArg_ParseTuple(args
, "Oz|ii:OpenKey", &obKey
, &subKey
,
1229 if (!PyHKEY_AsHKEY(obKey
, &hKey
, FALSE
))
1232 Py_BEGIN_ALLOW_THREADS
1233 rc
= RegOpenKeyEx(hKey
, subKey
, res
, sam
, &retKey
);
1234 Py_END_ALLOW_THREADS
1235 if (rc
!= ERROR_SUCCESS
)
1236 return PyErr_SetFromWindowsErrWithFunction(rc
, "RegOpenKeyEx");
1237 return PyHKEY_FromHKEY(retKey
);
1242 PyQueryInfoKey(PyObject
*self
, PyObject
*args
)
1247 DWORD nSubKeys
, nValues
;
1252 if (!PyArg_ParseTuple(args
, "O:QueryInfoKey", &obKey
))
1254 if (!PyHKEY_AsHKEY(obKey
, &hKey
, FALSE
))
1256 if ((rc
= RegQueryInfoKey(hKey
, NULL
, NULL
, 0, &nSubKeys
, NULL
, NULL
,
1257 &nValues
, NULL
, NULL
, NULL
, &ft
))
1259 return PyErr_SetFromWindowsErrWithFunction(rc
, "RegQueryInfoKey");
1260 li
.LowPart
= ft
.dwLowDateTime
;
1261 li
.HighPart
= ft
.dwHighDateTime
;
1262 l
= PyLong_FromLongLong(li
.QuadPart
);
1265 ret
= Py_BuildValue("iiO", nSubKeys
, nValues
, l
);
1271 PyQueryValue(PyObject
*self
, PyObject
*args
)
1281 if (!PyArg_ParseTuple(args
, "Oz:QueryValue", &obKey
, &subKey
))
1284 if (!PyHKEY_AsHKEY(obKey
, &hKey
, FALSE
))
1286 if ((rc
= RegQueryValue(hKey
, subKey
, NULL
, &bufSize
))
1288 return PyErr_SetFromWindowsErrWithFunction(rc
,
1290 retStr
= PyString_FromStringAndSize(NULL
, bufSize
);
1293 retBuf
= PyString_AS_STRING(retStr
);
1294 if ((rc
= RegQueryValue(hKey
, subKey
, retBuf
, &bufSize
))
1297 return PyErr_SetFromWindowsErrWithFunction(rc
,
1300 _PyString_Resize(&retStr
, strlen(retBuf
));
1305 PyQueryValueEx(PyObject
*self
, PyObject
*args
)
1318 if (!PyArg_ParseTuple(args
, "Oz:QueryValueEx", &obKey
, &valueName
))
1321 if (!PyHKEY_AsHKEY(obKey
, &hKey
, FALSE
))
1323 if ((rc
= RegQueryValueEx(hKey
, valueName
,
1327 return PyErr_SetFromWindowsErrWithFunction(rc
,
1329 retBuf
= (char *)PyMem_Malloc(bufSize
);
1331 return PyErr_NoMemory();
1332 if ((rc
= RegQueryValueEx(hKey
, valueName
, NULL
,
1333 &typ
, (BYTE
*)retBuf
, &bufSize
))
1336 return PyErr_SetFromWindowsErrWithFunction(rc
,
1339 obData
= Reg2Py(retBuf
, bufSize
, typ
);
1340 PyMem_Free((void *)retBuf
);
1343 result
= Py_BuildValue("Oi", obData
, typ
);
1350 PySaveKey(PyObject
*self
, PyObject
*args
)
1355 LPSECURITY_ATTRIBUTES pSA
= NULL
;
1358 if (!PyArg_ParseTuple(args
, "Os:SaveKey", &obKey
, &fileName
))
1360 if (!PyHKEY_AsHKEY(obKey
, &hKey
, FALSE
))
1362 /* One day we may get security into the core?
1363 if (!PyWinObject_AsSECURITY_ATTRIBUTES(obSA, &pSA, TRUE))
1366 Py_BEGIN_ALLOW_THREADS
1367 rc
= RegSaveKey(hKey
, fileName
, pSA
);
1368 Py_END_ALLOW_THREADS
1369 if (rc
!= ERROR_SUCCESS
)
1370 return PyErr_SetFromWindowsErrWithFunction(rc
, "RegSaveKey");
1376 PySetValue(PyObject
*self
, PyObject
*args
)
1387 if (!PyArg_ParseTuple(args
, "OOiO:SetValue",
1393 if (!PyHKEY_AsHKEY(obKey
, &hKey
, FALSE
))
1395 if (typ
!= REG_SZ
) {
1396 PyErr_SetString(PyExc_TypeError
,
1397 "Type must be _winreg.REG_SZ");
1400 /* XXX - need Unicode support */
1401 str
= PyString_AsString(obStrVal
);
1404 len
= PyString_Size(obStrVal
);
1405 if (obSubKey
== Py_None
)
1408 subKey
= PyString_AsString(obSubKey
);
1412 Py_BEGIN_ALLOW_THREADS
1413 rc
= RegSetValue(hKey
, subKey
, REG_SZ
, str
, len
+1);
1414 Py_END_ALLOW_THREADS
1415 if (rc
!= ERROR_SUCCESS
)
1416 return PyErr_SetFromWindowsErrWithFunction(rc
, "RegSetValue");
1422 PySetValueEx(PyObject
*self
, PyObject
*args
)
1435 if (!PyArg_ParseTuple(args
, "OzOiO:SetValueEx",
1442 if (!PyHKEY_AsHKEY(obKey
, &hKey
, FALSE
))
1444 if (!Py2Reg(value
, typ
, &data
, &len
))
1446 if (!PyErr_Occurred())
1447 PyErr_SetString(PyExc_ValueError
,
1448 "Could not convert the data to the specified type.");
1451 Py_BEGIN_ALLOW_THREADS
1452 rc
= RegSetValueEx(hKey
, valueName
, 0, typ
, data
, len
);
1453 Py_END_ALLOW_THREADS
1455 if (rc
!= ERROR_SUCCESS
)
1456 return PyErr_SetFromWindowsErrWithFunction(rc
,
1462 static struct PyMethodDef winreg_methods
[] = {
1463 {"CloseKey", PyCloseKey
, METH_VARARGS
, CloseKey_doc
},
1464 {"ConnectRegistry", PyConnectRegistry
, METH_VARARGS
, ConnectRegistry_doc
},
1465 {"CreateKey", PyCreateKey
, METH_VARARGS
, CreateKey_doc
},
1466 {"DeleteKey", PyDeleteKey
, METH_VARARGS
, DeleteKey_doc
},
1467 {"DeleteValue", PyDeleteValue
, METH_VARARGS
, DeleteValue_doc
},
1468 {"EnumKey", PyEnumKey
, METH_VARARGS
, EnumKey_doc
},
1469 {"EnumValue", PyEnumValue
, METH_VARARGS
, EnumValue_doc
},
1470 {"ExpandEnvironmentStrings", PyExpandEnvironmentStrings
, METH_VARARGS
,
1471 ExpandEnvironmentStrings_doc
},
1472 {"FlushKey", PyFlushKey
, METH_VARARGS
, FlushKey_doc
},
1473 {"LoadKey", PyLoadKey
, METH_VARARGS
, LoadKey_doc
},
1474 {"OpenKey", PyOpenKey
, METH_VARARGS
, OpenKey_doc
},
1475 {"OpenKeyEx", PyOpenKey
, METH_VARARGS
, OpenKeyEx_doc
},
1476 {"QueryValue", PyQueryValue
, METH_VARARGS
, QueryValue_doc
},
1477 {"QueryValueEx", PyQueryValueEx
, METH_VARARGS
, QueryValueEx_doc
},
1478 {"QueryInfoKey", PyQueryInfoKey
, METH_VARARGS
, QueryInfoKey_doc
},
1479 {"SaveKey", PySaveKey
, METH_VARARGS
, SaveKey_doc
},
1480 {"SetValue", PySetValue
, METH_VARARGS
, SetValue_doc
},
1481 {"SetValueEx", PySetValueEx
, METH_VARARGS
, SetValueEx_doc
},
1486 insint(PyObject
* d
, char * name
, long value
)
1488 PyObject
*v
= PyInt_FromLong(value
);
1489 if (!v
|| PyDict_SetItemString(d
, name
, v
))
1494 #define ADD_INT(val) insint(d, #val, val)
1497 inskey(PyObject
* d
, char * name
, HKEY key
)
1499 PyObject
*v
= PyLong_FromVoidPtr(key
);
1500 if (!v
|| PyDict_SetItemString(d
, name
, v
))
1505 #define ADD_KEY(val) inskey(d, #val, val)
1507 PyMODINIT_FUNC
init_winreg(void)
1510 m
= Py_InitModule3("_winreg", winreg_methods
, module_doc
);
1513 d
= PyModule_GetDict(m
);
1514 PyHKEY_Type
.ob_type
= &PyType_Type
;
1515 PyHKEY_Type
.tp_doc
= PyHKEY_doc
;
1516 Py_INCREF(&PyHKEY_Type
);
1517 if (PyDict_SetItemString(d
, "HKEYType",
1518 (PyObject
*)&PyHKEY_Type
) != 0)
1520 Py_INCREF(PyExc_WindowsError
);
1521 if (PyDict_SetItemString(d
, "error",
1522 PyExc_WindowsError
) != 0)
1525 /* Add the relevant constants */
1526 ADD_KEY(HKEY_CLASSES_ROOT
);
1527 ADD_KEY(HKEY_CURRENT_USER
);
1528 ADD_KEY(HKEY_LOCAL_MACHINE
);
1529 ADD_KEY(HKEY_USERS
);
1530 ADD_KEY(HKEY_PERFORMANCE_DATA
);
1531 #ifdef HKEY_CURRENT_CONFIG
1532 ADD_KEY(HKEY_CURRENT_CONFIG
);
1534 #ifdef HKEY_DYN_DATA
1535 ADD_KEY(HKEY_DYN_DATA
);
1537 ADD_INT(KEY_QUERY_VALUE
);
1538 ADD_INT(KEY_SET_VALUE
);
1539 ADD_INT(KEY_CREATE_SUB_KEY
);
1540 ADD_INT(KEY_ENUMERATE_SUB_KEYS
);
1541 ADD_INT(KEY_NOTIFY
);
1542 ADD_INT(KEY_CREATE_LINK
);
1545 ADD_INT(KEY_EXECUTE
);
1546 ADD_INT(KEY_ALL_ACCESS
);
1547 ADD_INT(REG_OPTION_RESERVED
);
1548 ADD_INT(REG_OPTION_NON_VOLATILE
);
1549 ADD_INT(REG_OPTION_VOLATILE
);
1550 ADD_INT(REG_OPTION_CREATE_LINK
);
1551 ADD_INT(REG_OPTION_BACKUP_RESTORE
);
1552 ADD_INT(REG_OPTION_OPEN_LINK
);
1553 ADD_INT(REG_LEGAL_OPTION
);
1554 ADD_INT(REG_CREATED_NEW_KEY
);
1555 ADD_INT(REG_OPENED_EXISTING_KEY
);
1556 ADD_INT(REG_WHOLE_HIVE_VOLATILE
);
1557 ADD_INT(REG_REFRESH_HIVE
);
1558 ADD_INT(REG_NO_LAZY_FLUSH
);
1559 ADD_INT(REG_NOTIFY_CHANGE_NAME
);
1560 ADD_INT(REG_NOTIFY_CHANGE_ATTRIBUTES
);
1561 ADD_INT(REG_NOTIFY_CHANGE_LAST_SET
);
1562 ADD_INT(REG_NOTIFY_CHANGE_SECURITY
);
1563 ADD_INT(REG_LEGAL_CHANGE_FILTER
);
1566 ADD_INT(REG_EXPAND_SZ
);
1567 ADD_INT(REG_BINARY
);
1569 ADD_INT(REG_DWORD_LITTLE_ENDIAN
);
1570 ADD_INT(REG_DWORD_BIG_ENDIAN
);
1572 ADD_INT(REG_MULTI_SZ
);
1573 ADD_INT(REG_RESOURCE_LIST
);
1574 ADD_INT(REG_FULL_RESOURCE_DESCRIPTOR
);
1575 ADD_INT(REG_RESOURCE_REQUIREMENTS_LIST
);