Wrap CommandLineToArgvW

This commit is contained in:
Kovid Goyal 2020-10-14 12:47:40 +05:30
parent 3fa1331448
commit 15443c869e
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 23 additions and 18 deletions

View File

@ -250,6 +250,7 @@ class BuildTest(unittest.TestCase):
m = winutil.create_mutex("test-mutex", False)
self.assertRaises(OSError, winutil.create_mutex, 'test-mutex', False)
m.close()
self.assertEqual(winutil.parse_cmdline('"c:\\test exe.exe" "some arg" 2'), ('c:\\test exe.exe', 'some arg', '2'))
def test_sqlite(self):
import sqlite3

View File

@ -800,6 +800,25 @@ create_mutex(PyObject *self, PyObject *args) {
return (PyObject*)Handle_create(h);
}
static PyObject*
parse_cmdline(PyObject *self, PyObject *args) {
wchar_raii cmdline;
if (!PyArg_ParseTuple(args, "O&", py_to_wchar_no_none, &cmdline)) return NULL;
int num;
LPWSTR *data = CommandLineToArgvW(cmdline.ptr(), &num);
if (data == NULL) return PyErr_SetFromWindowsErr(0);
PyObject *ans = PyTuple_New(num);
if (!ans) { LocalFree(data); return NULL; }
for (int i = 0; i < num; i++) {
PyObject *temp = PyUnicode_FromWideChar(data[i], -1);
if (!temp) { Py_CLEAR(ans); LocalFree(data); return NULL; }
PyTuple_SET_ITEM(ans, i, temp);
}
LocalFree(data);
return ans;
}
// Icon loading {{{
#pragma pack( push )
#pragma pack( 2 )
@ -945,6 +964,7 @@ static PyMethodDef winutil_methods[] = {
M(load_library, METH_VARARGS),
M(load_icons, METH_VARARGS),
M(get_icon_for_file, METH_VARARGS),
M(parse_cmdline, METH_VARARGS),
{"special_folder_path", winutil_folder_path, METH_VARARGS,
"special_folder_path(csidl_id) -> path\n\n"

View File

@ -5,8 +5,7 @@
__license__ = 'GPL v3'
__copyright__ = '2015, Kovid Goyal <kovid at kovidgoyal.net>'
import os, sys, time, ctypes, traceback
from ctypes.wintypes import HLOCAL, LPCWSTR
import os, sys, time, traceback
from threading import Thread
import winerror
@ -225,26 +224,11 @@ def get_open_data(base, prog_id):
return cmd, k.get(sub_key='DefaultIcon'), k.get_mui_string('FriendlyTypeName') or k.get()
CommandLineToArgvW = ctypes.windll.shell32.CommandLineToArgvW
CommandLineToArgvW.arg_types = [LPCWSTR, ctypes.POINTER(ctypes.c_int)]
CommandLineToArgvW.restype = ctypes.POINTER(LPCWSTR)
LocalFree = ctypes.windll.kernel32.LocalFree
LocalFree.res_type = HLOCAL
LocalFree.arg_types = [HLOCAL]
def split_commandline(commandline):
# CommandLineToArgvW returns path to executable if called with empty string.
if not commandline.strip():
return []
num = ctypes.c_int(0)
result_pointer = CommandLineToArgvW(commandline.lstrip(), ctypes.byref(num))
if not result_pointer:
raise ctypes.WinError()
result_array_type = LPCWSTR * num.value
result = [arg for arg in result_array_type.from_address(ctypes.addressof(result_pointer.contents))]
LocalFree(result_pointer)
return result
return list(plugins['winutil'][0].parse_cmdline(commandline))
def friendly_app_name(prog_id=None, exe=None):