Three patches from issue #1047, by Amaury Forgeot d'Arc:

1/ getargs.diff adds the 'Z' and 'Z#' format specifiers for
PyArg_ParseTuple. They mimic z and z# for unicode strings, by accepting
a Unicode or None (in which case the Py_UNICODE* pointer is set to
NULL). With doc and tests.

2/ subprocess.diff converts file PC/_subprocess.c to unicode. We use the
Unicode version of the win32 api (and Z conversion from previous patch)

3/ stdout.diff: sys.stdout must not convert the line endings, Windows
already does it.
Without this patch, when redirecting the output of python, the file
contains \r\r\n for each line. (test_subprocess did catch this)

However, I (GvR) removed the change to _fileio.c (included in the
patches) that prevents closing file descripors < 3 from being closed;
I think that needs to be solved in a different way.
diff --git a/PC/_subprocess.c b/PC/_subprocess.c
index 14e1333..e711e13 100644
--- a/PC/_subprocess.c
+++ b/PC/_subprocess.c
@@ -35,9 +35,6 @@
 /* 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
@@ -272,7 +269,7 @@
 		PyErr_Clear(); /* FIXME: propagate error? */
 		return NULL;
 	}
-	if (Py_Type(&value) != &sp_handle_type)
+	if (Py_Type(value) != &sp_handle_type)
 		ret = NULL;
 	else
 		ret = value->handle;
@@ -287,7 +284,7 @@
 	PyObject* out = NULL;
 	PyObject* keys;
 	PyObject* values;
-	char* p;
+	Py_UNICODE* p;
 
 	/* convert environment dictionary to windows enviroment string */
 	if (! PyMapping_Check(environment)) {
@@ -303,42 +300,42 @@
 	if (!keys || !values)
 		goto error;
 
-	out = PyString_FromStringAndSize(NULL, 2048);
+	out = PyUnicode_FromUnicode(NULL, 2048);
 	if (! out)
 		goto error;
 
-	p = PyString_AS_STRING(out);
+	p = PyUnicode_AS_UNICODE(out);
 
 	for (i = 0; i < envsize; i++) {
 		int ksize, vsize, totalsize;
 		PyObject* key = PyList_GET_ITEM(keys, i);
 		PyObject* value = PyList_GET_ITEM(values, i);
 
-		if (! PyString_Check(key) || ! PyString_Check(value)) {
+		if (! PyUnicode_Check(key) || ! PyUnicode_Check(value)) {
 			PyErr_SetString(PyExc_TypeError,
 				"environment can only contain strings");
 			goto error;
 		}
-		ksize = PyString_GET_SIZE(key);
-		vsize = PyString_GET_SIZE(value);
-		totalsize = (p - PyString_AS_STRING(out)) + ksize + 1 +
+		ksize = PyUnicode_GET_SIZE(key);
+		vsize = PyUnicode_GET_SIZE(value);
+		totalsize = (p - PyUnicode_AS_UNICODE(out)) + ksize + 1 +
 							     vsize + 1 + 1;
-		if (totalsize > PyString_GET_SIZE(out)) {
-			int offset = p - PyString_AS_STRING(out);
-			_PyString_Resize(&out, totalsize + 1024);
-			p = PyString_AS_STRING(out) + offset;
+		if (totalsize > PyUnicode_GET_SIZE(out)) {
+			int offset = p - PyUnicode_AS_UNICODE(out);
+			PyUnicode_Resize(&out, totalsize + 1024);
+			p = PyUnicode_AS_UNICODE(out) + offset;
 		}
-		memcpy(p, PyString_AS_STRING(key), ksize);
+		Py_UNICODE_COPY(p, PyUnicode_AS_UNICODE(key), ksize);
 		p += ksize;
 		*p++ = '=';
-		memcpy(p, PyString_AS_STRING(value), vsize);
+		Py_UNICODE_COPY(p, PyUnicode_AS_UNICODE(value), vsize);
 		p += vsize;
 		*p++ = '\0';
 	}
 
 	/* add trailing null byte */
 	*p++ = '\0';
-	_PyString_Resize(&out, p - PyString_AS_STRING(out));
+	PyUnicode_Resize(&out, p - PyUnicode_AS_UNICODE(out));
 
 	/* PyObject_Print(out, stdout, 0); */
 
@@ -359,20 +356,20 @@
 {
 	BOOL result;
 	PROCESS_INFORMATION pi;
-	STARTUPINFO si;
+	STARTUPINFOW si;
 	PyObject* environment;
 
-	char* application_name;
-	char* command_line;
+	Py_UNICODE* application_name;
+	Py_UNICODE* command_line;
 	PyObject* process_attributes; /* ignored */
 	PyObject* thread_attributes; /* ignored */
 	int inherit_handles;
 	int creation_flags;
 	PyObject* env_mapping;
-	char* current_directory;
+	Py_UNICODE* current_directory;
 	PyObject* startup_info;
 
-	if (! PyArg_ParseTuple(args, "zzOOiiOzO:CreateProcess",
+	if (! PyArg_ParseTuple(args, "ZZOOiiOZO:CreateProcess",
 			       &application_name,
 			       &command_line,
 			       &process_attributes,
@@ -406,13 +403,13 @@
 	}
 
 	Py_BEGIN_ALLOW_THREADS
-	result = CreateProcess(application_name,
+	result = CreateProcessW(application_name,
 			       command_line,
 			       NULL,
 			       NULL,
 			       inherit_handles,
-			       creation_flags,
-			       environment ? PyString_AS_STRING(environment) : NULL,
+			       creation_flags | CREATE_UNICODE_ENVIRONMENT,
+			       environment ? PyUnicode_AS_UNICODE(environment) : NULL,
 			       current_directory,
 			       &si,
 			       &pi);
@@ -504,18 +501,18 @@
 {
 	BOOL result;
 	long module;
-	TCHAR filename[MAX_PATH];
+	WCHAR filename[MAX_PATH];
 
 	if (! PyArg_ParseTuple(args, "l:GetModuleFileName", &module))
 		return NULL;
 
-	result = GetModuleFileName((HMODULE)module, filename, MAX_PATH);
+	result = GetModuleFileNameW((HMODULE)module, filename, MAX_PATH);
 	filename[MAX_PATH-1] = '\0';
 
 	if (! result)
 		return PyErr_SetFromWindowsErr(GetLastError());
 
-	return PyString_FromString(filename);
+	return PyUnicode_FromUnicode(filename, Py_UNICODE_strlen(filename));
 }
 
 static PyMethodDef sp_functions[] = {