summaryrefslogtreecommitdiffstats
path: root/contrib/tools/python/src/PC
diff options
context:
space:
mode:
authornkozlovskiy <[email protected]>2023-09-29 12:24:06 +0300
committernkozlovskiy <[email protected]>2023-09-29 12:41:34 +0300
commite0e3e1717e3d33762ce61950504f9637a6e669ed (patch)
treebca3ff6939b10ed60c3d5c12439963a1146b9711 /contrib/tools/python/src/PC
parent38f2c5852db84c7b4d83adfcb009eb61541d1ccd (diff)
add ydb deps
Diffstat (limited to 'contrib/tools/python/src/PC')
-rw-r--r--contrib/tools/python/src/PC/_subprocess.c822
-rw-r--r--contrib/tools/python/src/PC/_winreg.c1872
-rw-r--r--contrib/tools/python/src/PC/dl_nt.c106
-rw-r--r--contrib/tools/python/src/PC/errmap.h78
-rw-r--r--contrib/tools/python/src/PC/getpathp.c715
-rw-r--r--contrib/tools/python/src/PC/import_nt.c86
-rw-r--r--contrib/tools/python/src/PC/msvcrtmodule.c430
7 files changed, 4109 insertions, 0 deletions
diff --git a/contrib/tools/python/src/PC/_subprocess.c b/contrib/tools/python/src/PC/_subprocess.c
new file mode 100644
index 00000000000..5d0665d564a
--- /dev/null
+++ b/contrib/tools/python/src/PC/_subprocess.c
@@ -0,0 +1,822 @@
+/*
+ * support routines for subprocess module
+ *
+ * Currently, this extension module is only required when using the
+ * subprocess module on Windows, but in the future, stubs for other
+ * platforms might be added here as well.
+ *
+ * Copyright (c) 2004 by Fredrik Lundh <[email protected]>
+ * Copyright (c) 2004 by Secret Labs AB, http://www.pythonware.com
+ * Copyright (c) 2004 by Peter Astrand <[email protected]>
+ *
+ * By obtaining, using, and/or copying this software and/or its
+ * associated documentation, you agree that you have read, understood,
+ * and will comply with the following terms and conditions:
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its associated documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice appears in
+ * all copies, and that both that copyright notice and this permission
+ * notice appear in supporting documentation, and that the name of the
+ * authors not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission.
+ *
+ * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/* Licensed to PSF under a Contributor Agreement. */
+/* See http://www.python.org/2.4/license for licensing details. */
+
+/* TODO: handle unicode command lines? */
+/* TODO: handle unicode environment? */
+
+#include "Python.h"
+
+#define WINDOWS_LEAN_AND_MEAN
+#include "windows.h"
+
+/* -------------------------------------------------------------------- */
+/* handle wrapper. note that this library uses integers when passing
+ handles to a function, and handle wrappers when returning handles.
+ the wrapper is used to provide Detach and Close methods */
+
+typedef struct {
+ PyObject_HEAD
+ HANDLE handle;
+} sp_handle_object;
+
+staticforward PyTypeObject sp_handle_type;
+
+static PyObject*
+sp_handle_new(HANDLE handle)
+{
+ sp_handle_object* self;
+
+ self = PyObject_NEW(sp_handle_object, &sp_handle_type);
+ if (self == NULL)
+ return NULL;
+
+ self->handle = handle;
+
+ return (PyObject*) self;
+}
+
+#if defined(MS_WIN32) && !defined(MS_WIN64)
+#define HANDLE_TO_PYNUM(handle) PyInt_FromLong((long) handle)
+#define PY_HANDLE_PARAM "l"
+#else
+#define HANDLE_TO_PYNUM(handle) PyLong_FromLongLong((long long) handle)
+#define PY_HANDLE_PARAM "L"
+#endif
+
+static PyObject*
+sp_handle_detach(sp_handle_object* self, PyObject* args)
+{
+ HANDLE handle;
+
+ if (! PyArg_ParseTuple(args, ":Detach"))
+ return NULL;
+
+ handle = self->handle;
+
+ self->handle = INVALID_HANDLE_VALUE;
+
+ /* note: return the current handle, as an integer */
+ return HANDLE_TO_PYNUM(handle);
+}
+
+static PyObject*
+sp_handle_close(sp_handle_object* self, PyObject* args)
+{
+ if (! PyArg_ParseTuple(args, ":Close"))
+ return NULL;
+
+ if (self->handle != INVALID_HANDLE_VALUE) {
+ CloseHandle(self->handle);
+ self->handle = INVALID_HANDLE_VALUE;
+ }
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static void
+sp_handle_dealloc(sp_handle_object* self)
+{
+ if (self->handle != INVALID_HANDLE_VALUE)
+ CloseHandle(self->handle);
+ PyObject_FREE(self);
+}
+
+static PyMethodDef sp_handle_methods[] = {
+ {"Detach", (PyCFunction) sp_handle_detach, METH_VARARGS},
+ {"Close", (PyCFunction) sp_handle_close, METH_VARARGS},
+ {NULL, NULL}
+};
+
+static PyObject*
+sp_handle_getattr(sp_handle_object* self, char* name)
+{
+ return Py_FindMethod(sp_handle_methods, (PyObject*) self, name);
+}
+
+static PyObject*
+sp_handle_as_int(sp_handle_object* self)
+{
+ return HANDLE_TO_PYNUM(self->handle);
+}
+
+static PyNumberMethods sp_handle_as_number;
+
+statichere PyTypeObject sp_handle_type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /*ob_size*/
+ "_subprocess_handle", sizeof(sp_handle_object), 0,
+ (destructor) sp_handle_dealloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ (getattrfunc) sp_handle_getattr,/*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ &sp_handle_as_number, /*tp_as_number */
+ 0, /*tp_as_sequence */
+ 0, /*tp_as_mapping */
+ 0 /*tp_hash*/
+};
+
+/* -------------------------------------------------------------------- */
+/* windows API functions */
+
+PyDoc_STRVAR(GetStdHandle_doc,
+"GetStdHandle(handle) -> integer\n\
+\n\
+Return a handle to the specified standard device\n\
+(STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, STD_ERROR_HANDLE).\n\
+The integer associated with the handle object is returned.");
+
+static PyObject *
+sp_GetStdHandle(PyObject* self, PyObject* args)
+{
+ HANDLE handle;
+ int std_handle;
+
+ if (! PyArg_ParseTuple(args, "i:GetStdHandle", &std_handle))
+ return NULL;
+
+ Py_BEGIN_ALLOW_THREADS
+ handle = GetStdHandle((DWORD) std_handle);
+ Py_END_ALLOW_THREADS
+
+ if (handle == INVALID_HANDLE_VALUE)
+ return PyErr_SetFromWindowsErr(GetLastError());
+
+ if (! handle) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ /* note: returns integer, not handle object */
+ return HANDLE_TO_PYNUM(handle);
+}
+
+PyDoc_STRVAR(GetCurrentProcess_doc,
+"GetCurrentProcess() -> handle\n\
+\n\
+Return a handle object for the current process.");
+
+static PyObject *
+sp_GetCurrentProcess(PyObject* self, PyObject* args)
+{
+ if (! PyArg_ParseTuple(args, ":GetCurrentProcess"))
+ return NULL;
+
+ return sp_handle_new(GetCurrentProcess());
+}
+
+PyDoc_STRVAR(DuplicateHandle_doc,
+"DuplicateHandle(source_proc_handle, source_handle,\n\
+ target_proc_handle, target_handle, access,\n\
+ inherit[, options]) -> handle\n\
+\n\
+Return a duplicate handle object.\n\
+\n\
+The duplicate handle refers to the same object as the original\n\
+handle. Therefore, any changes to the object are reflected\n\
+through both handles.");
+
+static PyObject *
+sp_DuplicateHandle(PyObject* self, PyObject* args)
+{
+ HANDLE target_handle;
+ BOOL result;
+
+ HANDLE source_process_handle;
+ HANDLE source_handle;
+ HANDLE target_process_handle;
+ int desired_access;
+ int inherit_handle;
+ int options = 0;
+
+ if (! PyArg_ParseTuple(args,
+ PY_HANDLE_PARAM PY_HANDLE_PARAM PY_HANDLE_PARAM
+ "ii|i:DuplicateHandle",
+ &source_process_handle,
+ &source_handle,
+ &target_process_handle,
+ &desired_access,
+ &inherit_handle,
+ &options))
+ return NULL;
+
+ Py_BEGIN_ALLOW_THREADS
+ result = DuplicateHandle(
+ source_process_handle,
+ source_handle,
+ target_process_handle,
+ &target_handle,
+ desired_access,
+ inherit_handle,
+ options
+ );
+ Py_END_ALLOW_THREADS
+
+ if (! result)
+ return PyErr_SetFromWindowsErr(GetLastError());
+
+ return sp_handle_new(target_handle);
+}
+
+PyDoc_STRVAR(CreatePipe_doc,
+"CreatePipe(pipe_attrs, size) -> (read_handle, write_handle)\n\
+\n\
+Create an anonymous pipe, and return handles to the read and\n\
+write ends of the pipe.\n\
+\n\
+pipe_attrs is ignored internally and can be None.");
+
+static PyObject *
+sp_CreatePipe(PyObject* self, PyObject* args)
+{
+ HANDLE read_pipe;
+ HANDLE write_pipe;
+ BOOL result;
+
+ PyObject* pipe_attributes; /* ignored */
+ int size;
+
+ if (! PyArg_ParseTuple(args, "Oi:CreatePipe", &pipe_attributes, &size))
+ return NULL;
+
+ Py_BEGIN_ALLOW_THREADS
+ result = CreatePipe(&read_pipe, &write_pipe, NULL, size);
+ Py_END_ALLOW_THREADS
+
+ if (! result)
+ return PyErr_SetFromWindowsErr(GetLastError());
+
+ return Py_BuildValue(
+ "NN", sp_handle_new(read_pipe), sp_handle_new(write_pipe));
+}
+
+/* helpers for createprocess */
+
+static int
+getint(PyObject* obj, char* name)
+{
+ PyObject* value;
+ int ret;
+
+ value = PyObject_GetAttrString(obj, name);
+ if (! value) {
+ PyErr_Clear(); /* FIXME: propagate error? */
+ return 0;
+ }
+ ret = (int) PyInt_AsLong(value);
+ Py_DECREF(value);
+ return ret;
+}
+
+static HANDLE
+gethandle(PyObject* obj, char* name)
+{
+ sp_handle_object* value;
+ HANDLE ret;
+
+ value = (sp_handle_object*) PyObject_GetAttrString(obj, name);
+ if (! value) {
+ PyErr_Clear(); /* FIXME: propagate error? */
+ return NULL;
+ }
+ if (value->ob_type != &sp_handle_type)
+ ret = NULL;
+ else
+ ret = value->handle;
+ Py_DECREF(value);
+ return ret;
+}
+
+// DEVTOOLS-1825
+static char* ResizeEnv(char* envEnd, PyObject** env, int addSize) {
+ int newSize = (envEnd - PyString_AS_STRING(*env)) + addSize + 2;
+ if (newSize > PyString_GET_SIZE(*env)) {
+ int offset = envEnd - PyString_AS_STRING(*env);
+ _PyString_Resize(env, newSize + 1024);
+ /* In Python 2.7.11:
+ if (_PyString_Resize(&out, totalsize + 1024))
+ goto exit;
+ */
+ envEnd = PyString_AS_STRING(*env) + offset;
+ }
+ return envEnd;
+}
+
+// DEVTOOLS-1825
+static char* AddEnvKeyValue(char* envEnd, PyObject** env, const char* key, int keySize, const char* value, int valueSize) {
+ envEnd = ResizeEnv(envEnd, env, keySize + valueSize + 1);
+ memcpy(envEnd, key, keySize);
+ envEnd += keySize;
+ *envEnd++ = '=';
+ memcpy(envEnd, value, valueSize);
+ envEnd += valueSize;
+ *envEnd++ = '\0';
+ return envEnd;
+}
+
+// DEVTOOLS-1825
+static char* AddEnvVar(char* envEnd, PyObject** env, const char* var, int size) {
+ envEnd = ResizeEnv(envEnd, env, size);
+ memcpy(envEnd, var, size);
+ envEnd += size;
+ *envEnd++ = '\0';
+ return envEnd;
+}
+
+// DEVTOOLS-1825: env data types
+enum EEnvDataType {
+ EDT_REGULAR = 0x1, // regular env vars
+ EDT_SPECIAL = 0x2, // special env vars that start with '='
+};
+
+// DEVTOOLS-1825: construct curdir env variable
+// Returns TRUE if variable is based on real current drive, synthetic empty =C: variable is used instead
+// Buffer for variable must have MAX_PATH + 4 size
+// TODO: when CRT is patched this code should be removed
+static int ConstructCurDirVar(char* var) {
+ memcpy(var, "=C:=", 4);
+ DWORD valueSize = GetCurrentDirectoryA(MAX_PATH, var + 4);
+ if (!valueSize || (valueSize > MAX_PATH - 1)) {
+#ifdef _DEBUG
+ fprintf(stderr, "[devtools] Warn: can't get current directory to construct curdir env var\n");
+#endif
+ return 4;
+ }
+ if (!IsCharAlpha(var[4])) {
+#ifdef _DEBUG
+ fprintf(stderr, "[devtools] Warn: can't determine current drive to construct curdir env var\n");
+#endif
+ return 4;
+ }
+ var[1] = var[4];
+ return valueSize + 4;
+}
+
+// DEVTOOLS-1825: add to env parent environment data
+// dataType: type of data to copy, special
+// constructCurDirVar: if enabled code tries to reconstruct curdir env var for current drive (=X:=PATH) if it's not in the parent env
+// TODO: when CRT is patched regular data copying and curdir vat construction should be removed
+static char* AddParentEnvData(char* envEnd, PyObject** env, enum EEnvDataType dataType, BOOL constructCurDirVar) {
+ const char* parentEnv = NULL;
+ const char* var = NULL;
+ int size = 0;
+ char curDirVar[MAX_PATH + 4];
+ int curDirVarSize = 0;
+ BOOL curDirVarAdded = FALSE;
+ if (constructCurDirVar) {
+ curDirVarSize = ConstructCurDirVar(curDirVar);
+ }
+ parentEnv = GetEnvironmentStringsA();
+ if (dataType & EDT_SPECIAL) {
+ for (var = parentEnv; *var; var += size + 1) {
+ size = strlen(var);
+ if (var[0] != '=') {
+ continue;
+ }
+ if (constructCurDirVar && !curDirVarAdded && !strncmp(var, curDirVar, 4)) {
+ curDirVarAdded = TRUE;
+ }
+ envEnd = AddEnvVar(envEnd, env, var, size);
+ }
+ }
+ if (constructCurDirVar && !curDirVarAdded) {
+#ifdef _DEBUG
+ curDirVar[curDirVarSize] = '\0';
+ fprintf(stderr, "[devtools] No curdir env data found, constructing on the fly: %s\n", curDirVar);
+#endif
+ envEnd = AddEnvVar(envEnd, env, curDirVar, curDirVarSize);
+ }
+ if (dataType & EDT_REGULAR) {
+ for (var = parentEnv; *var; var += size + 1) {
+ size = strlen(var);
+ if (var[0] == '=') {
+ continue;
+ }
+ envEnd = AddEnvVar(envEnd, env, var, size);
+ }
+ }
+ FreeEnvironmentStringsA(parentEnv);
+ return envEnd;
+}
+
+static PyObject*
+getenvironment(PyObject* environment)
+{
+ int i, envsize;
+ PyObject* out = NULL;
+ PyObject* keys;
+ PyObject* values;
+ char* p;
+
+ /* convert environment dictionary to windows environment string */
+ if (! PyMapping_Check(environment)) {
+ PyErr_SetString(
+ PyExc_TypeError, "environment must be dictionary or None");
+ return NULL;
+ }
+
+ envsize = PyMapping_Length(environment);
+
+ keys = PyMapping_Keys(environment);
+ if (!keys) {
+ return NULL;
+ }
+ values = PyMapping_Values(environment);
+ if (!values) {
+ goto error;
+ }
+
+ out = PyString_FromStringAndSize(NULL, 2048);
+ if (! out)
+ goto error;
+
+ p = PyString_AS_STRING(out);
+
+ // DEVTOOLS-1825: copy special env data: it contains curdir per drive info (=X:=PATH)
+ // TODO: when CRT is patched disable constructCurDirVar
+ p = AddParentEnvData(p, &out, EDT_SPECIAL, TRUE);
+
+ for (i = 0; i < envsize; i++) {
+ size_t ksize, vsize, totalsize;
+ PyObject* key = PyList_GET_ITEM(keys, i);
+ PyObject* value = PyList_GET_ITEM(values, i);
+
+ if (! PyString_Check(key) || ! PyString_Check(value)) {
+ PyErr_SetString(PyExc_TypeError,
+ "environment can only contain strings");
+ goto error;
+ }
+ ksize = PyString_GET_SIZE(key);
+ vsize = PyString_GET_SIZE(value);
+ if (strlen(PyString_AS_STRING(key)) != ksize ||
+ strlen(PyString_AS_STRING(value)) != vsize)
+ {
+ PyErr_SetString(PyExc_TypeError, "embedded null character");
+ goto error;
+ }
+ /* Search from index 1 because on Windows starting '=' is allowed for
+ defining hidden environment variables. */
+ if (ksize == 0 || strchr(PyString_AS_STRING(key) + 1, '=') != NULL) {
+ PyErr_SetString(PyExc_ValueError, "illegal environment variable name");
+ goto error;
+ }
+ totalsize = (p - PyString_AS_STRING(out)) + ksize + 1 +
+ vsize + 1 + 1;
+ if (totalsize > (size_t)PyString_GET_SIZE(out)) {
+ size_t offset = p - PyString_AS_STRING(out);
+ if (_PyString_Resize(&out, totalsize + 1024))
+ goto exit;
+ p = PyString_AS_STRING(out) + offset;
+ }
+ memcpy(p, PyString_AS_STRING(key), ksize);
+ p += ksize;
+ *p++ = '=';
+ memcpy(p, PyString_AS_STRING(value), vsize);
+ p += vsize;
+ *p++ = '\0';
+ }
+
+ /* add trailing null byte */
+ *p++ = '\0';
+ _PyString_Resize(&out, p - PyString_AS_STRING(out));
+
+ /* PyObject_Print(out, stdout, 0); */
+exit:
+ Py_XDECREF(keys);
+ Py_XDECREF(values);
+
+ return out;
+
+ error:
+ Py_XDECREF(out);
+ Py_XDECREF(keys);
+ Py_XDECREF(values);
+ return NULL;
+}
+
+static PyObject* ReconstructEnvironment() {
+ PyObject* env = PyString_FromStringAndSize(NULL, 2048);
+ if (!env) {
+ return NULL;
+ }
+ char* p = PyString_AS_STRING(env);
+ p = AddParentEnvData(p, &env, EDT_REGULAR | EDT_SPECIAL, TRUE);
+ *p++ = '\0';
+ _PyString_Resize(&env, p - PyString_AS_STRING(env));
+ return env;
+}
+
+PyDoc_STRVAR(CreateProcess_doc,
+"CreateProcess(app_name, cmd_line, proc_attrs, thread_attrs,\n\
+ inherit, flags, env_mapping, curdir,\n\
+ startup_info) -> (proc_handle, thread_handle,\n\
+ pid, tid)\n\
+\n\
+Create a new process and its primary thread. The return\n\
+value is a tuple of the process handle, thread handle,\n\
+process ID, and thread ID.\n\
+\n\
+proc_attrs and thread_attrs are ignored internally and can be None.");
+
+static PyObject *
+sp_CreateProcess(PyObject* self, PyObject* args)
+{
+ BOOL result;
+ PROCESS_INFORMATION pi;
+ STARTUPINFO si;
+ PyObject* environment;
+
+ char* application_name;
+ char* command_line;
+ PyObject* process_attributes; /* ignored */
+ PyObject* thread_attributes; /* ignored */
+ int inherit_handles;
+ int creation_flags;
+ PyObject* env_mapping;
+ char* current_directory;
+ PyObject* startup_info;
+
+ if (! PyArg_ParseTuple(args, "zzOOiiOzO:CreateProcess",
+ &application_name,
+ &command_line,
+ &process_attributes,
+ &thread_attributes,
+ &inherit_handles,
+ &creation_flags,
+ &env_mapping,
+ &current_directory,
+ &startup_info))
+ return NULL;
+
+ ZeroMemory(&si, sizeof(si));
+ si.cb = sizeof(si);
+
+ /* note: we only support a small subset of all SI attributes */
+ si.dwFlags = getint(startup_info, "dwFlags");
+ si.wShowWindow = getint(startup_info, "wShowWindow");
+ si.hStdInput = gethandle(startup_info, "hStdInput");
+ si.hStdOutput = gethandle(startup_info, "hStdOutput");
+ si.hStdError = gethandle(startup_info, "hStdError");
+
+ if (PyErr_Occurred())
+ return NULL;
+
+ if (env_mapping == Py_None)
+ // DEVTOOLS-1825
+ // TODO: restore original code when CRT is patched
+ //environment = NULL;
+ environment = ReconstructEnvironment();
+ else {
+ environment = getenvironment(env_mapping);
+ if (! environment)
+ return NULL;
+ }
+
+ Py_BEGIN_ALLOW_THREADS
+ result = CreateProcess(application_name,
+ command_line,
+ NULL,
+ NULL,
+ inherit_handles,
+ creation_flags,
+ environment ? PyString_AS_STRING(environment) : NULL,
+ current_directory,
+ &si,
+ &pi);
+ Py_END_ALLOW_THREADS
+
+ Py_XDECREF(environment);
+
+ if (! result)
+ return PyErr_SetFromWindowsErr(GetLastError());
+
+ return Py_BuildValue("NNii",
+ sp_handle_new(pi.hProcess),
+ sp_handle_new(pi.hThread),
+ pi.dwProcessId,
+ pi.dwThreadId);
+}
+
+PyDoc_STRVAR(TerminateProcess_doc,
+"TerminateProcess(handle, exit_code) -> None\n\
+\n\
+Terminate the specified process and all of its threads.");
+
+static PyObject *
+sp_TerminateProcess(PyObject* self, PyObject* args)
+{
+ BOOL result;
+
+ HANDLE process;
+ int exit_code;
+ if (! PyArg_ParseTuple(args, PY_HANDLE_PARAM "i:TerminateProcess",
+ &process, &exit_code))
+ return NULL;
+
+ result = TerminateProcess(process, exit_code);
+
+ if (! result)
+ return PyErr_SetFromWindowsErr(GetLastError());
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+PyDoc_STRVAR(GetExitCodeProcess_doc,
+"GetExitCodeProcess(handle) -> Exit code\n\
+\n\
+Return the termination status of the specified process.");
+
+static PyObject *
+sp_GetExitCodeProcess(PyObject* self, PyObject* args)
+{
+ DWORD exit_code;
+ BOOL result;
+
+ HANDLE process;
+ if (! PyArg_ParseTuple(args, PY_HANDLE_PARAM ":GetExitCodeProcess", &process))
+ return NULL;
+
+ result = GetExitCodeProcess(process, &exit_code);
+
+ if (! result)
+ return PyErr_SetFromWindowsErr(GetLastError());
+
+ return PyInt_FromLong(exit_code);
+}
+
+PyDoc_STRVAR(WaitForSingleObject_doc,
+"WaitForSingleObject(handle, timeout) -> result\n\
+\n\
+Wait until the specified object is in the signaled state or\n\
+the time-out interval elapses. The timeout value is specified\n\
+in milliseconds.");
+
+static PyObject *
+sp_WaitForSingleObject(PyObject* self, PyObject* args)
+{
+ DWORD result;
+
+ HANDLE handle;
+ int milliseconds;
+ if (! PyArg_ParseTuple(args, PY_HANDLE_PARAM "i:WaitForSingleObject",
+ &handle,
+ &milliseconds))
+ return NULL;
+
+ Py_BEGIN_ALLOW_THREADS
+ result = WaitForSingleObject(handle, (DWORD) milliseconds);
+ Py_END_ALLOW_THREADS
+
+ if (result == WAIT_FAILED)
+ return PyErr_SetFromWindowsErr(GetLastError());
+
+ return PyInt_FromLong((int) result);
+}
+
+PyDoc_STRVAR(GetVersion_doc,
+"GetVersion() -> version\n\
+\n\
+Return the version number of the current operating system.");
+
+static PyObject *
+sp_GetVersion(PyObject* self, PyObject* args)
+{
+ if (! PyArg_ParseTuple(args, ":GetVersion"))
+ return NULL;
+
+ return PyInt_FromLong((int) GetVersion());
+}
+
+PyDoc_STRVAR(GetModuleFileName_doc,
+"GetModuleFileName(module) -> path\n\
+\n\
+Return the fully-qualified path for the file that contains\n\
+the specified module. The module must have been loaded by the\n\
+current process.\n\
+\n\
+The module parameter should be a handle to the loaded module\n\
+whose path is being requested. If this parameter is 0, \n\
+GetModuleFileName retrieves the path of the executable file\n\
+of the current process.");
+
+static PyObject *
+sp_GetModuleFileName(PyObject* self, PyObject* args)
+{
+ BOOL result;
+ HMODULE module;
+ TCHAR filename[MAX_PATH];
+
+ if (! PyArg_ParseTuple(args, PY_HANDLE_PARAM ":GetModuleFileName",
+ &module))
+ return NULL;
+
+ result = GetModuleFileName(module, filename, MAX_PATH);
+ filename[MAX_PATH-1] = '\0';
+
+ if (! result)
+ return PyErr_SetFromWindowsErr(GetLastError());
+
+ return PyString_FromString(filename);
+}
+
+static PyMethodDef sp_functions[] = {
+ {"GetStdHandle", sp_GetStdHandle, METH_VARARGS, GetStdHandle_doc},
+ {"GetCurrentProcess", sp_GetCurrentProcess, METH_VARARGS,
+ GetCurrentProcess_doc},
+ {"DuplicateHandle", sp_DuplicateHandle, METH_VARARGS,
+ DuplicateHandle_doc},
+ {"CreatePipe", sp_CreatePipe, METH_VARARGS, CreatePipe_doc},
+ {"CreateProcess", sp_CreateProcess, METH_VARARGS, CreateProcess_doc},
+ {"TerminateProcess", sp_TerminateProcess, METH_VARARGS,
+ TerminateProcess_doc},
+ {"GetExitCodeProcess", sp_GetExitCodeProcess, METH_VARARGS,
+ GetExitCodeProcess_doc},
+ {"WaitForSingleObject", sp_WaitForSingleObject, METH_VARARGS,
+ WaitForSingleObject_doc},
+ {"GetVersion", sp_GetVersion, METH_VARARGS, GetVersion_doc},
+ {"GetModuleFileName", sp_GetModuleFileName, METH_VARARGS,
+ GetModuleFileName_doc},
+ {NULL, NULL}
+};
+
+/* -------------------------------------------------------------------- */
+
+static void
+defint(PyObject* d, const char* name, int value)
+{
+ PyObject* v = PyInt_FromLong((long) value);
+ if (v) {
+ PyDict_SetItemString(d, (char*) name, v);
+ Py_DECREF(v);
+ }
+}
+
+#if PY_VERSION_HEX >= 0x02030000
+PyMODINIT_FUNC
+#else
+DL_EXPORT(void)
+#endif
+init_subprocess()
+{
+ PyObject *d;
+ PyObject *m;
+
+ /* patch up object descriptors */
+ sp_handle_type.ob_type = &PyType_Type;
+ sp_handle_as_number.nb_int = (unaryfunc) sp_handle_as_int;
+
+ m = Py_InitModule("_subprocess", sp_functions);
+ if (m == NULL)
+ return;
+ d = PyModule_GetDict(m);
+
+ /* constants */
+ defint(d, "STD_INPUT_HANDLE", STD_INPUT_HANDLE);
+ defint(d, "STD_OUTPUT_HANDLE", STD_OUTPUT_HANDLE);
+ defint(d, "STD_ERROR_HANDLE", STD_ERROR_HANDLE);
+ defint(d, "DUPLICATE_SAME_ACCESS", DUPLICATE_SAME_ACCESS);
+ defint(d, "STARTF_USESTDHANDLES", STARTF_USESTDHANDLES);
+ defint(d, "STARTF_USESHOWWINDOW", STARTF_USESHOWWINDOW);
+ defint(d, "SW_HIDE", SW_HIDE);
+ defint(d, "INFINITE", INFINITE);
+ defint(d, "WAIT_OBJECT_0", WAIT_OBJECT_0);
+ defint(d, "CREATE_NEW_CONSOLE", CREATE_NEW_CONSOLE);
+ defint(d, "CREATE_NEW_PROCESS_GROUP", CREATE_NEW_PROCESS_GROUP);
+ defint(d, "STILL_ACTIVE", STILL_ACTIVE);
+}
diff --git a/contrib/tools/python/src/PC/_winreg.c b/contrib/tools/python/src/PC/_winreg.c
new file mode 100644
index 00000000000..720f7988d32
--- /dev/null
+++ b/contrib/tools/python/src/PC/_winreg.c
@@ -0,0 +1,1872 @@
+/*
+ _winreg.c
+
+ Windows Registry access module for Python.
+
+ * Simple registry access written by Mark Hammond in win32api
+ module circa 1995.
+ * Bill Tutt expanded the support significantly not long after.
+ * Numerous other people have submitted patches since then.
+ * Ripped from win32api module 03-Feb-2000 by Mark Hammond, and
+ basic Unicode support added.
+
+*/
+
+#include "Python.h"
+#include "structmember.h"
+#include "malloc.h" /* for alloca */
+#include "windows.h"
+
+static BOOL PyHKEY_AsHKEY(PyObject *ob, HKEY *pRes, BOOL bNoneOK);
+static PyObject *PyHKEY_FromHKEY(HKEY h);
+static BOOL PyHKEY_Close(PyObject *obHandle);
+
+static char errNotAHandle[] = "Object is not a handle";
+
+/* The win32api module reports the function name that failed,
+ but this concept is not in the Python core.
+ Hopefully it will one day, and in the meantime I don't
+ want to lose this info...
+*/
+#define PyErr_SetFromWindowsErrWithFunction(rc, fnname) \
+ PyErr_SetFromWindowsErr(rc)
+
+/* Forward declares */
+
+/* Doc strings */
+PyDoc_STRVAR(module_doc,
+"This module provides access to the Windows registry API.\n"
+"\n"
+"Functions:\n"
+"\n"
+"CloseKey() - Closes a registry key.\n"
+"ConnectRegistry() - Establishes a connection to a predefined registry handle\n"
+" on another computer.\n"
+"CreateKey() - Creates the specified key, or opens it if it already exists.\n"
+"DeleteKey() - Deletes the specified key.\n"
+"DeleteValue() - Removes a named value from the specified registry key.\n"
+"EnumKey() - Enumerates subkeys of the specified open registry key.\n"
+"EnumValue() - Enumerates values of the specified open registry key.\n"
+"ExpandEnvironmentStrings() - Expand the env strings in a REG_EXPAND_SZ string.\n"
+"FlushKey() - Writes all the attributes of the specified key to the registry.\n"
+"LoadKey() - Creates a subkey under HKEY_USER or HKEY_LOCAL_MACHINE and stores\n"
+" registration information from a specified file into that subkey.\n"
+"OpenKey() - Alias for <om win32api.RegOpenKeyEx>\n"
+"OpenKeyEx() - Opens the specified key.\n"
+"QueryValue() - Retrieves the value associated with the unnamed value for a\n"
+" specified key in the registry.\n"
+"QueryValueEx() - Retrieves the type and data for a specified value name\n"
+" associated with an open registry key.\n"
+"QueryInfoKey() - Returns information about the specified key.\n"
+"SaveKey() - Saves the specified key, and all its subkeys a file.\n"
+"SetValue() - Associates a value with a specified key.\n"
+"SetValueEx() - Stores data in the value field of an open registry key.\n"
+"\n"
+"Special objects:\n"
+"\n"
+"HKEYType -- type object for HKEY objects\n"
+"error -- exception raised for Win32 errors\n"
+"\n"
+"Integer constants:\n"
+"Many constants are defined - see the documentation for each function\n"
+"to see what constants are used, and where.");
+
+
+PyDoc_STRVAR(CloseKey_doc,
+"CloseKey(hkey) - Closes a previously opened registry key.\n"
+"\n"
+"The hkey argument specifies a previously opened key.\n"
+"\n"
+"Note that if the key is not closed using this method, it will be\n"
+"closed when the hkey object is destroyed by Python.");
+
+PyDoc_STRVAR(ConnectRegistry_doc,
+"key = ConnectRegistry(computer_name, key) - "
+"Establishes a connection to a predefined registry handle on another computer.\n"
+"\n"
+"computer_name is the name of the remote computer, of the form \\\\computername.\n"
+" If None, the local computer is used.\n"
+"key is the predefined handle to connect to.\n"
+"\n"
+"The return value is the handle of the opened key.\n"
+"If the function fails, a WindowsError exception is raised.");
+
+PyDoc_STRVAR(CreateKey_doc,
+"key = CreateKey(key, sub_key) - Creates or opens the specified key.\n"
+"\n"
+"key is an already open key, or one of the predefined HKEY_* constants\n"
+"sub_key is a string that names the key this method opens or creates.\n"
+" If key is one of the predefined keys, sub_key may be None. In that case,\n"
+" the handle returned is the same key handle passed in to the function.\n"
+"\n"
+"If the key already exists, this function opens the existing key\n"
+"\n"
+"The return value is the handle of the opened key.\n"
+"If the function fails, an exception is raised.");
+
+PyDoc_STRVAR(CreateKeyEx_doc,
+"key = CreateKeyEx(key, sub_key, res, sam) - Creates or opens the specified key.\n"
+"\n"
+"key is an already open key, or one of the predefined HKEY_* constants\n"
+"sub_key is a string that names the key this method opens or creates.\n"
+"res is a reserved integer, and must be zero. Default is zero.\n"
+"sam is an integer that specifies an access mask that describes the desired\n"
+" If key is one of the predefined keys, sub_key may be None. In that case,\n"
+" the handle returned is the same key handle passed in to the function.\n"
+"\n"
+"If the key already exists, this function opens the existing key\n"
+"\n"
+"The return value is the handle of the opened key.\n"
+"If the function fails, an exception is raised.");
+
+PyDoc_STRVAR(DeleteKey_doc,
+"DeleteKey(key, sub_key) - Deletes the specified key.\n"
+"\n"
+"key is an already open key, or any one of the predefined HKEY_* constants.\n"
+"sub_key is a string that must be a subkey of the key identified by the key parameter.\n"
+" This value must not be None, and the key may not have subkeys.\n"
+"\n"
+"This method can not delete keys with subkeys.\n"
+"\n"
+"If the method succeeds, the entire key, including all of its values,\n"
+"is removed. If the method fails, a WindowsError exception is raised.");
+
+PyDoc_STRVAR(DeleteKeyEx_doc,
+"DeleteKeyEx(key, sub_key, sam, res) - Deletes the specified key.\n"
+"\n"
+"key is an already open key, or any one of the predefined HKEY_* constants.\n"
+"sub_key is a string that must be a subkey of the key identified by the key parameter.\n"
+"res is a reserved integer, and must be zero. Default is zero.\n"
+"sam is an integer that specifies an access mask that describes the desired\n"
+" This value must not be None, and the key may not have subkeys.\n"
+"\n"
+"This method can not delete keys with subkeys.\n"
+"\n"
+"If the method succeeds, the entire key, including all of its values,\n"
+"is removed. If the method fails, a WindowsError exception is raised.\n"
+"On unsupported Windows versions, NotImplementedError is raised.");
+
+PyDoc_STRVAR(DeleteValue_doc,
+"DeleteValue(key, value) - Removes a named value from a registry key.\n"
+"\n"
+"key is an already open key, or any one of the predefined HKEY_* constants.\n"
+"value is a string that identifies the value to remove.");
+
+PyDoc_STRVAR(EnumKey_doc,
+"string = EnumKey(key, index) - Enumerates subkeys of an open registry key.\n"
+"\n"
+"key is an already open key, or any one of the predefined HKEY_* constants.\n"
+"index is an integer that identifies the index of the key to retrieve.\n"
+"\n"
+"The function retrieves the name of one subkey each time it is called.\n"
+"It is typically called repeatedly until a WindowsError exception is\n"
+"raised, indicating no more values are available.");
+
+PyDoc_STRVAR(EnumValue_doc,
+"tuple = EnumValue(key, index) - Enumerates values of an open registry key.\n"
+"key is an already open key, or any one of the predefined HKEY_* constants.\n"
+"index is an integer that identifies the index of the value to retrieve.\n"
+"\n"
+"The function retrieves the name of one subkey each time it is called.\n"
+"It is typically called repeatedly, until a WindowsError exception\n"
+"is raised, indicating no more values.\n"
+"\n"
+"The result is a tuple of 3 items:\n"
+"value_name is a string that identifies the value.\n"
+"value_data is an object that holds the value data, and whose type depends\n"
+" on the underlying registry type.\n"
+"data_type is an integer that identifies the type of the value data.");
+
+PyDoc_STRVAR(ExpandEnvironmentStrings_doc,
+"string = ExpandEnvironmentStrings(string) - Expand environment vars.\n");
+
+PyDoc_STRVAR(FlushKey_doc,
+"FlushKey(key) - Writes all the attributes of a key to the registry.\n"
+"\n"
+"key is an already open key, or any one of the predefined HKEY_* constants.\n"
+"\n"
+"It is not necessary to call RegFlushKey to change a key.\n"
+"Registry changes are flushed to disk by the registry using its lazy flusher.\n"
+"Registry changes are also flushed to disk at system shutdown.\n"
+"Unlike CloseKey(), the FlushKey() method returns only when all the data has\n"
+"been written to the registry.\n"
+"An application should only call FlushKey() if it requires absolute certainty that registry changes are on disk.\n"
+"If you don't know whether a FlushKey() call is required, it probably isn't.");
+
+PyDoc_STRVAR(LoadKey_doc,
+"LoadKey(key, sub_key, file_name) - Creates a subkey under the specified key\n"
+"and stores registration information from a specified file into that subkey.\n"
+"\n"
+"key is an already open key, or any one of the predefined HKEY_* constants.\n"
+"sub_key is a string that identifies the sub_key to load\n"
+"file_name is the name of the file to load registry data from.\n"
+" This file must have been created with the SaveKey() function.\n"
+" Under the file allocation table (FAT) file system, the filename may not\n"
+"have an extension.\n"
+"\n"
+"A call to LoadKey() fails if the calling process does not have the\n"
+"SE_RESTORE_PRIVILEGE privilege.\n"
+"\n"
+"If key is a handle returned by ConnectRegistry(), then the path specified\n"
+"in fileName is relative to the remote computer.\n"
+"\n"
+"The docs imply key must be in the HKEY_USER or HKEY_LOCAL_MACHINE tree");
+
+PyDoc_STRVAR(OpenKey_doc,
+"key = OpenKey(key, sub_key, res = 0, sam = KEY_READ) - Opens the specified key.\n"
+"\n"
+"key is an already open key, or any one of the predefined HKEY_* constants.\n"
+"sub_key is a string that identifies the sub_key to open\n"
+"res is a reserved integer, and must be zero. Default is zero.\n"
+"sam is an integer that specifies an access mask that describes the desired\n"
+" security access for the key. Default is KEY_READ\n"
+"\n"
+"The result is a new handle to the specified key\n"
+"If the function fails, a WindowsError exception is raised.");
+
+PyDoc_STRVAR(OpenKeyEx_doc, "See OpenKey()");
+
+PyDoc_STRVAR(QueryInfoKey_doc,
+"tuple = QueryInfoKey(key) - Returns information about a key.\n"
+"\n"
+"key is an already open key, or any one of the predefined HKEY_* constants.\n"
+"\n"
+"The result is a tuple of 3 items:"
+"An integer that identifies the number of sub keys this key has.\n"
+"An integer that identifies the number of values this key has.\n"
+"A long integer that identifies when the key was last modified (if available)\n"
+" as 100's of nanoseconds since Jan 1, 1600.");
+
+PyDoc_STRVAR(QueryValue_doc,
+"string = QueryValue(key, sub_key) - retrieves the unnamed value for a key.\n"
+"\n"
+"key is an already open key, or any one of the predefined HKEY_* constants.\n"
+"sub_key is a string that holds the name of the subkey with which the value\n"
+" is associated. If this parameter is None or empty, the function retrieves\n"
+" the value set by the SetValue() method for the key identified by key."
+"\n"
+"Values in the registry have name, type, and data components. This method\n"
+"retrieves the data for a key's first value that has a NULL name.\n"
+"But the underlying API call doesn't return the type, Lame Lame Lame, DONT USE THIS!!!");
+
+PyDoc_STRVAR(QueryValueEx_doc,
+"value,type_id = QueryValueEx(key, value_name) - Retrieves the type and data for a specified value name associated with an open registry key.\n"
+"\n"
+"key is an already open key, or any one of the predefined HKEY_* constants.\n"
+"value_name is a string indicating the value to query");
+
+PyDoc_STRVAR(SaveKey_doc,
+"SaveKey(key, file_name) - Saves the specified key, and all its subkeys to the specified file.\n"
+"\n"
+"key is an already open key, or any one of the predefined HKEY_* constants.\n"
+"file_name is the name of the file to save registry data to.\n"
+" This file cannot already exist. If this filename includes an extension,\n"
+" it cannot be used on file allocation table (FAT) file systems by the\n"
+" LoadKey(), ReplaceKey() or RestoreKey() methods.\n"
+"\n"
+"If key represents a key on a remote computer, the path described by\n"
+"file_name is relative to the remote computer.\n"
+"The caller of this method must possess the SeBackupPrivilege security privilege.\n"
+"This function passes NULL for security_attributes to the API.");
+
+PyDoc_STRVAR(SetValue_doc,
+"SetValue(key, sub_key, type, value) - Associates a value with a specified key.\n"
+"\n"
+"key is an already open key, or any one of the predefined HKEY_* constants.\n"
+"sub_key is a string that names the subkey with which the value is associated.\n"
+"type is an integer that specifies the type of the data. Currently this\n"
+" must be REG_SZ, meaning only strings are supported.\n"
+"value is a string that specifies the new value.\n"
+"\n"
+"If the key specified by the sub_key parameter does not exist, the SetValue\n"
+"function creates it.\n"
+"\n"
+"Value lengths are limited by available memory. Long values (more than\n"
+"2048 bytes) should be stored as files with the filenames stored in \n"
+"the configuration registry. This helps the registry perform efficiently.\n"
+"\n"
+"The key identified by the key parameter must have been opened with\n"
+"KEY_SET_VALUE access.");
+
+PyDoc_STRVAR(SetValueEx_doc,
+"SetValueEx(key, value_name, reserved, type, value) - Stores data in the value field of an open registry key.\n"
+"\n"
+"key is an already open key, or any one of the predefined HKEY_* constants.\n"
+"value_name is a string containing the name of the value to set, or None\n"
+"type is an integer that specifies the type of the data. This should be one of:\n"
+" REG_BINARY -- Binary data in any form.\n"
+" REG_DWORD -- A 32-bit number.\n"
+" REG_DWORD_LITTLE_ENDIAN -- A 32-bit number in little-endian format.\n"
+" REG_DWORD_BIG_ENDIAN -- A 32-bit number in big-endian format.\n"
+" REG_EXPAND_SZ -- A null-terminated string that contains unexpanded references\n"
+" to environment variables (for example, %PATH%).\n"
+" REG_LINK -- A Unicode symbolic link.\n"
+" REG_MULTI_SZ -- A sequence of null-terminated strings, terminated by\n"
+" two null characters. Note that Python handles this\n"
+" termination automatically.\n"
+" REG_NONE -- No defined value type.\n"
+" REG_RESOURCE_LIST -- A device-driver resource list.\n"
+" REG_SZ -- A null-terminated string.\n"
+"reserved can be anything - zero is always passed to the API.\n"
+"value is a string that specifies the new value.\n"
+"\n"
+"This method can also set additional value and type information for the\n"
+"specified key. The key identified by the key parameter must have been\n"
+"opened with KEY_SET_VALUE access.\n"
+"\n"
+"To open the key, use the CreateKeyEx() or OpenKeyEx() methods.\n"
+"\n"
+"Value lengths are limited by available memory. Long values (more than\n"
+"2048 bytes) should be stored as files with the filenames stored in \n"
+"the configuration registry. This helps the registry perform efficiently.");
+
+PyDoc_STRVAR(DisableReflectionKey_doc,
+"Disables registry reflection for 32-bit processes running on a 64-bit\n"
+"Operating System. Will generally raise NotImplemented if executed on\n"
+"a 32-bit Operating System.\n"
+"If the key is not on the reflection list, the function succeeds but has no effect.\n"
+"Disabling reflection for a key does not affect reflection of any subkeys.");
+
+PyDoc_STRVAR(EnableReflectionKey_doc,
+"Restores registry reflection for the specified disabled key.\n"
+"Will generally raise NotImplemented if executed on a 32-bit Operating System.\n"
+"Restoring reflection for a key does not affect reflection of any subkeys.");
+
+PyDoc_STRVAR(QueryReflectionKey_doc,
+"bool = QueryReflectionKey(hkey) - Determines the reflection state for the specified key.\n"
+"Will generally raise NotImplemented if executed on a 32-bit Operating System.\n");
+
+/* PyHKEY docstrings */
+PyDoc_STRVAR(PyHKEY_doc,
+"PyHKEY Object - A Python object, representing a win32 registry key.\n"
+"\n"
+"This object wraps a Windows HKEY object, automatically closing it when\n"
+"the object is destroyed. To guarantee cleanup, you can call either\n"
+"the Close() method on the PyHKEY, or the CloseKey() method.\n"
+"\n"
+"All functions which accept a handle object also accept an integer - \n"
+"however, use of the handle object is encouraged.\n"
+"\n"
+"Functions:\n"
+"Close() - Closes the underlying handle.\n"
+"Detach() - Returns the integer Win32 handle, detaching it from the object\n"
+"\n"
+"Properties:\n"
+"handle - The integer Win32 handle.\n"
+"\n"
+"Operations:\n"
+"__nonzero__ - Handles with an open object return true, otherwise false.\n"
+"__int__ - Converting a handle to an integer returns the Win32 handle.\n"
+"__cmp__ - Handle objects are compared using the handle value.");
+
+
+PyDoc_STRVAR(PyHKEY_Close_doc,
+"key.Close() - Closes the underlying Windows handle.\n"
+"\n"
+"If the handle is already closed, no error is raised.");
+
+PyDoc_STRVAR(PyHKEY_Detach_doc,
+"int = key.Detach() - Detaches the Windows handle from the handle object.\n"
+"\n"
+"The result is the value of the handle before it is detached. If the\n"
+"handle is already detached, this will return zero.\n"
+"\n"
+"After calling this function, the handle is effectively invalidated,\n"
+"but the handle is not closed. You would call this function when you\n"
+"need the underlying win32 handle to exist beyond the lifetime of the\n"
+"handle object.\n"
+"On 64 bit windows, the result of this function is a long integer");
+
+
+/************************************************************************
+
+ The PyHKEY object definition
+
+************************************************************************/
+typedef struct {
+ PyObject_VAR_HEAD
+ HKEY hkey;
+} PyHKEYObject;
+
+#define PyHKEY_Check(op) ((op)->ob_type == &PyHKEY_Type)
+
+static char *failMsg = "bad operand type";
+
+static PyObject *
+PyHKEY_unaryFailureFunc(PyObject *ob)
+{
+ PyErr_SetString(PyExc_TypeError, failMsg);
+ return NULL;
+}
+static PyObject *
+PyHKEY_binaryFailureFunc(PyObject *ob1, PyObject *ob2)
+{
+ PyErr_SetString(PyExc_TypeError, failMsg);
+ return NULL;
+}
+static PyObject *
+PyHKEY_ternaryFailureFunc(PyObject *ob1, PyObject *ob2, PyObject *ob3)
+{
+ PyErr_SetString(PyExc_TypeError, failMsg);
+ return NULL;
+}
+
+static void
+PyHKEY_deallocFunc(PyObject *ob)
+{
+ /* Can not call PyHKEY_Close, as the ob->tp_type
+ has already been cleared, thus causing the type
+ check to fail!
+ */
+ PyHKEYObject *obkey = (PyHKEYObject *)ob;
+ if (obkey->hkey)
+ RegCloseKey((HKEY)obkey->hkey);
+ PyObject_DEL(ob);
+}
+
+static int
+PyHKEY_nonzeroFunc(PyObject *ob)
+{
+ return ((PyHKEYObject *)ob)->hkey != 0;
+}
+
+static PyObject *
+PyHKEY_intFunc(PyObject *ob)
+{
+ PyHKEYObject *pyhkey = (PyHKEYObject *)ob;
+ return PyLong_FromVoidPtr(pyhkey->hkey);
+}
+
+static int
+PyHKEY_printFunc(PyObject *ob, FILE *fp, int flags)
+{
+ PyHKEYObject *pyhkey = (PyHKEYObject *)ob;
+ fprintf(fp, "<PyHKEY at %p (%p)>",
+ ob, pyhkey->hkey);
+ return 0;
+}
+
+static PyObject *
+PyHKEY_strFunc(PyObject *ob)
+{
+ PyHKEYObject *pyhkey = (PyHKEYObject *)ob;
+ return PyString_FromFormat("<PyHKEY:%p>", pyhkey->hkey);
+}
+
+static int
+PyHKEY_compareFunc(PyObject *ob1, PyObject *ob2)
+{
+ PyHKEYObject *pyhkey1 = (PyHKEYObject *)ob1;
+ PyHKEYObject *pyhkey2 = (PyHKEYObject *)ob2;
+ return pyhkey1 == pyhkey2 ? 0 :
+ (pyhkey1 < pyhkey2 ? -1 : 1);
+}
+
+static long
+PyHKEY_hashFunc(PyObject *ob)
+{
+ /* Just use the address.
+ XXX - should we use the handle value?
+ */
+ return _Py_HashPointer(ob);
+}
+
+
+static PyNumberMethods PyHKEY_NumberMethods =
+{
+ PyHKEY_binaryFailureFunc, /* nb_add */
+ PyHKEY_binaryFailureFunc, /* nb_subtract */
+ PyHKEY_binaryFailureFunc, /* nb_multiply */
+ PyHKEY_binaryFailureFunc, /* nb_divide */
+ PyHKEY_binaryFailureFunc, /* nb_remainder */
+ PyHKEY_binaryFailureFunc, /* nb_divmod */
+ PyHKEY_ternaryFailureFunc, /* nb_power */
+ PyHKEY_unaryFailureFunc, /* nb_negative */
+ PyHKEY_unaryFailureFunc, /* nb_positive */
+ PyHKEY_unaryFailureFunc, /* nb_absolute */
+ PyHKEY_nonzeroFunc, /* nb_nonzero */
+ PyHKEY_unaryFailureFunc, /* nb_invert */
+ PyHKEY_binaryFailureFunc, /* nb_lshift */
+ PyHKEY_binaryFailureFunc, /* nb_rshift */
+ PyHKEY_binaryFailureFunc, /* nb_and */
+ PyHKEY_binaryFailureFunc, /* nb_xor */
+ PyHKEY_binaryFailureFunc, /* nb_or */
+ 0, /* nb_coerce (allowed to be zero) */
+ PyHKEY_intFunc, /* nb_int */
+ PyHKEY_unaryFailureFunc, /* nb_long */
+ PyHKEY_unaryFailureFunc, /* nb_float */
+ PyHKEY_unaryFailureFunc, /* nb_oct */
+ PyHKEY_unaryFailureFunc, /* nb_hex */
+};
+
+static PyObject *PyHKEY_CloseMethod(PyObject *self, PyObject *args);
+static PyObject *PyHKEY_DetachMethod(PyObject *self, PyObject *args);
+static PyObject *PyHKEY_Enter(PyObject *self);
+static PyObject *PyHKEY_Exit(PyObject *self, PyObject *args);
+
+static struct PyMethodDef PyHKEY_methods[] = {
+ {"Close", PyHKEY_CloseMethod, METH_VARARGS, PyHKEY_Close_doc},
+ {"Detach", PyHKEY_DetachMethod, METH_VARARGS, PyHKEY_Detach_doc},
+ {"__enter__", (PyCFunction)PyHKEY_Enter, METH_NOARGS, NULL},
+ {"__exit__", PyHKEY_Exit, METH_VARARGS, NULL},
+ {NULL}
+};
+
+static PyMemberDef PyHKEY_memberlist[] = {
+ {"handle", T_PYSSIZET, offsetof(PyHKEYObject, hkey), READONLY},
+ {NULL} /* Sentinel */
+};
+
+/* The type itself */
+PyTypeObject PyHKEY_Type =
+{
+ PyVarObject_HEAD_INIT(0, 0) /* fill in type at module init */
+ "PyHKEY",
+ sizeof(PyHKEYObject),
+ 0,
+ PyHKEY_deallocFunc, /* tp_dealloc */
+ PyHKEY_printFunc, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ PyHKEY_compareFunc, /* tp_compare */
+ 0, /* tp_repr */
+ &PyHKEY_NumberMethods, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ PyHKEY_hashFunc, /* tp_hash */
+ 0, /* tp_call */
+ PyHKEY_strFunc, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ PyHKEY_doc, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ PyHKEY_methods, /* tp_methods */
+ PyHKEY_memberlist, /* tp_members */
+};
+
+/************************************************************************
+
+ The PyHKEY object methods
+
+************************************************************************/
+static PyObject *
+PyHKEY_CloseMethod(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":Close"))
+ return NULL;
+ if (!PyHKEY_Close(self))
+ return NULL;
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+PyHKEY_DetachMethod(PyObject *self, PyObject *args)
+{
+ void* ret;
+ PyHKEYObject *pThis = (PyHKEYObject *)self;
+ if (!PyArg_ParseTuple(args, ":Detach"))
+ return NULL;
+ ret = (void*)pThis->hkey;
+ pThis->hkey = 0;
+ return PyLong_FromVoidPtr(ret);
+}
+
+static PyObject *
+PyHKEY_Enter(PyObject *self)
+{
+ Py_XINCREF(self);
+ return self;
+}
+
+static PyObject *
+PyHKEY_Exit(PyObject *self, PyObject *args)
+{
+ if (!PyHKEY_Close(self))
+ return NULL;
+ Py_RETURN_NONE;
+}
+
+
+/************************************************************************
+ The public PyHKEY API (well, not public yet :-)
+************************************************************************/
+PyObject *
+PyHKEY_New(HKEY hInit)
+{
+ PyHKEYObject *key = PyObject_NEW(PyHKEYObject, &PyHKEY_Type);
+ if (key)
+ key->hkey = hInit;
+ return (PyObject *)key;
+}
+
+BOOL
+PyHKEY_Close(PyObject *ob_handle)
+{
+ LONG rc;
+ PyHKEYObject *key;
+
+ if (!PyHKEY_Check(ob_handle)) {
+ PyErr_SetString(PyExc_TypeError, "bad operand type");
+ return FALSE;
+ }
+ key = (PyHKEYObject *)ob_handle;
+ rc = key->hkey ? RegCloseKey((HKEY)key->hkey) : ERROR_SUCCESS;
+ key->hkey = 0;
+ if (rc != ERROR_SUCCESS)
+ PyErr_SetFromWindowsErrWithFunction(rc, "RegCloseKey");
+ return rc == ERROR_SUCCESS;
+}
+
+BOOL
+PyHKEY_AsHKEY(PyObject *ob, HKEY *pHANDLE, BOOL bNoneOK)
+{
+ if (ob == Py_None) {
+ if (!bNoneOK) {
+ PyErr_SetString(
+ PyExc_TypeError,
+ "None is not a valid HKEY in this context");
+ return FALSE;
+ }
+ *pHANDLE = (HKEY)0;
+ }
+ else if (PyHKEY_Check(ob)) {
+ PyHKEYObject *pH = (PyHKEYObject *)ob;
+ *pHANDLE = pH->hkey;
+ }
+ else if (_PyAnyInt_Check(ob)) {
+ /* We also support integers */
+ PyErr_Clear();
+ *pHANDLE = (HKEY)PyLong_AsVoidPtr(ob);
+ if (PyErr_Occurred())
+ return FALSE;
+ }
+ else {
+ PyErr_SetString(
+ PyExc_TypeError,
+ "The object is not a PyHKEY object");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+PyObject *
+PyHKEY_FromHKEY(HKEY h)
+{
+ PyHKEYObject *op;
+
+ /* Inline PyObject_New */
+ op = (PyHKEYObject *) PyObject_MALLOC(sizeof(PyHKEYObject));
+ if (op == NULL)
+ return PyErr_NoMemory();
+ PyObject_INIT(op, &PyHKEY_Type);
+ op->hkey = h;
+ return (PyObject *)op;
+}
+
+
+/************************************************************************
+ The module methods
+************************************************************************/
+BOOL
+PyWinObject_CloseHKEY(PyObject *obHandle)
+{
+ BOOL ok;
+ if (PyHKEY_Check(obHandle)) {
+ ok = PyHKEY_Close(obHandle);
+ }
+#if SIZEOF_LONG >= SIZEOF_HKEY
+ else if (PyInt_Check(obHandle)) {
+ long rc = RegCloseKey((HKEY)PyInt_AsLong(obHandle));
+ ok = (rc == ERROR_SUCCESS);
+ if (!ok)
+ PyErr_SetFromWindowsErrWithFunction(rc, "RegCloseKey");
+ }
+#else
+ else if (PyLong_Check(obHandle)) {
+ long rc = RegCloseKey((HKEY)PyLong_AsVoidPtr(obHandle));
+ ok = (rc == ERROR_SUCCESS);
+ if (!ok)
+ PyErr_SetFromWindowsErrWithFunction(rc, "RegCloseKey");
+ }
+#endif
+ else {
+ PyErr_SetString(
+ PyExc_TypeError,
+ "A handle must be a HKEY object or an integer");
+ return FALSE;
+ }
+ return ok;
+}
+
+
+/*
+ Private Helper functions for the registry interfaces
+
+** Note that fixupMultiSZ and countString have both had changes
+** made to support "incorrect strings". The registry specification
+** calls for strings to be terminated with 2 null bytes. It seems
+** some commercial packages install strings which don't conform,
+** causing this code to fail - however, "regedit" etc still work
+** with these strings (ie only we don't!).
+*/
+static void
+fixupMultiSZ(char **str, char *data, int len)
+{
+ char *P;
+ int i;
+ char *Q;
+
+ Q = data + len;
+ for (P = data, i = 0; P < Q && *P != '\0'; P++, i++) {
+ str[i] = P;
+ for(; *P != '\0'; P++)
+ ;
+ }
+}
+
+static int
+countStrings(char *data, int len)
+{
+ int strings;
+ char *P;
+ char *Q = data + len;
+
+ for (P = data, strings = 0; P < Q && *P != '\0'; P++, strings++)
+ for (; P < Q && *P != '\0'; P++)
+ ;
+ return strings;
+}
+
+/* Convert PyObject into Registry data.
+ Allocates space as needed. */
+static BOOL
+Py2Reg(PyObject *value, DWORD typ, BYTE **retDataBuf, DWORD *retDataSize)
+{
+ Py_ssize_t i,j;
+ switch (typ) {
+ case REG_DWORD:
+ if (value != Py_None && !_PyAnyInt_Check(value))
+ return FALSE;
+ *retDataBuf = (BYTE *)PyMem_NEW(DWORD, 1);
+ if (*retDataBuf==NULL){
+ PyErr_NoMemory();
+ return FALSE;
+ }
+ *retDataSize = sizeof(DWORD);
+ if (value == Py_None) {
+ DWORD zero = 0;
+ memcpy(*retDataBuf, &zero, sizeof(DWORD));
+ }
+ else {
+ DWORD d = PyLong_AsUnsignedLong(value);
+ memcpy(*retDataBuf, &d, sizeof(DWORD));
+ }
+ break;
+ case REG_SZ:
+ case REG_EXPAND_SZ:
+ {
+ int need_decref = 0;
+ if (value == Py_None)
+ *retDataSize = 1;
+ else {
+ if (PyUnicode_Check(value)) {
+ value = PyUnicode_AsEncodedString(
+ value,
+ "mbcs",
+ NULL);
+ if (value==NULL)
+ return FALSE;
+ need_decref = 1;
+ }
+ if (!PyString_Check(value))
+ return FALSE;
+ *retDataSize = 1 + strlen(
+ PyString_AS_STRING(
+ (PyStringObject *)value));
+ }
+ *retDataBuf = (BYTE *)PyMem_NEW(DWORD, *retDataSize);
+ if (*retDataBuf==NULL){
+ PyErr_NoMemory();
+ return FALSE;
+ }
+ if (value == Py_None)
+ strcpy((char *)*retDataBuf, "");
+ else
+ strcpy((char *)*retDataBuf,
+ PyString_AS_STRING(
+ (PyStringObject *)value));
+ if (need_decref)
+ Py_DECREF(value);
+ break;
+ }
+ case REG_MULTI_SZ:
+ {
+ DWORD size = 0;
+ char *P;
+ PyObject **obs = NULL;
+
+ if (value == Py_None)
+ i = 0;
+ else {
+ if (!PyList_Check(value))
+ return FALSE;
+ i = PyList_Size(value);
+ }
+ obs = (PyObject**)malloc(sizeof(PyObject *) * i);
+ memset(obs, 0, sizeof(PyObject *) * i);
+ for (j = 0; j < i; j++)
+ {
+ PyObject *t;
+ t = PyList_GET_ITEM(
+ (PyListObject *)value,j);
+ if (PyString_Check(t)) {
+ obs[j] = t;
+ Py_INCREF(t);
+ } else if (PyUnicode_Check(t)) {
+ obs[j] = PyUnicode_AsEncodedString(
+ t,
+ "mbcs",
+ NULL);
+ if (obs[j]==NULL)
+ goto reg_multi_fail;
+ } else
+ goto reg_multi_fail;
+ size += 1 + strlen(
+ PyString_AS_STRING(
+ (PyStringObject *)obs[j]));
+ }
+
+ *retDataSize = size + 1;
+ *retDataBuf = (BYTE *)PyMem_NEW(char,
+ *retDataSize);
+ if (*retDataBuf==NULL){
+ PyErr_NoMemory();
+ goto reg_multi_fail;
+ }
+ P = (char *)*retDataBuf;
+
+ for (j = 0; j < i; j++)
+ {
+ PyObject *t;
+ t = obs[j];
+ strcpy(P,
+ PyString_AS_STRING(
+ (PyStringObject *)t));
+ P += 1 + strlen(
+ PyString_AS_STRING(
+ (PyStringObject *)t));
+ Py_DECREF(obs[j]);
+ }
+ /* And doubly-terminate the list... */
+ *P = '\0';
+ free(obs);
+ break;
+ reg_multi_fail:
+ if (obs) {
+ for (j = 0; j < i; j++)
+ Py_XDECREF(obs[j]);
+
+ free(obs);
+ }
+ return FALSE;
+ }
+ case REG_BINARY:
+ /* ALSO handle ALL unknown data types here. Even if we can't
+ support it natively, we should handle the bits. */
+ default:
+ if (value == Py_None) {
+ *retDataSize = 0;
+ *retDataBuf = NULL;
+ }
+ else {
+ void *src_buf;
+ PyBufferProcs *pb = value->ob_type->tp_as_buffer;
+ if (pb == NULL || pb->bf_getreadbuffer == NULL) {
+ PyErr_Format(PyExc_TypeError,
+ "Objects of type '%s' can not "
+ "be used as binary registry values",
+ value->ob_type->tp_name);
+ return FALSE;
+ }
+ *retDataSize = (*pb->bf_getreadbuffer)(value, 0, &src_buf);
+ if (*retDataSize < 0) {
+ return FALSE;
+ }
+ *retDataBuf = (BYTE *)PyMem_NEW(char, *retDataSize);
+ if (*retDataBuf == NULL){
+ PyErr_NoMemory();
+ return FALSE;
+ }
+ memcpy(*retDataBuf, src_buf, *retDataSize);
+ }
+ break;
+ }
+ return TRUE;
+}
+
+/* Convert Registry data into PyObject*/
+static PyObject *
+Reg2Py(char *retDataBuf, DWORD retDataSize, DWORD typ)
+{
+ PyObject *obData;
+
+ switch (typ) {
+ case REG_DWORD:
+ if (retDataSize == 0)
+ obData = Py_BuildValue("k", 0);
+ else
+ obData = Py_BuildValue("k",
+ *(int *)retDataBuf);
+ break;
+ case REG_SZ:
+ case REG_EXPAND_SZ:
+ /* retDataBuf may or may not have a trailing NULL in
+ the buffer. */
+ if (retDataSize && retDataBuf[retDataSize-1] == '\0')
+ --retDataSize;
+ if (retDataSize ==0)
+ retDataBuf = "";
+ obData = PyUnicode_DecodeMBCS(retDataBuf,
+ retDataSize,
+ NULL);
+ break;
+ case REG_MULTI_SZ:
+ if (retDataSize == 0)
+ obData = PyList_New(0);
+ else
+ {
+ int index = 0;
+ int s = countStrings(retDataBuf, retDataSize);
+ char **str = (char **)malloc(sizeof(char *)*s);
+ if (str == NULL)
+ return PyErr_NoMemory();
+
+ fixupMultiSZ(str, retDataBuf, retDataSize);
+ obData = PyList_New(s);
+ if (obData == NULL) {
+ free(str);
+ return NULL;
+ }
+ for (index = 0; index < s; index++)
+ {
+ size_t len = _mbstrlen(str[index]);
+ if (len > INT_MAX) {
+ PyErr_SetString(PyExc_OverflowError,
+ "registry string is too long for a Python string");
+ Py_DECREF(obData);
+ free(str);
+ return NULL;
+ }
+ PyList_SetItem(obData,
+ index,
+ PyUnicode_DecodeMBCS(
+ (const char *)str[index],
+ (int)len,
+ NULL)
+ );
+ }
+ free(str);
+
+ break;
+ }
+ case REG_BINARY:
+ /* ALSO handle ALL unknown data types here. Even if we can't
+ support it natively, we should handle the bits. */
+ default:
+ if (retDataSize == 0) {
+ Py_INCREF(Py_None);
+ obData = Py_None;
+ }
+ else
+ obData = Py_BuildValue("s#",
+ (char *)retDataBuf,
+ retDataSize);
+ break;
+ }
+ if (obData == NULL)
+ return NULL;
+ else
+ return obData;
+}
+
+/* The Python methods */
+
+static PyObject *
+PyCloseKey(PyObject *self, PyObject *args)
+{
+ PyObject *obKey;
+ if (!PyArg_ParseTuple(args, "O:CloseKey", &obKey))
+ return NULL;
+ if (!PyHKEY_Close(obKey))
+ return NULL;
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+PyConnectRegistry(PyObject *self, PyObject *args)
+{
+ HKEY hKey;
+ PyObject *obKey;
+ char *szCompName = NULL;
+ HKEY retKey;
+ long rc;
+ if (!PyArg_ParseTuple(args, "zO:ConnectRegistry", &szCompName, &obKey))
+ return NULL;
+ if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
+ return NULL;
+ Py_BEGIN_ALLOW_THREADS
+ rc = RegConnectRegistry(szCompName, hKey, &retKey);
+ Py_END_ALLOW_THREADS
+ if (rc != ERROR_SUCCESS)
+ return PyErr_SetFromWindowsErrWithFunction(rc,
+ "ConnectRegistry");
+ return PyHKEY_FromHKEY(retKey);
+}
+
+static PyObject *
+PyCreateKey(PyObject *self, PyObject *args)
+{
+ HKEY hKey;
+ PyObject *obKey;
+ char *subKey;
+ HKEY retKey;
+ long rc;
+ if (!PyArg_ParseTuple(args, "Oz:CreateKey", &obKey, &subKey))
+ return NULL;
+ if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
+ return NULL;
+ rc = RegCreateKey(hKey, subKey, &retKey);
+ if (rc != ERROR_SUCCESS)
+ return PyErr_SetFromWindowsErrWithFunction(rc, "CreateKey");
+ return PyHKEY_FromHKEY(retKey);
+}
+
+static PyObject *
+PyCreateKeyEx(PyObject *self, PyObject *args)
+{
+ HKEY hKey;
+ PyObject *obKey;
+ char *subKey;
+ HKEY retKey;
+ int res = 0;
+ REGSAM sam = KEY_WRITE;
+ long rc;
+ if (!PyArg_ParseTuple(args, "Oz|ii:CreateKeyEx", &obKey, &subKey,
+ &res, &sam))
+ return NULL;
+ if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
+ return NULL;
+
+ rc = RegCreateKeyEx(hKey, subKey, res, NULL, (DWORD)NULL,
+ sam, NULL, &retKey, NULL);
+ if (rc != ERROR_SUCCESS)
+ return PyErr_SetFromWindowsErrWithFunction(rc, "CreateKeyEx");
+ return PyHKEY_FromHKEY(retKey);
+}
+
+static PyObject *
+PyDeleteKey(PyObject *self, PyObject *args)
+{
+ HKEY hKey;
+ PyObject *obKey;
+ char *subKey;
+ long rc;
+ if (!PyArg_ParseTuple(args, "Os:DeleteKey", &obKey, &subKey))
+ return NULL;
+ if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
+ return NULL;
+ rc = RegDeleteKey(hKey, subKey );
+ if (rc != ERROR_SUCCESS)
+ return PyErr_SetFromWindowsErrWithFunction(rc, "RegDeleteKey");
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+PyDeleteKeyEx(PyObject *self, PyObject *args)
+{
+ HKEY hKey;
+ PyObject *obKey;
+ HMODULE hMod;
+ typedef LONG (WINAPI *RDKEFunc)(HKEY, const char*, REGSAM, int);
+ RDKEFunc pfn = NULL;
+ char *subKey;
+ long rc;
+ int res = 0;
+ REGSAM sam = KEY_WOW64_64KEY;
+
+ if (!PyArg_ParseTuple(args, "Os|ii:DeleteKeyEx",
+ &obKey, &subKey, &sam, &res))
+ return NULL;
+ if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
+ return NULL;
+
+ /* Only available on 64bit platforms, so we must load it
+ dynamically. */
+ hMod = GetModuleHandle("advapi32.dll");
+ if (hMod)
+ pfn = (RDKEFunc)GetProcAddress(hMod,
+ "RegDeleteKeyExA");
+ if (!pfn) {
+ PyErr_SetString(PyExc_NotImplementedError,
+ "not implemented on this platform");
+ return NULL;
+ }
+ Py_BEGIN_ALLOW_THREADS
+ rc = (*pfn)(hKey, subKey, sam, res);
+ Py_END_ALLOW_THREADS
+
+ if (rc != ERROR_SUCCESS)
+ return PyErr_SetFromWindowsErrWithFunction(rc, "RegDeleteKeyEx");
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+PyDeleteValue(PyObject *self, PyObject *args)
+{
+ HKEY hKey;
+ PyObject *obKey;
+ char *subKey;
+ long rc;
+ if (!PyArg_ParseTuple(args, "Oz:DeleteValue", &obKey, &subKey))
+ return NULL;
+ if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
+ return NULL;
+ Py_BEGIN_ALLOW_THREADS
+ rc = RegDeleteValue(hKey, subKey);
+ Py_END_ALLOW_THREADS
+ if (rc !=ERROR_SUCCESS)
+ return PyErr_SetFromWindowsErrWithFunction(rc,
+ "RegDeleteValue");
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+PyEnumKey(PyObject *self, PyObject *args)
+{
+ HKEY hKey;
+ PyObject *obKey;
+ int index;
+ long rc;
+ PyObject *retStr;
+
+ /* The Windows docs claim that the max key name length is 255
+ * characters, plus a terminating nul character. However,
+ * empirical testing demonstrates that it is possible to
+ * create a 256 character key that is missing the terminating
+ * nul. RegEnumKeyEx requires a 257 character buffer to
+ * retrieve such a key name. */
+ char tmpbuf[257];
+ DWORD len = sizeof(tmpbuf); /* includes NULL terminator */
+
+ if (!PyArg_ParseTuple(args, "Oi:EnumKey", &obKey, &index))
+ return NULL;
+ if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
+ return NULL;
+
+ Py_BEGIN_ALLOW_THREADS
+ rc = RegEnumKeyEx(hKey, index, tmpbuf, &len, NULL, NULL, NULL, NULL);
+ Py_END_ALLOW_THREADS
+ if (rc != ERROR_SUCCESS)
+ return PyErr_SetFromWindowsErrWithFunction(rc, "RegEnumKeyEx");
+
+ retStr = PyString_FromStringAndSize(tmpbuf, len);
+ return retStr; /* can be NULL */
+}
+
+static PyObject *
+PyEnumValue(PyObject *self, PyObject *args)
+{
+ HKEY hKey;
+ PyObject *obKey;
+ int index;
+ long rc;
+ char *retValueBuf;
+ char *retDataBuf;
+ char *tmpBuf;
+ DWORD retValueSize, bufValueSize;
+ DWORD retDataSize, bufDataSize;
+ DWORD typ;
+ PyObject *obData;
+ PyObject *retVal;
+
+ if (!PyArg_ParseTuple(args, "Oi:EnumValue", &obKey, &index))
+ return NULL;
+ if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
+ return NULL;
+
+ if ((rc = RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL,
+ &retValueSize, &retDataSize, NULL, NULL))
+ != ERROR_SUCCESS)
+ return PyErr_SetFromWindowsErrWithFunction(rc,
+ "RegQueryInfoKey");
+ ++retValueSize; /* include null terminators */
+ ++retDataSize;
+ bufDataSize = retDataSize;
+ bufValueSize = retValueSize;
+ retValueBuf = (char *)PyMem_Malloc(retValueSize);
+ if (retValueBuf == NULL)
+ return PyErr_NoMemory();
+ retDataBuf = (char *)PyMem_Malloc(retDataSize);
+ if (retDataBuf == NULL) {
+ PyMem_Free(retValueBuf);
+ return PyErr_NoMemory();
+ }
+
+ while (1) {
+ Py_BEGIN_ALLOW_THREADS
+ rc = RegEnumValue(hKey,
+ index,
+ retValueBuf,
+ &retValueSize,
+ NULL,
+ &typ,
+ (BYTE *)retDataBuf,
+ &retDataSize);
+ Py_END_ALLOW_THREADS
+
+ if (rc != ERROR_MORE_DATA)
+ break;
+
+ bufDataSize *= 2;
+ tmpBuf = (char *)PyMem_Realloc(retDataBuf, bufDataSize);
+ if (tmpBuf == NULL) {
+ PyErr_NoMemory();
+ retVal = NULL;
+ goto fail;
+ }
+ retDataBuf = tmpBuf;
+ retDataSize = bufDataSize;
+ retValueSize = bufValueSize;
+ }
+
+ if (rc != ERROR_SUCCESS) {
+ retVal = PyErr_SetFromWindowsErrWithFunction(rc,
+ "PyRegEnumValue");
+ goto fail;
+ }
+ obData = Reg2Py(retDataBuf, retDataSize, typ);
+ if (obData == NULL) {
+ retVal = NULL;
+ goto fail;
+ }
+ retVal = Py_BuildValue("sOi", retValueBuf, obData, typ);
+ Py_DECREF(obData);
+ fail:
+ PyMem_Free(retValueBuf);
+ PyMem_Free(retDataBuf);
+ return retVal;
+}
+
+static PyObject *
+PyExpandEnvironmentStrings(PyObject *self, PyObject *args)
+{
+ Py_UNICODE *retValue = NULL;
+ Py_UNICODE *src;
+ DWORD retValueSize;
+ DWORD rc;
+ PyObject *o;
+
+ if (!PyArg_ParseTuple(args, "u:ExpandEnvironmentStrings", &src))
+ return NULL;
+
+ retValueSize = ExpandEnvironmentStringsW(src, retValue, 0);
+ if (retValueSize == 0) {
+ return PyErr_SetFromWindowsErrWithFunction(retValueSize,
+ "ExpandEnvironmentStrings");
+ }
+ retValue = (Py_UNICODE *)PyMem_Malloc(retValueSize * sizeof(Py_UNICODE));
+ if (retValue == NULL) {
+ return PyErr_NoMemory();
+ }
+
+ rc = ExpandEnvironmentStringsW(src, retValue, retValueSize);
+ if (rc == 0) {
+ PyMem_Free(retValue);
+ return PyErr_SetFromWindowsErrWithFunction(retValueSize,
+ "ExpandEnvironmentStrings");
+ }
+ o = PyUnicode_FromUnicode(retValue, wcslen(retValue));
+ PyMem_Free(retValue);
+ return o;
+}
+
+static PyObject *
+PyFlushKey(PyObject *self, PyObject *args)
+{
+ HKEY hKey;
+ PyObject *obKey;
+ long rc;
+ if (!PyArg_ParseTuple(args, "O:FlushKey", &obKey))
+ return NULL;
+ if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
+ return NULL;
+ Py_BEGIN_ALLOW_THREADS
+ rc = RegFlushKey(hKey);
+ Py_END_ALLOW_THREADS
+ if (rc != ERROR_SUCCESS)
+ return PyErr_SetFromWindowsErrWithFunction(rc, "RegFlushKey");
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+static PyObject *
+PyLoadKey(PyObject *self, PyObject *args)
+{
+ HKEY hKey;
+ PyObject *obKey;
+ char *subKey;
+ char *fileName;
+
+ long rc;
+ if (!PyArg_ParseTuple(args, "Oss:LoadKey", &obKey, &subKey, &fileName))
+ return NULL;
+ if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
+ return NULL;
+ Py_BEGIN_ALLOW_THREADS
+ rc = RegLoadKey(hKey, subKey, fileName );
+ Py_END_ALLOW_THREADS
+ if (rc != ERROR_SUCCESS)
+ return PyErr_SetFromWindowsErrWithFunction(rc, "RegLoadKey");
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+PyOpenKey(PyObject *self, PyObject *args)
+{
+ HKEY hKey;
+ PyObject *obKey;
+
+ char *subKey;
+ int res = 0;
+ HKEY retKey;
+ long rc;
+ REGSAM sam = KEY_READ;
+ if (!PyArg_ParseTuple(args, "Oz|ii:OpenKey", &obKey, &subKey,
+ &res, &sam))
+ return NULL;
+ if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
+ return NULL;
+
+ Py_BEGIN_ALLOW_THREADS
+ rc = RegOpenKeyEx(hKey, subKey, res, sam, &retKey);
+ Py_END_ALLOW_THREADS
+ if (rc != ERROR_SUCCESS)
+ return PyErr_SetFromWindowsErrWithFunction(rc, "RegOpenKeyEx");
+ return PyHKEY_FromHKEY(retKey);
+}
+
+
+static PyObject *
+PyQueryInfoKey(PyObject *self, PyObject *args)
+{
+ HKEY hKey;
+ PyObject *obKey;
+ long rc;
+ DWORD nSubKeys, nValues;
+ FILETIME ft;
+ LARGE_INTEGER li;
+ PyObject *l;
+ PyObject *ret;
+ if (!PyArg_ParseTuple(args, "O:QueryInfoKey", &obKey))
+ return NULL;
+ if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
+ return NULL;
+ if ((rc = RegQueryInfoKey(hKey, NULL, NULL, 0, &nSubKeys, NULL, NULL,
+ &nValues, NULL, NULL, NULL, &ft))
+ != ERROR_SUCCESS)
+ return PyErr_SetFromWindowsErrWithFunction(rc, "RegQueryInfoKey");
+ li.LowPart = ft.dwLowDateTime;
+ li.HighPart = ft.dwHighDateTime;
+ l = PyLong_FromLongLong(li.QuadPart);
+ if (l == NULL)
+ return NULL;
+ ret = Py_BuildValue("iiO", nSubKeys, nValues, l);
+ Py_DECREF(l);
+ return ret;
+}
+
+static PyObject *
+PyQueryValue(PyObject *self, PyObject *args)
+{
+ HKEY hKey;
+ PyObject *obKey;
+ char *subKey;
+ long rc;
+ PyObject *retStr;
+ char *retBuf;
+ DWORD bufSize = 0;
+ LONG retSize = 0;
+ char *tmp;
+
+ if (!PyArg_ParseTuple(args, "Oz:QueryValue", &obKey, &subKey))
+ return NULL;
+
+ if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
+ return NULL;
+
+ rc = RegQueryValue(hKey, subKey, NULL, &retSize);
+ if (rc == ERROR_MORE_DATA)
+ retSize = 256;
+ else if (rc != ERROR_SUCCESS)
+ return PyErr_SetFromWindowsErrWithFunction(rc,
+ "RegQueryValue");
+
+ bufSize = retSize;
+ retBuf = (char *) PyMem_Malloc(bufSize);
+ if (retBuf == NULL)
+ return PyErr_NoMemory();
+
+ while (1) {
+ retSize = bufSize;
+ rc = RegQueryValue(hKey, subKey, retBuf, &retSize);
+ if (rc != ERROR_MORE_DATA)
+ break;
+
+ bufSize *= 2;
+ tmp = (char *) PyMem_Realloc(retBuf, bufSize);
+ if (tmp == NULL) {
+ PyMem_Free(retBuf);
+ return PyErr_NoMemory();
+ }
+ retBuf = tmp;
+ }
+
+ if (rc != ERROR_SUCCESS) {
+ PyMem_Free(retBuf);
+ return PyErr_SetFromWindowsErrWithFunction(rc,
+ "RegQueryValue");
+ }
+
+ if (retBuf[retSize-1] == '\x00')
+ retSize--;
+ retStr = PyString_FromStringAndSize(retBuf, retSize);
+ if (retStr == NULL) {
+ PyMem_Free(retBuf);
+ return NULL;
+ }
+ return retStr;
+}
+
+static PyObject *
+PyQueryValueEx(PyObject *self, PyObject *args)
+{
+ HKEY hKey;
+ PyObject *obKey;
+ char *valueName;
+
+ long rc;
+ char *retBuf, *tmp;
+ DWORD bufSize = 0, retSize;
+ DWORD typ;
+ PyObject *obData;
+ PyObject *result;
+
+ if (!PyArg_ParseTuple(args, "Oz:QueryValueEx", &obKey, &valueName))
+ return NULL;
+
+ if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
+ return NULL;
+
+ rc = RegQueryValueEx(hKey, valueName, NULL, NULL, NULL, &bufSize);
+ if (rc == ERROR_MORE_DATA)
+ bufSize = 256;
+ else if (rc != ERROR_SUCCESS)
+ return PyErr_SetFromWindowsErrWithFunction(rc,
+ "RegQueryValueEx");
+ retBuf = (char *)PyMem_Malloc(bufSize);
+ if (retBuf == NULL)
+ return PyErr_NoMemory();
+
+ while (1) {
+ retSize = bufSize;
+ rc = RegQueryValueEx(hKey, valueName, NULL, &typ,
+ (BYTE *)retBuf, &retSize);
+ if (rc != ERROR_MORE_DATA)
+ break;
+
+ bufSize *= 2;
+ tmp = (char *) PyMem_Realloc(retBuf, bufSize);
+ if (tmp == NULL) {
+ PyMem_Free(retBuf);
+ return PyErr_NoMemory();
+ }
+ retBuf = tmp;
+ }
+
+ if (rc != ERROR_SUCCESS) {
+ PyMem_Free(retBuf);
+ return PyErr_SetFromWindowsErrWithFunction(rc,
+ "RegQueryValueEx");
+ }
+ obData = Reg2Py(retBuf, bufSize, typ);
+ PyMem_Free((void *)retBuf);
+ if (obData == NULL)
+ return NULL;
+ result = Py_BuildValue("Oi", obData, typ);
+ Py_DECREF(obData);
+ return result;
+}
+
+
+static PyObject *
+PySaveKey(PyObject *self, PyObject *args)
+{
+ HKEY hKey;
+ PyObject *obKey;
+ char *fileName;
+ LPSECURITY_ATTRIBUTES pSA = NULL;
+
+ long rc;
+ if (!PyArg_ParseTuple(args, "Os:SaveKey", &obKey, &fileName))
+ return NULL;
+ if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
+ return NULL;
+/* One day we may get security into the core?
+ if (!PyWinObject_AsSECURITY_ATTRIBUTES(obSA, &pSA, TRUE))
+ return NULL;
+*/
+ Py_BEGIN_ALLOW_THREADS
+ rc = RegSaveKey(hKey, fileName, pSA );
+ Py_END_ALLOW_THREADS
+ if (rc != ERROR_SUCCESS)
+ return PyErr_SetFromWindowsErrWithFunction(rc, "RegSaveKey");
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+PySetValue(PyObject *self, PyObject *args)
+{
+ HKEY hKey;
+ PyObject *obKey;
+ char *subKey;
+ char *str;
+ DWORD typ;
+ DWORD len;
+ long rc;
+ PyObject *obStrVal;
+ PyObject *obSubKey;
+ if (!PyArg_ParseTuple(args, "OOiO:SetValue",
+ &obKey,
+ &obSubKey,
+ &typ,
+ &obStrVal))
+ return NULL;
+ if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
+ return NULL;
+ if (typ != REG_SZ) {
+ PyErr_SetString(PyExc_TypeError,
+ "Type must be _winreg.REG_SZ");
+ return NULL;
+ }
+ /* XXX - need Unicode support */
+ str = PyString_AsString(obStrVal);
+ if (str == NULL)
+ return NULL;
+ len = PyString_Size(obStrVal);
+ if (obSubKey == Py_None)
+ subKey = NULL;
+ else {
+ subKey = PyString_AsString(obSubKey);
+ if (subKey == NULL)
+ return NULL;
+ }
+ Py_BEGIN_ALLOW_THREADS
+ rc = RegSetValue(hKey, subKey, REG_SZ, str, len+1);
+ Py_END_ALLOW_THREADS
+ if (rc != ERROR_SUCCESS)
+ return PyErr_SetFromWindowsErrWithFunction(rc, "RegSetValue");
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+PySetValueEx(PyObject *self, PyObject *args)
+{
+ HKEY hKey;
+ PyObject *obKey;
+ char *valueName;
+ PyObject *obRes;
+ PyObject *value;
+ BYTE *data;
+ DWORD len;
+ DWORD typ;
+
+ LONG rc;
+
+ if (!PyArg_ParseTuple(args, "OzOiO:SetValueEx",
+ &obKey,
+ &valueName,
+ &obRes,
+ &typ,
+ &value))
+ return NULL;
+ if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
+ return NULL;
+ if (!Py2Reg(value, typ, &data, &len))
+ {
+ if (!PyErr_Occurred())
+ PyErr_SetString(PyExc_ValueError,
+ "Could not convert the data to the specified type.");
+ return NULL;
+ }
+ Py_BEGIN_ALLOW_THREADS
+ rc = RegSetValueEx(hKey, valueName, 0, typ, data, len);
+ Py_END_ALLOW_THREADS
+ PyMem_DEL(data);
+ if (rc != ERROR_SUCCESS)
+ return PyErr_SetFromWindowsErrWithFunction(rc,
+ "RegSetValueEx");
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+PyDisableReflectionKey(PyObject *self, PyObject *args)
+{
+ HKEY hKey;
+ PyObject *obKey;
+ HMODULE hMod;
+ typedef LONG (WINAPI *RDRKFunc)(HKEY);
+ RDRKFunc pfn = NULL;
+ LONG rc;
+
+ if (!PyArg_ParseTuple(args, "O:DisableReflectionKey", &obKey))
+ return NULL;
+ if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
+ return NULL;
+
+ /* Only available on 64bit platforms, so we must load it
+ dynamically. */
+ hMod = GetModuleHandle("advapi32.dll");
+ if (hMod)
+ pfn = (RDRKFunc)GetProcAddress(hMod,
+ "RegDisableReflectionKey");
+ if (!pfn) {
+ PyErr_SetString(PyExc_NotImplementedError,
+ "not implemented on this platform");
+ return NULL;
+ }
+ Py_BEGIN_ALLOW_THREADS
+ rc = (*pfn)(hKey);
+ Py_END_ALLOW_THREADS
+ if (rc != ERROR_SUCCESS)
+ return PyErr_SetFromWindowsErrWithFunction(rc,
+ "RegDisableReflectionKey");
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+PyEnableReflectionKey(PyObject *self, PyObject *args)
+{
+ HKEY hKey;
+ PyObject *obKey;
+ HMODULE hMod;
+ typedef LONG (WINAPI *RERKFunc)(HKEY);
+ RERKFunc pfn = NULL;
+ LONG rc;
+
+ if (!PyArg_ParseTuple(args, "O:EnableReflectionKey", &obKey))
+ return NULL;
+ if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
+ return NULL;
+
+ /* Only available on 64bit platforms, so we must load it
+ dynamically. */
+ hMod = GetModuleHandle("advapi32.dll");
+ if (hMod)
+ pfn = (RERKFunc)GetProcAddress(hMod,
+ "RegEnableReflectionKey");
+ if (!pfn) {
+ PyErr_SetString(PyExc_NotImplementedError,
+ "not implemented on this platform");
+ return NULL;
+ }
+ Py_BEGIN_ALLOW_THREADS
+ rc = (*pfn)(hKey);
+ Py_END_ALLOW_THREADS
+ if (rc != ERROR_SUCCESS)
+ return PyErr_SetFromWindowsErrWithFunction(rc,
+ "RegEnableReflectionKey");
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+PyQueryReflectionKey(PyObject *self, PyObject *args)
+{
+ HKEY hKey;
+ PyObject *obKey;
+ HMODULE hMod;
+ typedef LONG (WINAPI *RQRKFunc)(HKEY, BOOL *);
+ RQRKFunc pfn = NULL;
+ BOOL result;
+ LONG rc;
+
+ if (!PyArg_ParseTuple(args, "O:QueryReflectionKey", &obKey))
+ return NULL;
+ if (!PyHKEY_AsHKEY(obKey, &hKey, FALSE))
+ return NULL;
+
+ /* Only available on 64bit platforms, so we must load it
+ dynamically. */
+ hMod = GetModuleHandle("advapi32.dll");
+ if (hMod)
+ pfn = (RQRKFunc)GetProcAddress(hMod,
+ "RegQueryReflectionKey");
+ if (!pfn) {
+ PyErr_SetString(PyExc_NotImplementedError,
+ "not implemented on this platform");
+ return NULL;
+ }
+ Py_BEGIN_ALLOW_THREADS
+ rc = (*pfn)(hKey, &result);
+ Py_END_ALLOW_THREADS
+ if (rc != ERROR_SUCCESS)
+ return PyErr_SetFromWindowsErrWithFunction(rc,
+ "RegQueryReflectionKey");
+ return PyBool_FromLong(result);
+}
+
+static struct PyMethodDef winreg_methods[] = {
+ {"CloseKey", PyCloseKey, METH_VARARGS, CloseKey_doc},
+ {"ConnectRegistry", PyConnectRegistry, METH_VARARGS, ConnectRegistry_doc},
+ {"CreateKey", PyCreateKey, METH_VARARGS, CreateKey_doc},
+ {"CreateKeyEx", PyCreateKeyEx, METH_VARARGS, CreateKeyEx_doc},
+ {"DeleteKey", PyDeleteKey, METH_VARARGS, DeleteKey_doc},
+ {"DeleteKeyEx", PyDeleteKeyEx, METH_VARARGS, DeleteKeyEx_doc},
+ {"DeleteValue", PyDeleteValue, METH_VARARGS, DeleteValue_doc},
+ {"DisableReflectionKey", PyDisableReflectionKey, METH_VARARGS, DisableReflectionKey_doc},
+ {"EnableReflectionKey", PyEnableReflectionKey, METH_VARARGS, EnableReflectionKey_doc},
+ {"EnumKey", PyEnumKey, METH_VARARGS, EnumKey_doc},
+ {"EnumValue", PyEnumValue, METH_VARARGS, EnumValue_doc},
+ {"ExpandEnvironmentStrings", PyExpandEnvironmentStrings, METH_VARARGS,
+ ExpandEnvironmentStrings_doc },
+ {"FlushKey", PyFlushKey, METH_VARARGS, FlushKey_doc},
+ {"LoadKey", PyLoadKey, METH_VARARGS, LoadKey_doc},
+ {"OpenKey", PyOpenKey, METH_VARARGS, OpenKey_doc},
+ {"OpenKeyEx", PyOpenKey, METH_VARARGS, OpenKeyEx_doc},
+ {"QueryValue", PyQueryValue, METH_VARARGS, QueryValue_doc},
+ {"QueryValueEx", PyQueryValueEx, METH_VARARGS, QueryValueEx_doc},
+ {"QueryInfoKey", PyQueryInfoKey, METH_VARARGS, QueryInfoKey_doc},
+ {"QueryReflectionKey",PyQueryReflectionKey,METH_VARARGS, QueryReflectionKey_doc},
+ {"SaveKey", PySaveKey, METH_VARARGS, SaveKey_doc},
+ {"SetValue", PySetValue, METH_VARARGS, SetValue_doc},
+ {"SetValueEx", PySetValueEx, METH_VARARGS, SetValueEx_doc},
+ NULL,
+};
+
+static void
+insint(PyObject * d, char * name, long value)
+{
+ PyObject *v = PyInt_FromLong(value);
+ if (!v || PyDict_SetItemString(d, name, v))
+ PyErr_Clear();
+ Py_XDECREF(v);
+}
+
+#define ADD_INT(val) insint(d, #val, val)
+
+static void
+inskey(PyObject * d, char * name, HKEY key)
+{
+ PyObject *v = PyLong_FromVoidPtr(key);
+ if (!v || PyDict_SetItemString(d, name, v))
+ PyErr_Clear();
+ Py_XDECREF(v);
+}
+
+#define ADD_KEY(val) inskey(d, #val, val)
+
+PyMODINIT_FUNC init_winreg(void)
+{
+ PyObject *m, *d;
+ m = Py_InitModule3("_winreg", winreg_methods, module_doc);
+ if (m == NULL)
+ return;
+ d = PyModule_GetDict(m);
+ if (PyType_Ready(&PyHKEY_Type) < 0)
+ return;
+ PyHKEY_Type.tp_doc = PyHKEY_doc;
+ Py_INCREF(&PyHKEY_Type);
+ if (PyDict_SetItemString(d, "HKEYType",
+ (PyObject *)&PyHKEY_Type) != 0)
+ return;
+ Py_INCREF(PyExc_WindowsError);
+ if (PyDict_SetItemString(d, "error",
+ PyExc_WindowsError) != 0)
+ return;
+
+ /* Add the relevant constants */
+ ADD_KEY(HKEY_CLASSES_ROOT);
+ ADD_KEY(HKEY_CURRENT_USER);
+ ADD_KEY(HKEY_LOCAL_MACHINE);
+ ADD_KEY(HKEY_USERS);
+ ADD_KEY(HKEY_PERFORMANCE_DATA);
+#ifdef HKEY_CURRENT_CONFIG
+ ADD_KEY(HKEY_CURRENT_CONFIG);
+#endif
+#ifdef HKEY_DYN_DATA
+ ADD_KEY(HKEY_DYN_DATA);
+#endif
+ ADD_INT(KEY_QUERY_VALUE);
+ ADD_INT(KEY_SET_VALUE);
+ ADD_INT(KEY_CREATE_SUB_KEY);
+ ADD_INT(KEY_ENUMERATE_SUB_KEYS);
+ ADD_INT(KEY_NOTIFY);
+ ADD_INT(KEY_CREATE_LINK);
+ ADD_INT(KEY_READ);
+ ADD_INT(KEY_WRITE);
+ ADD_INT(KEY_EXECUTE);
+ ADD_INT(KEY_ALL_ACCESS);
+#ifdef KEY_WOW64_64KEY
+ ADD_INT(KEY_WOW64_64KEY);
+#endif
+#ifdef KEY_WOW64_32KEY
+ ADD_INT(KEY_WOW64_32KEY);
+#endif
+ ADD_INT(REG_OPTION_RESERVED);
+ ADD_INT(REG_OPTION_NON_VOLATILE);
+ ADD_INT(REG_OPTION_VOLATILE);
+ ADD_INT(REG_OPTION_CREATE_LINK);
+ ADD_INT(REG_OPTION_BACKUP_RESTORE);
+ ADD_INT(REG_OPTION_OPEN_LINK);
+ ADD_INT(REG_LEGAL_OPTION);
+ ADD_INT(REG_CREATED_NEW_KEY);
+ ADD_INT(REG_OPENED_EXISTING_KEY);
+ ADD_INT(REG_WHOLE_HIVE_VOLATILE);
+ ADD_INT(REG_REFRESH_HIVE);
+ ADD_INT(REG_NO_LAZY_FLUSH);
+ ADD_INT(REG_NOTIFY_CHANGE_NAME);
+ ADD_INT(REG_NOTIFY_CHANGE_ATTRIBUTES);
+ ADD_INT(REG_NOTIFY_CHANGE_LAST_SET);
+ ADD_INT(REG_NOTIFY_CHANGE_SECURITY);
+ ADD_INT(REG_LEGAL_CHANGE_FILTER);
+ ADD_INT(REG_NONE);
+ ADD_INT(REG_SZ);
+ ADD_INT(REG_EXPAND_SZ);
+ ADD_INT(REG_BINARY);
+ ADD_INT(REG_DWORD);
+ ADD_INT(REG_DWORD_LITTLE_ENDIAN);
+ ADD_INT(REG_DWORD_BIG_ENDIAN);
+ ADD_INT(REG_LINK);
+ ADD_INT(REG_MULTI_SZ);
+ ADD_INT(REG_RESOURCE_LIST);
+ ADD_INT(REG_FULL_RESOURCE_DESCRIPTOR);
+ ADD_INT(REG_RESOURCE_REQUIREMENTS_LIST);
+}
+
diff --git a/contrib/tools/python/src/PC/dl_nt.c b/contrib/tools/python/src/PC/dl_nt.c
new file mode 100644
index 00000000000..ef1ce0934c1
--- /dev/null
+++ b/contrib/tools/python/src/PC/dl_nt.c
@@ -0,0 +1,106 @@
+/*
+
+Entry point for the Windows NT DLL.
+
+About the only reason for having this, is so initall() can automatically
+be called, removing that burden (and possible source of frustration if
+forgotten) from the programmer.
+
+*/
+
+#include "Python.h"
+#include "windows.h"
+
+#ifdef Py_ENABLE_SHARED
+char dllVersionBuffer[16] = ""; // a private buffer
+
+// Python Globals
+HMODULE PyWin_DLLhModule = NULL;
+const char *PyWin_DLLVersionString = dllVersionBuffer;
+
+// Windows "Activation Context" work:
+// Our .pyd extension modules are generally built without a manifest (ie,
+// those included with Python and those built with a default distutils.
+// This requires we perform some "activation context" magic when loading our
+// extensions. In summary:
+// * As our DLL loads we save the context being used.
+// * Before loading our extensions we re-activate our saved context.
+// * After extension load is complete we restore the old context.
+// As an added complication, this magic only works on XP or later - we simply
+// use the existence (or not) of the relevant function pointers from kernel32.
+// See bug 4566 (http://python.org/sf/4566) for more details.
+
+typedef BOOL (WINAPI * PFN_GETCURRENTACTCTX)(HANDLE *);
+typedef BOOL (WINAPI * PFN_ACTIVATEACTCTX)(HANDLE, ULONG_PTR *);
+typedef BOOL (WINAPI * PFN_DEACTIVATEACTCTX)(DWORD, ULONG_PTR);
+typedef BOOL (WINAPI * PFN_ADDREFACTCTX)(HANDLE);
+typedef BOOL (WINAPI * PFN_RELEASEACTCTX)(HANDLE);
+
+// locals and function pointers for this activation context magic.
+static HANDLE PyWin_DLLhActivationContext = NULL; // one day it might be public
+static PFN_GETCURRENTACTCTX pfnGetCurrentActCtx = NULL;
+static PFN_ACTIVATEACTCTX pfnActivateActCtx = NULL;
+static PFN_DEACTIVATEACTCTX pfnDeactivateActCtx = NULL;
+static PFN_ADDREFACTCTX pfnAddRefActCtx = NULL;
+static PFN_RELEASEACTCTX pfnReleaseActCtx = NULL;
+
+void _LoadActCtxPointers()
+{
+ HINSTANCE hKernel32 = GetModuleHandleW(L"kernel32.dll");
+ if (hKernel32)
+ pfnGetCurrentActCtx = (PFN_GETCURRENTACTCTX) GetProcAddress(hKernel32, "GetCurrentActCtx");
+ // If we can't load GetCurrentActCtx (ie, pre XP) , don't bother with the rest.
+ if (pfnGetCurrentActCtx) {
+ pfnActivateActCtx = (PFN_ACTIVATEACTCTX) GetProcAddress(hKernel32, "ActivateActCtx");
+ pfnDeactivateActCtx = (PFN_DEACTIVATEACTCTX) GetProcAddress(hKernel32, "DeactivateActCtx");
+ pfnAddRefActCtx = (PFN_ADDREFACTCTX) GetProcAddress(hKernel32, "AddRefActCtx");
+ pfnReleaseActCtx = (PFN_RELEASEACTCTX) GetProcAddress(hKernel32, "ReleaseActCtx");
+ }
+}
+
+ULONG_PTR _Py_ActivateActCtx()
+{
+ ULONG_PTR ret = 0;
+ if (PyWin_DLLhActivationContext && pfnActivateActCtx)
+ if (!(*pfnActivateActCtx)(PyWin_DLLhActivationContext, &ret)) {
+ OutputDebugString("Python failed to activate the activation context before loading a DLL\n");
+ ret = 0; // no promise the failing function didn't change it!
+ }
+ return ret;
+}
+
+void _Py_DeactivateActCtx(ULONG_PTR cookie)
+{
+ if (cookie && pfnDeactivateActCtx)
+ if (!(*pfnDeactivateActCtx)(0, cookie))
+ OutputDebugString("Python failed to de-activate the activation context\n");
+}
+
+BOOL WINAPI DllMain (HANDLE hInst,
+ ULONG ul_reason_for_call,
+ LPVOID lpReserved)
+{
+ switch (ul_reason_for_call)
+ {
+ case DLL_PROCESS_ATTACH:
+ PyWin_DLLhModule = hInst;
+ // 1000 is a magic number I picked out of the air. Could do with a #define, I spose...
+ LoadString(hInst, 1000, dllVersionBuffer, sizeof(dllVersionBuffer));
+
+ // and capture our activation context for use when loading extensions.
+ _LoadActCtxPointers();
+ if (pfnGetCurrentActCtx && pfnAddRefActCtx)
+ if ((*pfnGetCurrentActCtx)(&PyWin_DLLhActivationContext))
+ if (!(*pfnAddRefActCtx)(PyWin_DLLhActivationContext))
+ OutputDebugString("Python failed to load the default activation context\n");
+ break;
+
+ case DLL_PROCESS_DETACH:
+ if (pfnReleaseActCtx)
+ (*pfnReleaseActCtx)(PyWin_DLLhActivationContext);
+ break;
+ }
+ return TRUE;
+}
+
+#endif /* Py_ENABLE_SHARED */
diff --git a/contrib/tools/python/src/PC/errmap.h b/contrib/tools/python/src/PC/errmap.h
new file mode 100644
index 00000000000..d225aa4311f
--- /dev/null
+++ b/contrib/tools/python/src/PC/errmap.h
@@ -0,0 +1,78 @@
+/* Generated file. Do not edit. */
+int winerror_to_errno(int winerror)
+{
+ switch(winerror) {
+ case 2: return 2;
+ case 3: return 2;
+ case 4: return 24;
+ case 5: return 13;
+ case 6: return 9;
+ case 7: return 12;
+ case 8: return 12;
+ case 9: return 12;
+ case 10: return 7;
+ case 11: return 8;
+ case 15: return 2;
+ case 16: return 13;
+ case 17: return 18;
+ case 18: return 2;
+ case 19: return 13;
+ case 20: return 13;
+ case 21: return 13;
+ case 22: return 13;
+ case 23: return 13;
+ case 24: return 13;
+ case 25: return 13;
+ case 26: return 13;
+ case 27: return 13;
+ case 28: return 13;
+ case 29: return 13;
+ case 30: return 13;
+ case 31: return 13;
+ case 32: return 13;
+ case 33: return 13;
+ case 34: return 13;
+ case 35: return 13;
+ case 36: return 13;
+ case 53: return 2;
+ case 65: return 13;
+ case 67: return 2;
+ case 80: return 17;
+ case 82: return 13;
+ case 83: return 13;
+ case 89: return 11;
+ case 108: return 13;
+ case 109: return 32;
+ case 112: return 28;
+ case 114: return 9;
+ case 128: return 10;
+ case 129: return 10;
+ case 130: return 9;
+ case 132: return 13;
+ case 145: return 41;
+ case 158: return 13;
+ case 161: return 2;
+ case 164: return 11;
+ case 167: return 13;
+ case 183: return 17;
+ case 188: return 8;
+ case 189: return 8;
+ case 190: return 8;
+ case 191: return 8;
+ case 192: return 8;
+ case 193: return 8;
+ case 194: return 8;
+ case 195: return 8;
+ case 196: return 8;
+ case 197: return 8;
+ case 198: return 8;
+ case 199: return 8;
+ case 200: return 8;
+ case 201: return 8;
+ case 202: return 8;
+ case 206: return 2;
+ case 215: return 11;
+ case 1816: return 12;
+ default: return EINVAL;
+ }
+}
diff --git a/contrib/tools/python/src/PC/getpathp.c b/contrib/tools/python/src/PC/getpathp.c
new file mode 100644
index 00000000000..a159ecff295
--- /dev/null
+++ b/contrib/tools/python/src/PC/getpathp.c
@@ -0,0 +1,715 @@
+
+/* Return the initial module search path. */
+/* Used by DOS, OS/2, Windows 3.1, Windows 95/98, Windows NT. */
+
+/* ----------------------------------------------------------------
+ PATH RULES FOR WINDOWS:
+ This describes how sys.path is formed on Windows. It describes the
+ functionality, not the implementation (ie, the order in which these
+ are actually fetched is different)
+
+ * Python always adds an empty entry at the start, which corresponds
+ to the current directory.
+
+ * If the PYTHONPATH env. var. exists, its entries are added next.
+
+ * We look in the registry for "application paths" - that is, sub-keys
+ under the main PythonPath registry key. These are added next (the
+ order of sub-key processing is undefined).
+ HKEY_CURRENT_USER is searched and added first.
+ HKEY_LOCAL_MACHINE is searched and added next.
+ (Note that all known installers only use HKLM, so HKCU is typically
+ empty)
+
+ * We attempt to locate the "Python Home" - if the PYTHONHOME env var
+ is set, we believe it. Otherwise, we use the path of our host .EXE's
+ to try and locate our "landmark" (lib\\os.py) and deduce our home.
+ - If we DO have a Python Home: The relevant sub-directories (Lib,
+ plat-win, lib-tk, etc) are based on the Python Home
+ - If we DO NOT have a Python Home, the core Python Path is
+ loaded from the registry. This is the main PythonPath key,
+ and both HKLM and HKCU are combined to form the path)
+
+ * Iff - we can not locate the Python Home, have not had a PYTHONPATH
+ specified, and can't locate any Registry entries (ie, we have _nothing_
+ we can assume is a good path), a default path with relative entries is
+ used (eg. .\Lib;.\plat-win, etc)
+
+
+ The end result of all this is:
+ * When running python.exe, or any other .exe in the main Python directory
+ (either an installed version, or directly from the PCbuild directory),
+ the core path is deduced, and the core paths in the registry are
+ ignored. Other "application paths" in the registry are always read.
+
+ * When Python is hosted in another exe (different directory, embedded via
+ COM, etc), the Python Home will not be deduced, so the core path from
+ the registry is used. Other "application paths" in the registry are
+ always read.
+
+ * If Python can't find its home and there is no registry (eg, frozen
+ exe, some very strange installation setup) you get a path with
+ some default, but relative, paths.
+
+ ---------------------------------------------------------------- */
+
+
+#include "Python.h"
+#include "osdefs.h"
+
+#ifdef MS_WINDOWS
+#include <windows.h>
+#include <tchar.h>
+#include <minmax.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif /* HAVE_SYS_TYPES_H */
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif /* HAVE_SYS_STAT_H */
+
+#include <string.h>
+
+/* Search in some common locations for the associated Python libraries.
+ *
+ * Py_GetPath() tries to return a sensible Python module search path.
+ *
+ * The approach is an adaptation for Windows of the strategy used in
+ * ../Modules/getpath.c; it uses the Windows Registry as one of its
+ * information sources.
+ */
+
+#ifndef LANDMARK
+#define LANDMARK "lib\\os.py"
+#endif
+
+static char prefix[MAXPATHLEN+1];
+static char progpath[MAXPATHLEN+1];
+static char dllpath[MAXPATHLEN+1];
+static char *module_search_path = NULL;
+
+
+static int
+is_sep(char ch) /* determine if "ch" is a separator character */
+{
+#ifdef ALTSEP
+ return ch == SEP || ch == ALTSEP;
+#else
+ return ch == SEP;
+#endif
+}
+
+/* assumes 'dir' null terminated in bounds. Never writes
+ beyond existing terminator.
+*/
+static void
+reduce(char *dir)
+{
+ size_t i = strlen(dir);
+ while (i > 0 && !is_sep(dir[i]))
+ --i;
+ dir[i] = '\0';
+}
+
+
+static int
+exists(char *filename)
+{
+ struct stat buf;
+ return stat(filename, &buf) == 0;
+}
+
+/* Assumes 'filename' MAXPATHLEN+1 bytes long -
+ may extend 'filename' by one character.
+*/
+static int
+ismodule(char *filename) /* Is module -- check for .pyc/.pyo too */
+{
+ if (exists(filename))
+ return 1;
+
+ /* Check for the compiled version of prefix. */
+ if (strlen(filename) < MAXPATHLEN) {
+ strcat(filename, Py_OptimizeFlag ? "o" : "c");
+ if (exists(filename))
+ return 1;
+ }
+ return 0;
+}
+
+/* Add a path component, by appending stuff to buffer.
+ buffer must have at least MAXPATHLEN + 1 bytes allocated, and contain a
+ NUL-terminated string with no more than MAXPATHLEN characters (not counting
+ the trailing NUL). It's a fatal error if it contains a string longer than
+ that (callers must be careful!). If these requirements are met, it's
+ guaranteed that buffer will still be a NUL-terminated string with no more
+ than MAXPATHLEN characters at exit. If stuff is too long, only as much of
+ stuff as fits will be appended.
+*/
+static void
+join(char *buffer, char *stuff)
+{
+ size_t n, k;
+ if (is_sep(stuff[0]))
+ n = 0;
+ else {
+ n = strlen(buffer);
+ if (n > 0 && !is_sep(buffer[n-1]) && n < MAXPATHLEN)
+ buffer[n++] = SEP;
+ }
+ if (n > MAXPATHLEN)
+ Py_FatalError("buffer overflow in getpathp.c's joinpath()");
+ k = strlen(stuff);
+ if (n + k > MAXPATHLEN)
+ k = MAXPATHLEN - n;
+ strncpy(buffer+n, stuff, k);
+ buffer[n+k] = '\0';
+}
+
+/* gotlandmark only called by search_for_prefix, which ensures
+ 'prefix' is null terminated in bounds. join() ensures
+ 'landmark' can not overflow prefix if too long.
+*/
+static int
+gotlandmark(char *landmark)
+{
+ int ok;
+ Py_ssize_t n;
+
+ n = strlen(prefix);
+ join(prefix, landmark);
+ ok = ismodule(prefix);
+ prefix[n] = '\0';
+ return ok;
+}
+
+/* assumes argv0_path is MAXPATHLEN+1 bytes long, already \0 term'd.
+ assumption provided by only caller, calculate_path() */
+static int
+search_for_prefix(char *argv0_path, char *landmark)
+{
+ /* Search from argv0_path, until landmark is found */
+ strcpy(prefix, argv0_path);
+ do {
+ if (gotlandmark(landmark))
+ return 1;
+ reduce(prefix);
+ } while (prefix[0]);
+ return 0;
+}
+
+#ifdef MS_WINDOWS
+#ifdef Py_ENABLE_SHARED
+
+/* a string loaded from the DLL at startup.*/
+extern const char *PyWin_DLLVersionString;
+
+
+/* Load a PYTHONPATH value from the registry.
+ Load from either HKEY_LOCAL_MACHINE or HKEY_CURRENT_USER.
+
+ Works in both Unicode and 8bit environments. Only uses the
+ Ex family of functions so it also works with Windows CE.
+
+ Returns NULL, or a pointer that should be freed.
+
+ XXX - this code is pretty strange, as it used to also
+ work on Win16, where the buffer sizes werent available
+ in advance. It could be simplied now Win16/Win32s is dead!
+*/
+
+static char *
+getpythonregpath(HKEY keyBase, int skipcore)
+{
+ HKEY newKey = 0;
+ DWORD dataSize = 0;
+ DWORD numKeys = 0;
+ LONG rc;
+ char *retval = NULL;
+ TCHAR *dataBuf = NULL;
+ static const TCHAR keyPrefix[] = _T("Software\\Python\\PythonCore\\");
+ static const TCHAR keySuffix[] = _T("\\PythonPath");
+ size_t versionLen;
+ DWORD index;
+ TCHAR *keyBuf = NULL;
+ TCHAR *keyBufPtr;
+ TCHAR **ppPaths = NULL;
+
+ /* Tried to use sysget("winver") but here is too early :-( */
+ versionLen = _tcslen(PyWin_DLLVersionString);
+ /* Space for all the chars, plus one \0 */
+ keyBuf = keyBufPtr = malloc(sizeof(keyPrefix) +
+ sizeof(TCHAR)*(versionLen-1) +
+ sizeof(keySuffix));
+ if (keyBuf==NULL) goto done;
+
+ memcpy(keyBufPtr, keyPrefix, sizeof(keyPrefix)-sizeof(TCHAR));
+ keyBufPtr += sizeof(keyPrefix)/sizeof(TCHAR) - 1;
+ memcpy(keyBufPtr, PyWin_DLLVersionString, versionLen * sizeof(TCHAR));
+ keyBufPtr += versionLen;
+ /* NULL comes with this one! */
+ memcpy(keyBufPtr, keySuffix, sizeof(keySuffix));
+ /* Open the root Python key */
+ rc=RegOpenKeyEx(keyBase,
+ keyBuf, /* subkey */
+ 0, /* reserved */
+ KEY_READ,
+ &newKey);
+ if (rc!=ERROR_SUCCESS) goto done;
+ /* Find out how big our core buffer is, and how many subkeys we have */
+ rc = RegQueryInfoKey(newKey, NULL, NULL, NULL, &numKeys, NULL, NULL,
+ NULL, NULL, &dataSize, NULL, NULL);
+ if (rc!=ERROR_SUCCESS) goto done;
+ if (skipcore) dataSize = 0; /* Only count core ones if we want them! */
+ /* Allocate a temp array of char buffers, so we only need to loop
+ reading the registry once
+ */
+ ppPaths = malloc( sizeof(TCHAR *) * numKeys );
+ if (ppPaths==NULL) goto done;
+ memset(ppPaths, 0, sizeof(TCHAR *) * numKeys);
+ /* Loop over all subkeys, allocating a temp sub-buffer. */
+ for(index=0;index<numKeys;index++) {
+ TCHAR keyBuf[MAX_PATH+1];
+ HKEY subKey = 0;
+ DWORD reqdSize = MAX_PATH+1;
+ /* Get the sub-key name */
+ DWORD rc = RegEnumKeyEx(newKey, index, keyBuf, &reqdSize,
+ NULL, NULL, NULL, NULL );
+ if (rc!=ERROR_SUCCESS) goto done;
+ /* Open the sub-key */
+ rc=RegOpenKeyEx(newKey,
+ keyBuf, /* subkey */
+ 0, /* reserved */
+ KEY_READ,
+ &subKey);
+ if (rc!=ERROR_SUCCESS) goto done;
+ /* Find the value of the buffer size, malloc, then read it */
+ RegQueryValueEx(subKey, NULL, 0, NULL, NULL, &reqdSize);
+ if (reqdSize) {
+ ppPaths[index] = malloc(reqdSize);
+ if (ppPaths[index]) {
+ RegQueryValueEx(subKey, NULL, 0, NULL,
+ (LPBYTE)ppPaths[index],
+ &reqdSize);
+ dataSize += reqdSize + 1; /* 1 for the ";" */
+ }
+ }
+ RegCloseKey(subKey);
+ }
+
+ /* return null if no path to return */
+ if (dataSize == 0) goto done;
+
+ /* original datasize from RegQueryInfo doesn't include the \0 */
+ dataBuf = malloc((dataSize+1) * sizeof(TCHAR));
+ if (dataBuf) {
+ TCHAR *szCur = dataBuf;
+ DWORD reqdSize = dataSize;
+ /* Copy our collected strings */
+ for (index=0;index<numKeys;index++) {
+ if (index > 0) {
+ *(szCur++) = _T(';');
+ dataSize--;
+ }
+ if (ppPaths[index]) {
+ Py_ssize_t len = _tcslen(ppPaths[index]);
+ _tcsncpy(szCur, ppPaths[index], len);
+ szCur += len;
+ assert(dataSize > (DWORD)len);
+ dataSize -= (DWORD)len;
+ }
+ }
+ if (skipcore)
+ *szCur = '\0';
+ else {
+ /* If we have no values, we dont need a ';' */
+ if (numKeys) {
+ *(szCur++) = _T(';');
+ dataSize--;
+ }
+ /* Now append the core path entries -
+ this will include the NULL
+ */
+ rc = RegQueryValueEx(newKey, NULL, 0, NULL,
+ (LPBYTE)szCur, &dataSize);
+ }
+ /* And set the result - caller must free
+ If MBCS, it is fine as is. If Unicode, allocate new
+ buffer and convert.
+ */
+#ifdef UNICODE
+ retval = (char *)malloc(reqdSize+1);
+ if (retval)
+ WideCharToMultiByte(CP_ACP, 0,
+ dataBuf, -1, /* source */
+ retval, reqdSize+1, /* dest */
+ NULL, NULL);
+ free(dataBuf);
+#else
+ retval = dataBuf;
+#endif
+ }
+done:
+ /* Loop freeing my temp buffers */
+ if (ppPaths) {
+ for(index=0;index<numKeys;index++)
+ if (ppPaths[index]) free(ppPaths[index]);
+ free(ppPaths);
+ }
+ if (newKey)
+ RegCloseKey(newKey);
+ if (keyBuf)
+ free(keyBuf);
+ return retval;
+}
+#endif /* Py_ENABLE_SHARED */
+#endif /* MS_WINDOWS */
+
+static void
+get_progpath(void)
+{
+ extern char *Py_GetProgramName(void);
+ char *path = getenv("PATH");
+ char *prog = Py_GetProgramName();
+
+#ifdef MS_WINDOWS
+ extern HANDLE PyWin_DLLhModule;
+#ifdef UNICODE
+ WCHAR wprogpath[MAXPATHLEN+1];
+ /* Windows documents that GetModuleFileName() will "truncate",
+ but makes no mention of the null terminator. Play it safe.
+ PLUS Windows itself defines MAX_PATH as the same, but anyway...
+ */
+#ifdef Py_ENABLE_SHARED
+ wprogpath[MAXPATHLEN]=_T('\0');
+ if (PyWin_DLLhModule &&
+ GetModuleFileName(PyWin_DLLhModule, wprogpath, MAXPATHLEN)) {
+ WideCharToMultiByte(CP_ACP, 0,
+ wprogpath, -1,
+ dllpath, MAXPATHLEN+1,
+ NULL, NULL);
+ }
+#else
+ dllpath[0] = 0;
+#endif
+ wprogpath[MAXPATHLEN]=_T('\0');
+ if (GetModuleFileName(NULL, wprogpath, MAXPATHLEN)) {
+ WideCharToMultiByte(CP_ACP, 0,
+ wprogpath, -1,
+ progpath, MAXPATHLEN+1,
+ NULL, NULL);
+ return;
+ }
+#else
+ /* static init of progpath ensures final char remains \0 */
+#ifdef Py_ENABLE_SHARED
+ if (PyWin_DLLhModule)
+ if (!GetModuleFileName(PyWin_DLLhModule, dllpath, MAXPATHLEN))
+ dllpath[0] = 0;
+#else
+ dllpath[0] = 0;
+#endif
+ if (GetModuleFileName(NULL, progpath, MAXPATHLEN))
+ return;
+#endif
+#endif
+ if (prog == NULL || *prog == '\0')
+ prog = "python";
+
+ /* If there is no slash in the argv0 path, then we have to
+ * assume python is on the user's $PATH, since there's no
+ * other way to find a directory to start the search from. If
+ * $PATH isn't exported, you lose.
+ */
+#ifdef ALTSEP
+ if (strchr(prog, SEP) || strchr(prog, ALTSEP))
+#else
+ if (strchr(prog, SEP))
+#endif
+ strncpy(progpath, prog, MAXPATHLEN);
+ else if (path) {
+ while (1) {
+ char *delim = strchr(path, DELIM);
+
+ if (delim) {
+ size_t len = delim - path;
+ /* ensure we can't overwrite buffer */
+ len = min(MAXPATHLEN,len);
+ strncpy(progpath, path, len);
+ *(progpath + len) = '\0';
+ }
+ else
+ strncpy(progpath, path, MAXPATHLEN);
+
+ /* join() is safe for MAXPATHLEN+1 size buffer */
+ join(progpath, prog);
+ if (exists(progpath))
+ break;
+
+ if (!delim) {
+ progpath[0] = '\0';
+ break;
+ }
+ path = delim + 1;
+ }
+ }
+ else
+ progpath[0] = '\0';
+}
+
+static void
+calculate_path(void)
+{
+ char argv0_path[MAXPATHLEN+1];
+ char *buf;
+ size_t bufsz;
+ char *pythonhome = Py_GetPythonHome();
+ char *envpath = Py_GETENV("PYTHONPATH");
+
+#ifdef MS_WINDOWS
+ int skiphome, skipdefault;
+ char *machinepath = NULL;
+ char *userpath = NULL;
+ char zip_path[MAXPATHLEN+1];
+ size_t len;
+#endif
+
+ get_progpath();
+ /* progpath guaranteed \0 terminated in MAXPATH+1 bytes. */
+ strcpy(argv0_path, progpath);
+ reduce(argv0_path);
+ if (pythonhome == NULL || *pythonhome == '\0') {
+ if (search_for_prefix(argv0_path, LANDMARK))
+ pythonhome = prefix;
+ else
+ pythonhome = NULL;
+ }
+ else
+ strncpy(prefix, pythonhome, MAXPATHLEN);
+
+ if (envpath && *envpath == '\0')
+ envpath = NULL;
+
+
+#ifdef MS_WINDOWS
+ /* Calculate zip archive path */
+ if (dllpath[0]) /* use name of python DLL */
+ strncpy(zip_path, dllpath, MAXPATHLEN);
+ else /* use name of executable program */
+ strncpy(zip_path, progpath, MAXPATHLEN);
+ zip_path[MAXPATHLEN] = '\0';
+ len = strlen(zip_path);
+ if (len > 4) {
+ zip_path[len-3] = 'z'; /* change ending to "zip" */
+ zip_path[len-2] = 'i';
+ zip_path[len-1] = 'p';
+ }
+ else {
+ zip_path[0] = 0;
+ }
+
+ skiphome = pythonhome==NULL ? 0 : 1;
+#ifdef Py_ENABLE_SHARED
+ machinepath = getpythonregpath(HKEY_LOCAL_MACHINE, skiphome);
+ userpath = getpythonregpath(HKEY_CURRENT_USER, skiphome);
+#endif
+ /* We only use the default relative PYTHONPATH if we havent
+ anything better to use! */
+ skipdefault = envpath!=NULL || pythonhome!=NULL || \
+ machinepath!=NULL || userpath!=NULL;
+#endif
+
+ /* We need to construct a path from the following parts.
+ (1) the PYTHONPATH environment variable, if set;
+ (2) for Win32, the zip archive file path;
+ (3) for Win32, the machinepath and userpath, if set;
+ (4) the PYTHONPATH config macro, with the leading "."
+ of each component replaced with pythonhome, if set;
+ (5) the directory containing the executable (argv0_path).
+ The length calculation calculates #4 first.
+ Extra rules:
+ - If PYTHONHOME is set (in any way) item (3) is ignored.
+ - If registry values are used, (4) and (5) are ignored.
+ */
+
+ /* Calculate size of return buffer */
+ if (pythonhome != NULL) {
+ char *p;
+ bufsz = 1;
+ for (p = PYTHONPATH; *p; p++) {
+ if (*p == DELIM)
+ bufsz++; /* number of DELIM plus one */
+ }
+ bufsz *= strlen(pythonhome);
+ }
+ else
+ bufsz = 0;
+ bufsz += strlen(PYTHONPATH) + 1;
+ bufsz += strlen(argv0_path) + 1;
+#ifdef MS_WINDOWS
+ if (userpath)
+ bufsz += strlen(userpath) + 1;
+ if (machinepath)
+ bufsz += strlen(machinepath) + 1;
+ bufsz += strlen(zip_path) + 1;
+#endif
+ if (envpath != NULL)
+ bufsz += strlen(envpath) + 1;
+
+ module_search_path = buf = (char*)malloc(bufsz);
+ if (buf == NULL) {
+ /* We can't exit, so print a warning and limp along */
+ fprintf(stderr, "Can't malloc dynamic PYTHONPATH.\n");
+ if (envpath) {
+ fprintf(stderr, "Using environment $PYTHONPATH.\n");
+ module_search_path = envpath;
+ }
+ else {
+ fprintf(stderr, "Using default static path.\n");
+ module_search_path = PYTHONPATH;
+ }
+#ifdef MS_WINDOWS
+ if (machinepath)
+ free(machinepath);
+ if (userpath)
+ free(userpath);
+#endif /* MS_WINDOWS */
+ return;
+ }
+
+ if (envpath) {
+ strcpy(buf, envpath);
+ buf = strchr(buf, '\0');
+ *buf++ = DELIM;
+ }
+#ifdef MS_WINDOWS
+ if (zip_path[0]) {
+ strcpy(buf, zip_path);
+ buf = strchr(buf, '\0');
+ *buf++ = DELIM;
+ }
+ if (userpath) {
+ strcpy(buf, userpath);
+ buf = strchr(buf, '\0');
+ *buf++ = DELIM;
+ free(userpath);
+ }
+ if (machinepath) {
+ strcpy(buf, machinepath);
+ buf = strchr(buf, '\0');
+ *buf++ = DELIM;
+ free(machinepath);
+ }
+ if (pythonhome == NULL) {
+ if (!skipdefault) {
+ strcpy(buf, PYTHONPATH);
+ buf = strchr(buf, '\0');
+ }
+ }
+#else
+ if (pythonhome == NULL) {
+ strcpy(buf, PYTHONPATH);
+ buf = strchr(buf, '\0');
+ }
+#endif /* MS_WINDOWS */
+ else {
+ char *p = PYTHONPATH;
+ char *q;
+ size_t n;
+ for (;;) {
+ q = strchr(p, DELIM);
+ if (q == NULL)
+ n = strlen(p);
+ else
+ n = q-p;
+ if (p[0] == '.' && is_sep(p[1])) {
+ strcpy(buf, pythonhome);
+ buf = strchr(buf, '\0');
+ p++;
+ n--;
+ }
+ strncpy(buf, p, n);
+ buf += n;
+ if (q == NULL)
+ break;
+ *buf++ = DELIM;
+ p = q+1;
+ }
+ }
+ if (argv0_path) {
+ *buf++ = DELIM;
+ strcpy(buf, argv0_path);
+ buf = strchr(buf, '\0');
+ }
+ *buf = '\0';
+ /* Now to pull one last hack/trick. If sys.prefix is
+ empty, then try and find it somewhere on the paths
+ we calculated. We scan backwards, as our general policy
+ is that Python core directories are at the *end* of
+ sys.path. We assume that our "lib" directory is
+ on the path, and that our 'prefix' directory is
+ the parent of that.
+ */
+ if (*prefix=='\0') {
+ char lookBuf[MAXPATHLEN+1];
+ char *look = buf - 1; /* 'buf' is at the end of the buffer */
+ while (1) {
+ Py_ssize_t nchars;
+ char *lookEnd = look;
+ /* 'look' will end up one character before the
+ start of the path in question - even if this
+ is one character before the start of the buffer
+ */
+ while (look >= module_search_path && *look != DELIM)
+ look--;
+ nchars = lookEnd-look;
+ strncpy(lookBuf, look+1, nchars);
+ lookBuf[nchars] = '\0';
+ /* Up one level to the parent */
+ reduce(lookBuf);
+ if (search_for_prefix(lookBuf, LANDMARK)) {
+ break;
+ }
+ /* If we are out of paths to search - give up */
+ if (look < module_search_path)
+ break;
+ look--;
+ }
+ }
+}
+
+
+/* External interface */
+
+char *
+Py_GetPath(void)
+{
+ if (!module_search_path)
+ calculate_path();
+ return module_search_path;
+}
+
+char *
+Py_GetPrefix(void)
+{
+ if (!module_search_path)
+ calculate_path();
+ return prefix;
+}
+
+char *
+Py_GetExecPrefix(void)
+{
+ return Py_GetPrefix();
+}
+
+char *
+Py_GetProgramFullPath(void)
+{
+ if (!module_search_path)
+ calculate_path();
+ return progpath;
+}
diff --git a/contrib/tools/python/src/PC/import_nt.c b/contrib/tools/python/src/PC/import_nt.c
new file mode 100644
index 00000000000..9b0d8e8c1df
--- /dev/null
+++ b/contrib/tools/python/src/PC/import_nt.c
@@ -0,0 +1,86 @@
+/********************************************************************
+
+ import_nt.c
+
+ Win32 specific import code.
+
+*/
+
+#include "Python.h"
+#include "osdefs.h"
+#include <windows.h>
+#include <Python/importdl.h>
+#include "malloc.h" /* for alloca */
+
+/* a string loaded from the DLL at startup */
+extern const char *PyWin_DLLVersionString;
+
+FILE *PyWin_FindRegisteredModule(const char *moduleName,
+ struct filedescr **ppFileDesc,
+ char *pathBuf,
+ Py_ssize_t pathLen)
+{
+ char *moduleKey;
+ const char keyPrefix[] = "Software\\Python\\PythonCore\\";
+ const char keySuffix[] = "\\Modules\\";
+#ifdef _DEBUG
+ /* In debugging builds, we _must_ have the debug version
+ * registered.
+ */
+ const char debugString[] = "\\Debug";
+#else
+ const char debugString[] = "";
+#endif
+ struct filedescr *fdp = NULL;
+ FILE *fp;
+ HKEY keyBase = HKEY_CURRENT_USER;
+ LONG modNameSize;
+ long regStat;
+
+ /* Calculate the size for the sprintf buffer.
+ * Get the size of the chars only, plus 1 NULL.
+ */
+ size_t bufSize = sizeof(keyPrefix)-1 +
+ strlen(PyWin_DLLVersionString) +
+ sizeof(keySuffix) +
+ strlen(moduleName) +
+ sizeof(debugString) - 1;
+ /* alloca == no free required, but memory only local to fn,
+ * also no heap fragmentation!
+ */
+ moduleKey = (char*)alloca(bufSize);
+ PyOS_snprintf(moduleKey, bufSize,
+ "Software\\Python\\PythonCore\\%s\\Modules\\%s%s",
+ PyWin_DLLVersionString, moduleName, debugString);
+
+ assert(pathLen < INT_MAX);
+ modNameSize = (int)pathLen;
+ regStat = RegQueryValue(keyBase, moduleKey, pathBuf, &modNameSize);
+ if (regStat != ERROR_SUCCESS) {
+ /* No user setting - lookup in machine settings */
+ keyBase = HKEY_LOCAL_MACHINE;
+ /* be anal - failure may have reset size param */
+ modNameSize = (int)pathLen;
+ regStat = RegQueryValue(keyBase, moduleKey,
+ pathBuf, &modNameSize);
+
+ if (regStat != ERROR_SUCCESS)
+ return NULL;
+ }
+ /* use the file extension to locate the type entry. */
+ for (fdp = _PyImport_Filetab; fdp->suffix != NULL; fdp++) {
+ size_t extLen = strlen(fdp->suffix);
+ assert(modNameSize >= 0); /* else cast to size_t is wrong */
+ if ((size_t)modNameSize > extLen &&
+ strnicmp(pathBuf + ((size_t)modNameSize-extLen-1),
+ fdp->suffix,
+ extLen) == 0)
+ break;
+ }
+ if (fdp->suffix == NULL)
+ return NULL;
+ fp = fopen(pathBuf, fdp->mode);
+ if (fp != NULL)
+ *ppFileDesc = fdp;
+ return fp;
+}
diff --git a/contrib/tools/python/src/PC/msvcrtmodule.c b/contrib/tools/python/src/PC/msvcrtmodule.c
new file mode 100644
index 00000000000..44c82e4594f
--- /dev/null
+++ b/contrib/tools/python/src/PC/msvcrtmodule.c
@@ -0,0 +1,430 @@
+/*********************************************************
+
+ msvcrtmodule.c
+
+ A Python interface to the Microsoft Visual C Runtime
+ Library, providing access to those non-portable, but
+ still useful routines.
+
+ Only ever compiled with an MS compiler, so no attempt
+ has been made to avoid MS language extensions, etc...
+
+ This may only work on NT or 95...
+
+ Author: Mark Hammond and Guido van Rossum.
+ Maintenance: Guido van Rossum.
+
+***********************************************************/
+
+#include "Python.h"
+#include "malloc.h"
+#include <io.h>
+#include <conio.h>
+#include <sys/locking.h>
+
+#ifdef _MSC_VER
+#if _MSC_VER >= 1500 && _MSC_VER < 1600
+#include <crtassem.h>
+#endif
+#endif
+
+// Force the malloc heap to clean itself up, and free unused blocks
+// back to the OS. (According to the docs, only works on NT.)
+static PyObject *
+msvcrt_heapmin(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":heapmin"))
+ return NULL;
+
+ if (_heapmin() != 0)
+ return PyErr_SetFromErrno(PyExc_IOError);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+PyDoc_STRVAR(heapmin_doc,
+"heapmin() -> None\n\
+\n\
+Force the malloc() heap to clean itself up and return unused blocks\n\
+to the operating system. On failure, this raises IOError.");
+
+// Perform locking operations on a C runtime file descriptor.
+static PyObject *
+msvcrt_locking(PyObject *self, PyObject *args)
+{
+ int fd;
+ int mode;
+ long nbytes;
+ int err;
+
+ if (!PyArg_ParseTuple(args, "iil:locking", &fd, &mode, &nbytes))
+ return NULL;
+
+ Py_BEGIN_ALLOW_THREADS
+ err = _locking(fd, mode, nbytes);
+ Py_END_ALLOW_THREADS
+ if (err != 0)
+ return PyErr_SetFromErrno(PyExc_IOError);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+PyDoc_STRVAR(locking_doc,
+"locking(fd, mode, nbytes) -> None\n\
+\n\
+Lock part of a file based on file descriptor fd from the C runtime.\n\
+Raises IOError on failure. The locked region of the file extends from\n\
+the current file position for nbytes bytes, and may continue beyond\n\
+the end of the file. mode must be one of the LK_* constants listed\n\
+below. Multiple regions in a file may be locked at the same time, but\n\
+may not overlap. Adjacent regions are not merged; they must be unlocked\n\
+individually.");
+
+// Set the file translation mode for a C runtime file descriptor.
+static PyObject *
+msvcrt_setmode(PyObject *self, PyObject *args)
+{
+ int fd;
+ int flags;
+ if (!PyArg_ParseTuple(args,"ii:setmode", &fd, &flags))
+ return NULL;
+
+ flags = _setmode(fd, flags);
+ if (flags == -1)
+ return PyErr_SetFromErrno(PyExc_IOError);
+
+ return PyInt_FromLong(flags);
+}
+
+PyDoc_STRVAR(setmode_doc,
+"setmode(fd, mode) -> Previous mode\n\
+\n\
+Set the line-end translation mode for the file descriptor fd. To set\n\
+it to text mode, flags should be os.O_TEXT; for binary, it should be\n\
+os.O_BINARY.");
+
+// Convert an OS file handle to a C runtime file descriptor.
+static PyObject *
+msvcrt_open_osfhandle(PyObject *self, PyObject *args)
+{
+ long handle;
+ int flags;
+ int fd;
+
+ if (!PyArg_ParseTuple(args, "li:open_osfhandle", &handle, &flags))
+ return NULL;
+
+ fd = _open_osfhandle(handle, flags);
+ if (fd == -1)
+ return PyErr_SetFromErrno(PyExc_IOError);
+
+ return PyInt_FromLong(fd);
+}
+
+PyDoc_STRVAR(open_osfhandle_doc,
+"open_osfhandle(handle, flags) -> file descriptor\n\
+\n\
+Create a C runtime file descriptor from the file handle handle. The\n\
+flags parameter should be a bitwise OR of os.O_APPEND, os.O_RDONLY,\n\
+and os.O_TEXT. The returned file descriptor may be used as a parameter\n\
+to os.fdopen() to create a file object.");
+
+// Convert a C runtime file descriptor to an OS file handle.
+static PyObject *
+msvcrt_get_osfhandle(PyObject *self, PyObject *args)
+{
+ int fd;
+ Py_intptr_t handle;
+
+ if (!PyArg_ParseTuple(args,"i:get_osfhandle", &fd))
+ return NULL;
+
+ if (!_PyVerify_fd(fd))
+ return PyErr_SetFromErrno(PyExc_IOError);
+
+ handle = _get_osfhandle(fd);
+ if (handle == -1)
+ return PyErr_SetFromErrno(PyExc_IOError);
+
+ /* technically 'handle' is not a pointer, but an integer as
+ large as a pointer, Python's *VoidPtr interface is the
+ most appropriate here */
+ return PyLong_FromVoidPtr((void*)handle);
+}
+
+PyDoc_STRVAR(get_osfhandle_doc,
+"get_osfhandle(fd) -> file handle\n\
+\n\
+Return the file handle for the file descriptor fd. Raises IOError\n\
+if fd is not recognized.");
+
+/* Console I/O */
+
+static PyObject *
+msvcrt_kbhit(PyObject *self, PyObject *args)
+{
+ int ok;
+
+ if (!PyArg_ParseTuple(args, ":kbhit"))
+ return NULL;
+
+ ok = _kbhit();
+ return PyInt_FromLong(ok);
+}
+
+PyDoc_STRVAR(kbhit_doc,
+"kbhit() -> bool\n\
+\n\
+Return true if a keypress is waiting to be read.");
+
+static PyObject *
+msvcrt_getch(PyObject *self, PyObject *args)
+{
+ int ch;
+ char s[1];
+
+ if (!PyArg_ParseTuple(args, ":getch"))
+ return NULL;
+
+ Py_BEGIN_ALLOW_THREADS
+ ch = _getch();
+ Py_END_ALLOW_THREADS
+ s[0] = ch;
+ return PyString_FromStringAndSize(s, 1);
+}
+
+PyDoc_STRVAR(getch_doc,
+"getch() -> key character\n\
+\n\
+Read a keypress and return the resulting character. Nothing is echoed to\n\
+the console. This call will block if a keypress is not already\n\
+available, but will not wait for Enter to be pressed. If the pressed key\n\
+was a special function key, this will return '\\000' or '\\xe0'; the next\n\
+call will return the keycode. The Control-C keypress cannot be read with\n\
+this function.");
+
+#ifdef _WCONIO_DEFINED
+static PyObject *
+msvcrt_getwch(PyObject *self, PyObject *args)
+{
+ Py_UNICODE ch;
+ Py_UNICODE u[1];
+
+ if (!PyArg_ParseTuple(args, ":getwch"))
+ return NULL;
+
+ Py_BEGIN_ALLOW_THREADS
+ ch = _getwch();
+ Py_END_ALLOW_THREADS
+ u[0] = ch;
+ return PyUnicode_FromUnicode(u, 1);
+}
+
+PyDoc_STRVAR(getwch_doc,
+"getwch() -> Unicode key character\n\
+\n\
+Wide char variant of getch(), returning a Unicode value.");
+#endif
+
+static PyObject *
+msvcrt_getche(PyObject *self, PyObject *args)
+{
+ int ch;
+ char s[1];
+
+ if (!PyArg_ParseTuple(args, ":getche"))
+ return NULL;
+
+ Py_BEGIN_ALLOW_THREADS
+ ch = _getche();
+ Py_END_ALLOW_THREADS
+ s[0] = ch;
+ return PyString_FromStringAndSize(s, 1);
+}
+
+PyDoc_STRVAR(getche_doc,
+"getche() -> key character\n\
+\n\
+Similar to getch(), but the keypress will be echoed if it represents\n\
+a printable character.");
+
+#ifdef _WCONIO_DEFINED
+static PyObject *
+msvcrt_getwche(PyObject *self, PyObject *args)
+{
+ Py_UNICODE ch;
+ Py_UNICODE s[1];
+
+ if (!PyArg_ParseTuple(args, ":getwche"))
+ return NULL;
+
+ Py_BEGIN_ALLOW_THREADS
+ ch = _getwche();
+ Py_END_ALLOW_THREADS
+ s[0] = ch;
+ return PyUnicode_FromUnicode(s, 1);
+}
+
+PyDoc_STRVAR(getwche_doc,
+"getwche() -> Unicode key character\n\
+\n\
+Wide char variant of getche(), returning a Unicode value.");
+#endif
+
+static PyObject *
+msvcrt_putch(PyObject *self, PyObject *args)
+{
+ char ch;
+
+ if (!PyArg_ParseTuple(args, "c:putch", &ch))
+ return NULL;
+
+ _putch(ch);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+PyDoc_STRVAR(putch_doc,
+"putch(char) -> None\n\
+\n\
+Print the character char to the console without buffering.");
+
+#ifdef _WCONIO_DEFINED
+static PyObject *
+msvcrt_putwch(PyObject *self, PyObject *args)
+{
+ Py_UNICODE *ch;
+ int size;
+
+ if (!PyArg_ParseTuple(args, "u#:putwch", &ch, &size))
+ return NULL;
+
+ if (size == 0) {
+ PyErr_SetString(PyExc_ValueError,
+ "Expected unicode string of length 1");
+ return NULL;
+ }
+ _putwch(*ch);
+ Py_RETURN_NONE;
+
+}
+
+PyDoc_STRVAR(putwch_doc,
+"putwch(unicode_char) -> None\n\
+\n\
+Wide char variant of putch(), accepting a Unicode value.");
+#endif
+
+static PyObject *
+msvcrt_ungetch(PyObject *self, PyObject *args)
+{
+ char ch;
+
+ if (!PyArg_ParseTuple(args, "c:ungetch", &ch))
+ return NULL;
+
+ if (_ungetch(ch) == EOF)
+ return PyErr_SetFromErrno(PyExc_IOError);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+PyDoc_STRVAR(ungetch_doc,
+"ungetch(char) -> None\n\
+\n\
+Cause the character char to be \"pushed back\" into the console buffer;\n\
+it will be the next character read by getch() or getche().");
+
+#ifdef _WCONIO_DEFINED
+static PyObject *
+msvcrt_ungetwch(PyObject *self, PyObject *args)
+{
+ Py_UNICODE ch;
+
+ if (!PyArg_ParseTuple(args, "u:ungetwch", &ch))
+ return NULL;
+
+ if (_ungetch(ch) == EOF)
+ return PyErr_SetFromErrno(PyExc_IOError);
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+PyDoc_STRVAR(ungetwch_doc,
+"ungetwch(unicode_char) -> None\n\
+\n\
+Wide char variant of ungetch(), accepting a Unicode value.");
+#endif
+
+static void
+insertint(PyObject *d, char *name, int value)
+{
+ PyObject *v = PyInt_FromLong((long) value);
+ if (v == NULL) {
+ /* Don't bother reporting this error */
+ PyErr_Clear();
+ }
+ else {
+ PyDict_SetItemString(d, name, v);
+ Py_DECREF(v);
+ }
+}
+
+
+/* List of functions exported by this module */
+static struct PyMethodDef msvcrt_functions[] = {
+ {"heapmin", msvcrt_heapmin, METH_VARARGS, heapmin_doc},
+ {"locking", msvcrt_locking, METH_VARARGS, locking_doc},
+ {"setmode", msvcrt_setmode, METH_VARARGS, setmode_doc},
+ {"open_osfhandle", msvcrt_open_osfhandle, METH_VARARGS, open_osfhandle_doc},
+ {"get_osfhandle", msvcrt_get_osfhandle, METH_VARARGS, get_osfhandle_doc},
+ {"kbhit", msvcrt_kbhit, METH_VARARGS, kbhit_doc},
+ {"getch", msvcrt_getch, METH_VARARGS, getch_doc},
+ {"getche", msvcrt_getche, METH_VARARGS, getche_doc},
+ {"putch", msvcrt_putch, METH_VARARGS, putch_doc},
+ {"ungetch", msvcrt_ungetch, METH_VARARGS, ungetch_doc},
+#ifdef _WCONIO_DEFINED
+ {"getwch", msvcrt_getwch, METH_VARARGS, getwch_doc},
+ {"getwche", msvcrt_getwche, METH_VARARGS, getwche_doc},
+ {"putwch", msvcrt_putwch, METH_VARARGS, putwch_doc},
+ {"ungetwch", msvcrt_ungetwch, METH_VARARGS, ungetwch_doc},
+#endif
+ {NULL, NULL}
+};
+
+PyMODINIT_FUNC
+initmsvcrt(void)
+{
+ int st;
+ PyObject *d;
+ PyObject *m = Py_InitModule("msvcrt", msvcrt_functions);
+ if (m == NULL)
+ return;
+ d = PyModule_GetDict(m);
+
+ /* constants for the locking() function's mode argument */
+ insertint(d, "LK_LOCK", _LK_LOCK);
+ insertint(d, "LK_NBLCK", _LK_NBLCK);
+ insertint(d, "LK_NBRLCK", _LK_NBRLCK);
+ insertint(d, "LK_RLCK", _LK_RLCK);
+ insertint(d, "LK_UNLCK", _LK_UNLCK);
+
+ /* constants for the crt versions */
+#ifdef _VC_ASSEMBLY_PUBLICKEYTOKEN
+ st = PyModule_AddStringConstant(m, "VC_ASSEMBLY_PUBLICKEYTOKEN",
+ _VC_ASSEMBLY_PUBLICKEYTOKEN);
+ if (st < 0)return;
+#endif
+#ifdef _CRT_ASSEMBLY_VERSION
+ st = PyModule_AddStringConstant(m, "CRT_ASSEMBLY_VERSION",
+ _CRT_ASSEMBLY_VERSION);
+ if (st < 0)return;
+#endif
+#ifdef __LIBRARIES_ASSEMBLY_NAME_PREFIX
+ st = PyModule_AddStringConstant(m, "LIBRARIES_ASSEMBLY_NAME_PREFIX",
+ __LIBRARIES_ASSEMBLY_NAME_PREFIX);
+ if (st < 0)return;
+#endif
+}