From 9461d3d230665ee6caab886527f6376f7bc799d8 Mon Sep 17 00:00:00 2001 From: Ray Donnelly Date: Sat, 16 Mar 2019 22:49:28 +0000 Subject: [PATCH 17/17] Use CreateProcessW to support Unicode --- PC/_subprocess.c | 133 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 107 insertions(+), 26 deletions(-) diff --git a/PC/_subprocess.c b/PC/_subprocess.c index 66940ff7e4..591fab9513 100644 --- a/PC/_subprocess.c +++ b/PC/_subprocess.c @@ -425,36 +425,110 @@ 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; + STARTUPINFOW si; PyObject* environment; - char* application_name; - char* command_line; PyObject* process_attributes; /* ignored */ PyObject* thread_attributes; /* ignored */ int inherit_handles; + int i, j, len; int creation_flags; PyObject* env_mapping; - char* current_directory; PyObject* startup_info; - - if (! PyArg_ParseTuple(args, "zzOOiiOzO:CreateProcess", - &application_name, - &command_line, + #define APPLICATION_NAME 0 + #define COMMAND_LINE 1 + #define CURRENT_DIRECTORY 2 + #define ENVIRONMENT 3 + PyObject* us[4] = {NULL, NULL, NULL, NULL}; + PyObject* ss[4] = {NULL, NULL, NULL, NULL}; + wchar_t* wc[4] = {NULL, NULL, NULL, NULL}; + + if (! PyArg_ParseTuple(args, "OOOOiiOOO:CreateProcess", + &ss[APPLICATION_NAME], + &ss[COMMAND_LINE], &process_attributes, &thread_attributes, &inherit_handles, &creation_flags, &env_mapping, - ¤t_directory, + &ss[CURRENT_DIRECTORY], &startup_info)) return NULL; + if (env_mapping == Py_None) + environment = NULL; + else { + environment = getenvironment(env_mapping); + if (! environment) + return NULL; + } + + if (environment != NULL) { + ss[ENVIRONMENT] = environment; + } else { + ss[ENVIRONMENT] = Py_None; + } + + /* Was going to use CreateProcessA when all strings, but what about env_mapping? Best to always + go Unicode. Also, consider renaming this to CreateProcessW()? + if (PyString_Check(ss[APPLICATION_NAME]) && PyString_Check(ss[COMMAND_LINE]) && + PyString_Check(ss[CURRENT_DIRECTORY])) { + unicode = FALSE; + } else */ { + for (i = 0; i < 4; ++i) { + if (ss[i] == Py_None) { + continue; + } else if (PyUnicode_Check(ss[i])) { + us[i] = ss[i]; + } else { + us[i] = PyUnicode_FromEncodedObject(ss[i], "utf-8", "strict"); + if (us[i] == NULL) { + for (j = 0; j < i; ++j) { + if (us[j] != NULL && ss[j] != us[j]) { + Py_DECREF(us[j]); + } + } + return NULL; + } + } + } + } + for (i = 0; i < 4; ++i) { + /* Convert the unicode strings to wchar[]. */ + if (us[i] == NULL) { + continue; + } + len = PyUnicode_GET_SIZE(us[i]) + 1; + wc[i] = PyMem_NEW(wchar_t, len); + if (wc[i] == NULL) { + for (j = 0; j < 3; ++j) { + if (us[j] != NULL && ss[j] != us[j]) { + Py_DECREF(us[j]); + } + } + + PyErr_NoMemory(); + return NULL; + } + if (PyUnicode_AsWideChar((PyUnicodeObject*)us[i], wc[i], len) == -1) { + for (j = 0; j < 4; ++j) { + if (us[j] != NULL && ss[j] != us[j]) { + Py_DECREF(us[j]); + } + if (wc[j] != NULL) { + PyMem_FREE(wc[j]); + } + } + return NULL; + } + wc[i][len - 1] = 0; + } ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); @@ -468,27 +542,30 @@ sp_CreateProcess(PyObject* self, PyObject* args) if (PyErr_Occurred()) return NULL; - if (env_mapping == Py_None) - environment = NULL; - else { - environment = getenvironment(env_mapping); - if (! environment) - return NULL; - } + creation_flags |= CREATE_UNICODE_ENVIRONMENT; 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); + result = CreateProcessW(wc[APPLICATION_NAME], + wc[COMMAND_LINE], + NULL, + NULL, + inherit_handles, + creation_flags, + wc[ENVIRONMENT], + wc[CURRENT_DIRECTORY], + &si, + &pi); Py_END_ALLOW_THREADS + for (i = 0; i < 4; ++i) { + if (us[i] != NULL && ss[i] != us[i]) { + Py_DECREF(us[i]); + } + if (wc[i] != NULL) { + PyMem_FREE(wc[i]); + } + } + Py_XDECREF(environment); if (! result) @@ -499,6 +576,10 @@ sp_CreateProcess(PyObject* self, PyObject* args) sp_handle_new(pi.hThread), pi.dwProcessId, pi.dwThreadId); + #undef APPLICATION_NAME + #undef COMMAND_LINE + #undef CURRENT_DIRECTORY + #undef ENVIRONMENT } PyDoc_STRVAR(TerminateProcess_doc, -- 2.20.1