comtypes 1.4.9__zip → 1.4.11__zip
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {comtypes-1.4.9 → comtypes-1.4.11}/CHANGES.txt +41 -0
- {comtypes-1.4.9/comtypes.egg-info → comtypes-1.4.11}/PKG-INFO +4 -2
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/GUID.py +34 -13
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/__init__.py +25 -16
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_comobject.py +92 -39
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_memberspec.py +112 -78
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_meta.py +2 -1
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_post_coinit/_cominterface_meta_patcher.py +3 -6
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_post_coinit/bstr.py +12 -5
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_post_coinit/instancemethod.py +1 -2
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_post_coinit/misc.py +59 -24
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_post_coinit/unknwn.py +30 -25
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_safearray.py +2 -2
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_vtbl.py +52 -55
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/automation.py +19 -14
- comtypes-1.4.11/comtypes/client/__init__.py +42 -0
- comtypes-1.4.11/comtypes/client/_activeobj.py +46 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/client/_code_cache.py +15 -24
- comtypes-1.4.11/comtypes/client/_create.py +147 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/client/_events.py +140 -57
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/client/_generate.py +3 -5
- comtypes-1.4.11/comtypes/client/_managing.py +114 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/client/dynamic.py +2 -3
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/client/lazybind.py +10 -11
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/connectionpoints.py +38 -3
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/errorinfo.py +72 -21
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/git.py +4 -3
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/hints.pyi +15 -2
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/hresult.py +16 -6
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/logutil.py +15 -3
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/messageloop.py +15 -13
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/persist.py +3 -5
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/safearray.py +8 -6
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/server/__init__.py +22 -4
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/server/automation.py +1 -2
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/server/connectionpoints.py +71 -70
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/server/inprocserver.py +14 -8
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/server/localserver.py +28 -16
- comtypes-1.4.11/comtypes/server/register.py +478 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/shelllink.py +13 -7
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/stream.py +7 -4
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/TestComServer.py +6 -7
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/TestDispServer.py +4 -2
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/__init__.py +1 -1
- comtypes-1.4.11/comtypes/test/find_memleak.py +72 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/runtests.py +1 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/setup.py +2 -1
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_BSTR.py +7 -17
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_GUID.py +7 -7
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_QueryService.py +1 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_agilent.py +4 -3
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_basic.py +18 -9
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_clear_cache.py +1 -1
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_client.py +2 -2
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_client_dynamic.py +2 -2
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_client_regenerate_modules.py +2 -2
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_collections.py +7 -4
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_comobject.py +22 -9
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_comserver.py +56 -3
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_dict.py +2 -1
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_dispifc_records.py +1 -1
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_dispifc_safearrays.py +1 -1
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_dyndispatch.py +5 -2
- comtypes-1.4.11/comtypes/test/test_errorinfo.py +115 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_findgendir.py +1 -2
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_getactiveobj.py +4 -4
- comtypes-1.4.11/comtypes/test/test_hresult.py +48 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_ie.py +19 -6
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_ienum.py +2 -2
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_imfattributes.py +13 -3
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_inout_args.py +10 -3
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_midl_safearray_create.py +6 -4
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_monikers.py +23 -9
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_msscript.py +2 -1
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_npsupport.py +4 -4
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_outparam.py +22 -6
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_persist.py +2 -4
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_recordinfo.py +1 -1
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_safearray.py +2 -1
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_sapi.py +4 -1
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_server_register.py +114 -125
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_shelllink.py +2 -3
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_storage.py +12 -6
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_stream.py +16 -5
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_subinterface.py +4 -2
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_typeannotator.py +1 -2
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_typeinfo.py +36 -7
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_urlhistory.py +7 -4
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_variant.py +5 -3
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_w_getopt.py +4 -4
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_word.py +1 -1
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/tools/codegenerator/codegenerator.py +167 -435
- comtypes-1.4.11/comtypes/tools/codegenerator/comments.py +79 -0
- comtypes-1.4.11/comtypes/tools/codegenerator/heads.py +192 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/tools/codegenerator/helpers.py +3 -6
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/tools/codegenerator/namespaces.py +13 -5
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/tools/codegenerator/typeannotator.py +13 -3
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/tools/tlbparser.py +25 -25
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/tools/typedesc.py +3 -2
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/tools/typedesc_base.py +2 -2
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/typeinfo.py +163 -51
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/viewobject.py +2 -4
- {comtypes-1.4.9 → comtypes-1.4.11/comtypes.egg-info}/PKG-INFO +4 -2
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes.egg-info/SOURCES.txt +7 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/pyproject.toml +10 -23
- comtypes-1.4.9/comtypes/client/__init__.py +0 -323
- comtypes-1.4.9/comtypes/server/register.py +0 -419
- comtypes-1.4.9/comtypes/test/find_memleak.py +0 -76
- {comtypes-1.4.9 → comtypes-1.4.11}/LICENSE.txt +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/MANIFEST.in +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/README.md +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_npsupport.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_post_coinit/__init__.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/_tlib_version_checker.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/clear_cache.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/client/_constants.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/patcher.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/server/w_getopt.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/TestComServer.idl +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/TestComServer.tlb +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/TestDispServer.idl +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/TestDispServer.tlb +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/mylib.idl +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/mylib.tlb +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/mytypelib.idl +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_DISPPARAMS.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_avmc.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_casesensitivity.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_createwrappers.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_dispinterface.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_excel.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_jscript.js +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_pump_events.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_server.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_showevents.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_win32com_interop.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/test_wmi.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/test/urlhist.tlb +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/tools/__init__.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/tools/codegenerator/__init__.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/tools/codegenerator/modulenamer.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/tools/codegenerator/packing.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes/util.py +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes.egg-info/dependency_links.txt +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes.egg-info/entry_points.txt +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/comtypes.egg-info/top_level.txt +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/setup.cfg +0 -0
- {comtypes-1.4.9 → comtypes-1.4.11}/setup.py +0 -0
|
@@ -1,26 +1,80 @@
|
|
|
1
1
|
import _ctypes
|
|
2
|
-
import ctypes
|
|
3
2
|
import os
|
|
4
3
|
import sys
|
|
5
4
|
import unittest as ut
|
|
6
5
|
import winreg
|
|
6
|
+
from ctypes.wintypes import MAX_PATH
|
|
7
7
|
from unittest import mock
|
|
8
8
|
|
|
9
9
|
import comtypes
|
|
10
10
|
import comtypes.server.inprocserver
|
|
11
11
|
from comtypes import GUID
|
|
12
12
|
from comtypes.server import register
|
|
13
|
-
from comtypes.server.register import
|
|
13
|
+
from comtypes.server.register import (
|
|
14
|
+
FrozenRegistryEntries,
|
|
15
|
+
InterpRegistryEntries,
|
|
16
|
+
Registrar,
|
|
17
|
+
_delete_key,
|
|
18
|
+
_get_serverdll,
|
|
19
|
+
)
|
|
14
20
|
|
|
15
21
|
HKCR = winreg.HKEY_CLASSES_ROOT
|
|
16
22
|
MULTI_SZ = winreg.REG_MULTI_SZ
|
|
17
23
|
SZ = winreg.REG_SZ
|
|
18
24
|
|
|
25
|
+
ERROR_ACCESS_DENIED = 5
|
|
26
|
+
ERROR_FILE_NOT_FOUND = 2
|
|
19
27
|
|
|
28
|
+
|
|
29
|
+
@mock.patch.object(register, "SHDeleteKey")
|
|
30
|
+
@mock.patch.object(register, "winreg")
|
|
31
|
+
class Test_delete_key(ut.TestCase):
|
|
32
|
+
def test_calls_sh_deletekey_if_forced(self, _winreg, _sh_deletekey):
|
|
33
|
+
_delete_key(123, "subkey", force=True)
|
|
34
|
+
_winreg.DeleteKey.assert_not_called()
|
|
35
|
+
_sh_deletekey.assert_called_once_with(123, "subkey")
|
|
36
|
+
|
|
37
|
+
def test_calls_winreg_deletekey_if_not_forced(self, _winreg, _sh_deletekey):
|
|
38
|
+
_delete_key(123, "subkey", force=False)
|
|
39
|
+
_winreg.DeleteKey.assert_called_once_with(123, "subkey")
|
|
40
|
+
_sh_deletekey.assert_not_called()
|
|
41
|
+
|
|
42
|
+
def test_ignores_error_on_sh_deletekey(self, _winreg, _sh_deletekey):
|
|
43
|
+
err = OSError(ERROR_FILE_NOT_FOUND, "msg", "filename", ERROR_FILE_NOT_FOUND)
|
|
44
|
+
_sh_deletekey.side_effect = err
|
|
45
|
+
_delete_key(123, "subkey", force=True)
|
|
46
|
+
_winreg.DeleteKey.assert_not_called()
|
|
47
|
+
_sh_deletekey.assert_called_once_with(123, "subkey")
|
|
48
|
+
|
|
49
|
+
def test_ignores_error_on_winreg_deletekey(self, _winreg, _sh_deletekey):
|
|
50
|
+
err = OSError(ERROR_FILE_NOT_FOUND, "msg", "filename", ERROR_FILE_NOT_FOUND)
|
|
51
|
+
_winreg.DeleteKey.side_effect = err
|
|
52
|
+
_delete_key(123, "subkey", force=False)
|
|
53
|
+
_winreg.DeleteKey.assert_called_once_with(123, "subkey")
|
|
54
|
+
_sh_deletekey.assert_not_called()
|
|
55
|
+
|
|
56
|
+
def test_not_ignores_winerror_on_sh_deletekey(self, _winreg, _sh_deletekey):
|
|
57
|
+
err = OSError(ERROR_ACCESS_DENIED, "msg", "filename", ERROR_ACCESS_DENIED)
|
|
58
|
+
_sh_deletekey.side_effect = err
|
|
59
|
+
with self.assertRaises(OSError) as e:
|
|
60
|
+
_delete_key(123, "subkey", force=True)
|
|
61
|
+
self.assertEqual(e.exception.winerror, ERROR_ACCESS_DENIED)
|
|
62
|
+
_winreg.DeleteKey.assert_not_called()
|
|
63
|
+
_sh_deletekey.assert_called_once_with(123, "subkey")
|
|
64
|
+
|
|
65
|
+
def test_not_ignores_winerror_on_winreg_deletekey(self, _winreg, _sh_deletekey):
|
|
66
|
+
err = OSError(ERROR_ACCESS_DENIED, "msg", "filename", ERROR_ACCESS_DENIED)
|
|
67
|
+
_winreg.DeleteKey.side_effect = err
|
|
68
|
+
with self.assertRaises(OSError) as e:
|
|
69
|
+
_delete_key(123, "subkey", force=False)
|
|
70
|
+
self.assertEqual(e.exception.winerror, ERROR_ACCESS_DENIED)
|
|
71
|
+
_winreg.DeleteKey.assert_called_once_with(123, "subkey")
|
|
72
|
+
_sh_deletekey.assert_not_called()
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@mock.patch.object(register, "winreg")
|
|
20
76
|
class Test_Registrar_nodebug(ut.TestCase):
|
|
21
|
-
@mock.patch.object(register, "winreg")
|
|
22
77
|
def test_calls_openkey_and_deletekey(self, _winreg):
|
|
23
|
-
_winreg.HKEY_CLASSES_ROOT = HKCR
|
|
24
78
|
hkey = mock.Mock(spec=winreg.HKEYType)
|
|
25
79
|
_winreg.OpenKey.return_value = hkey
|
|
26
80
|
reg_clsid = GUID.create_new()
|
|
@@ -33,10 +87,7 @@ class Test_Registrar_nodebug(ut.TestCase):
|
|
|
33
87
|
_winreg.OpenKey.assert_called_once_with(HKCR, rf"CLSID\{reg_clsid}")
|
|
34
88
|
_winreg.DeleteKey.assert_called_once_with(hkey, "Logging")
|
|
35
89
|
|
|
36
|
-
@mock.patch.object(register, "winreg")
|
|
37
90
|
def test_ignores_winerror(self, _winreg):
|
|
38
|
-
_winreg.HKEY_CLASSES_ROOT = HKCR
|
|
39
|
-
ERROR_FILE_NOT_FOUND = 2
|
|
40
91
|
err = OSError(ERROR_FILE_NOT_FOUND, "msg", "filename", ERROR_FILE_NOT_FOUND)
|
|
41
92
|
_winreg.OpenKey.side_effect = err
|
|
42
93
|
reg_clsid = GUID.create_new()
|
|
@@ -49,12 +100,9 @@ class Test_Registrar_nodebug(ut.TestCase):
|
|
|
49
100
|
_winreg.OpenKey.assert_called_once_with(HKCR, rf"CLSID\{reg_clsid}")
|
|
50
101
|
_winreg.DeleteKey.assert_not_called()
|
|
51
102
|
|
|
52
|
-
@mock.patch.object(register, "winreg")
|
|
53
103
|
def test_not_ignores_winerror(self, _winreg):
|
|
54
|
-
_winreg.HKEY_CLASSES_ROOT = HKCR
|
|
55
104
|
hkey = mock.Mock(spec=winreg.HKEYType)
|
|
56
105
|
_winreg.OpenKey.return_value = hkey
|
|
57
|
-
ERROR_ACCESS_DENIED = 5
|
|
58
106
|
err = OSError(ERROR_ACCESS_DENIED, "msg", "filename", ERROR_ACCESS_DENIED)
|
|
59
107
|
_winreg.OpenKey.return_value = hkey
|
|
60
108
|
_winreg.DeleteKey.side_effect = err
|
|
@@ -71,10 +119,9 @@ class Test_Registrar_nodebug(ut.TestCase):
|
|
|
71
119
|
_winreg.DeleteKey.assert_called_once_with(hkey, "Logging")
|
|
72
120
|
|
|
73
121
|
|
|
122
|
+
@mock.patch.object(register, "winreg")
|
|
74
123
|
class Test_Registrar_debug(ut.TestCase):
|
|
75
|
-
@mock.patch.object(register, "winreg")
|
|
76
124
|
def test_calls_createkey_and_sets_format(self, _winreg):
|
|
77
|
-
_winreg.HKEY_CLASSES_ROOT = HKCR
|
|
78
125
|
_winreg.REG_MULTI_SZ = MULTI_SZ
|
|
79
126
|
_winreg.REG_SZ = SZ
|
|
80
127
|
hkey = mock.Mock(spec=winreg.HKEYType)
|
|
@@ -97,9 +144,7 @@ class Test_Registrar_debug(ut.TestCase):
|
|
|
97
144
|
],
|
|
98
145
|
)
|
|
99
146
|
|
|
100
|
-
@mock.patch.object(register, "winreg")
|
|
101
147
|
def test_calls_createkey_and_deletes_format(self, _winreg):
|
|
102
|
-
_winreg.HKEY_CLASSES_ROOT = HKCR
|
|
103
148
|
_winreg.REG_MULTI_SZ = MULTI_SZ
|
|
104
149
|
hkey = mock.Mock(spec=winreg.HKEYType)
|
|
105
150
|
_winreg.CreateKey.return_value = hkey
|
|
@@ -117,13 +162,10 @@ class Test_Registrar_debug(ut.TestCase):
|
|
|
117
162
|
)
|
|
118
163
|
_winreg.DeleteValue.assert_called_once_with(hkey, "format")
|
|
119
164
|
|
|
120
|
-
@mock.patch.object(register, "winreg")
|
|
121
165
|
def test_calls_createkey_and_ignores_errors_on_deleting(self, _winreg):
|
|
122
|
-
_winreg.HKEY_CLASSES_ROOT = HKCR
|
|
123
166
|
_winreg.REG_MULTI_SZ = MULTI_SZ
|
|
124
167
|
hkey = mock.Mock(spec=winreg.HKEYType)
|
|
125
168
|
_winreg.CreateKey.return_value = hkey
|
|
126
|
-
ERROR_FILE_NOT_FOUND = 2
|
|
127
169
|
err = OSError(ERROR_FILE_NOT_FOUND, "msg", "filename", ERROR_FILE_NOT_FOUND)
|
|
128
170
|
_winreg.DeleteValue.side_effect = err
|
|
129
171
|
levels = ["lv=DEBUG"]
|
|
@@ -140,13 +182,10 @@ class Test_Registrar_debug(ut.TestCase):
|
|
|
140
182
|
)
|
|
141
183
|
_winreg.DeleteValue.assert_called_once_with(hkey, "format")
|
|
142
184
|
|
|
143
|
-
@mock.patch.object(register, "winreg")
|
|
144
185
|
def test_calls_createkey_and_not_ignores_errors_on_deleting(self, _winreg):
|
|
145
|
-
_winreg.HKEY_CLASSES_ROOT = HKCR
|
|
146
186
|
_winreg.REG_MULTI_SZ = MULTI_SZ
|
|
147
187
|
hkey = mock.Mock(spec=winreg.HKEYType)
|
|
148
188
|
_winreg.CreateKey.return_value = hkey
|
|
149
|
-
ERROR_ACCESS_DENIED = 5
|
|
150
189
|
err = OSError(ERROR_ACCESS_DENIED, "msg", "filename", ERROR_ACCESS_DENIED)
|
|
151
190
|
_winreg.DeleteValue.side_effect = err
|
|
152
191
|
levels = ["lv=DEBUG"]
|
|
@@ -191,24 +230,17 @@ class Test_Registrar_unregister(ut.TestCase):
|
|
|
191
230
|
|
|
192
231
|
|
|
193
232
|
class Test_get_serverdll(ut.TestCase):
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
self.assertEqual(handle, hModule)
|
|
206
|
-
buf_type = type(ctypes.create_string_buffer(260))
|
|
207
|
-
self.assertIsInstance(lpFilename, buf_type)
|
|
208
|
-
self.assertEqual(260, nSize)
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
class Test_NonFrozen_RegistryEntries(ut.TestCase):
|
|
233
|
+
@mock.patch.object(register, "GetModuleFileName")
|
|
234
|
+
def test_frozen(self, GetModuleFileName):
|
|
235
|
+
handle, dll_path = 1234, r"path\to\frozen.dll"
|
|
236
|
+
GetModuleFileName.return_value = dll_path
|
|
237
|
+
self.assertEqual(dll_path, _get_serverdll(handle))
|
|
238
|
+
(((hmodule, maxsize), _),) = GetModuleFileName.call_args_list
|
|
239
|
+
self.assertEqual(handle, hmodule)
|
|
240
|
+
self.assertEqual(MAX_PATH, maxsize)
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
class Test_InterpRegistryEntries(ut.TestCase):
|
|
212
244
|
def test_reg_clsid(self):
|
|
213
245
|
reg_clsid = GUID.create_new()
|
|
214
246
|
|
|
@@ -216,7 +248,7 @@ class Test_NonFrozen_RegistryEntries(ut.TestCase):
|
|
|
216
248
|
_reg_clsid_ = reg_clsid
|
|
217
249
|
|
|
218
250
|
expected = [(HKCR, rf"CLSID\{reg_clsid}", "", "")]
|
|
219
|
-
self.assertEqual(expected, list(
|
|
251
|
+
self.assertEqual(expected, list(InterpRegistryEntries(Cls)))
|
|
220
252
|
|
|
221
253
|
def test_reg_desc(self):
|
|
222
254
|
reg_clsid = GUID.create_new()
|
|
@@ -227,7 +259,7 @@ class Test_NonFrozen_RegistryEntries(ut.TestCase):
|
|
|
227
259
|
_reg_desc_ = reg_desc
|
|
228
260
|
|
|
229
261
|
expected = [(HKCR, rf"CLSID\{reg_clsid}", "", reg_desc)]
|
|
230
|
-
self.assertEqual(expected, list(
|
|
262
|
+
self.assertEqual(expected, list(InterpRegistryEntries(Cls)))
|
|
231
263
|
|
|
232
264
|
def test_reg_novers_progid(self):
|
|
233
265
|
reg_clsid = GUID.create_new()
|
|
@@ -238,7 +270,7 @@ class Test_NonFrozen_RegistryEntries(ut.TestCase):
|
|
|
238
270
|
_reg_novers_progid_ = reg_novers_progid
|
|
239
271
|
|
|
240
272
|
expected = [(HKCR, rf"CLSID\{reg_clsid}", "", "Lib Server")]
|
|
241
|
-
self.assertEqual(expected, list(
|
|
273
|
+
self.assertEqual(expected, list(InterpRegistryEntries(Cls)))
|
|
242
274
|
|
|
243
275
|
def test_progid(self):
|
|
244
276
|
reg_clsid = GUID.create_new()
|
|
@@ -254,7 +286,7 @@ class Test_NonFrozen_RegistryEntries(ut.TestCase):
|
|
|
254
286
|
(HKCR, reg_progid, "", "Lib Server 1"),
|
|
255
287
|
(HKCR, rf"{reg_progid}\CLSID", "", str(reg_clsid)),
|
|
256
288
|
]
|
|
257
|
-
self.assertEqual(expected, list(
|
|
289
|
+
self.assertEqual(expected, list(InterpRegistryEntries(Cls)))
|
|
258
290
|
|
|
259
291
|
def test_reg_progid_reg_desc(self):
|
|
260
292
|
reg_clsid = GUID.create_new()
|
|
@@ -272,7 +304,7 @@ class Test_NonFrozen_RegistryEntries(ut.TestCase):
|
|
|
272
304
|
(HKCR, reg_progid, "", "description for testing"),
|
|
273
305
|
(HKCR, rf"{reg_progid}\CLSID", "", str(reg_clsid)),
|
|
274
306
|
]
|
|
275
|
-
self.assertEqual(expected, list(
|
|
307
|
+
self.assertEqual(expected, list(InterpRegistryEntries(Cls)))
|
|
276
308
|
|
|
277
309
|
def test_reg_progid_reg_novers_progid(self):
|
|
278
310
|
reg_clsid = GUID.create_new()
|
|
@@ -295,7 +327,7 @@ class Test_NonFrozen_RegistryEntries(ut.TestCase):
|
|
|
295
327
|
(HKCR, rf"{reg_novers_progid}\CurVer", "", "Lib.Server.1"),
|
|
296
328
|
(HKCR, rf"{reg_novers_progid}\CLSID", "", str(reg_clsid)),
|
|
297
329
|
]
|
|
298
|
-
self.assertEqual(expected, list(
|
|
330
|
+
self.assertEqual(expected, list(InterpRegistryEntries(Cls)))
|
|
299
331
|
|
|
300
332
|
def test_local_server(self):
|
|
301
333
|
reg_clsid = GUID.create_new()
|
|
@@ -311,7 +343,7 @@ class Test_NonFrozen_RegistryEntries(ut.TestCase):
|
|
|
311
343
|
(HKCR, clsid_sub, "", ""),
|
|
312
344
|
(HKCR, local_srv_sub, "", f"{sys.executable} {__file__}"),
|
|
313
345
|
]
|
|
314
|
-
self.assertEqual(expected, list(
|
|
346
|
+
self.assertEqual(expected, list(InterpRegistryEntries(Cls)))
|
|
315
347
|
|
|
316
348
|
def test_inproc_server(self):
|
|
317
349
|
reg_clsid = GUID.create_new()
|
|
@@ -330,7 +362,7 @@ class Test_NonFrozen_RegistryEntries(ut.TestCase):
|
|
|
330
362
|
(HKCR, inproc_srv_sub, "PythonClass", full_classname),
|
|
331
363
|
(HKCR, inproc_srv_sub, "PythonPath", os.path.dirname(__file__)),
|
|
332
364
|
]
|
|
333
|
-
self.assertEqual(expected, list(
|
|
365
|
+
self.assertEqual(expected, list(InterpRegistryEntries(Cls)))
|
|
334
366
|
|
|
335
367
|
def test_inproc_server_reg_threading(self):
|
|
336
368
|
reg_clsid = GUID.create_new()
|
|
@@ -352,7 +384,7 @@ class Test_NonFrozen_RegistryEntries(ut.TestCase):
|
|
|
352
384
|
(HKCR, inproc_srv_sub, "PythonPath", os.path.dirname(__file__)),
|
|
353
385
|
(HKCR, inproc_srv_sub, "ThreadingModel", reg_threading),
|
|
354
386
|
]
|
|
355
|
-
self.assertEqual(expected, list(
|
|
387
|
+
self.assertEqual(expected, list(InterpRegistryEntries(Cls)))
|
|
356
388
|
|
|
357
389
|
def test_reg_typelib(self):
|
|
358
390
|
reg_clsid = GUID.create_new()
|
|
@@ -367,7 +399,7 @@ class Test_NonFrozen_RegistryEntries(ut.TestCase):
|
|
|
367
399
|
(HKCR, rf"CLSID\{reg_clsid}", "", ""),
|
|
368
400
|
(HKCR, rf"CLSID\{reg_clsid}\Typelib", "", libid),
|
|
369
401
|
]
|
|
370
|
-
self.assertEqual(expected, list(
|
|
402
|
+
self.assertEqual(expected, list(InterpRegistryEntries(Cls)))
|
|
371
403
|
|
|
372
404
|
def test_all_entries(self):
|
|
373
405
|
reg_clsid = GUID.create_new()
|
|
@@ -408,34 +440,17 @@ class Test_NonFrozen_RegistryEntries(ut.TestCase):
|
|
|
408
440
|
(HKCR, inproc_srv_sub, "ThreadingModel", reg_threading),
|
|
409
441
|
(HKCR, rf"{clsid_sub}\Typelib", "", libid),
|
|
410
442
|
]
|
|
411
|
-
self.assertEqual(expected, list(
|
|
443
|
+
self.assertEqual(expected, list(InterpRegistryEntries(Cls)))
|
|
412
444
|
|
|
413
445
|
|
|
414
|
-
class
|
|
415
|
-
|
|
416
|
-
def test_local_dll(self, _sys):
|
|
417
|
-
_sys.mock_add_spec(["executable", "frozen"])
|
|
418
|
-
_sys.executable = sys.executable
|
|
419
|
-
_sys.frozen = "dll"
|
|
420
|
-
reg_clsid = GUID.create_new()
|
|
421
|
-
reg_clsctx = comtypes.CLSCTX_LOCAL_SERVER
|
|
446
|
+
class Test_FrozenRegistryEntries(ut.TestCase):
|
|
447
|
+
SERVERDLL = r"my\target\server.dll"
|
|
422
448
|
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
clsid_sub = rf"CLSID\{reg_clsid}"
|
|
428
|
-
expected = [
|
|
429
|
-
(HKCR, clsid_sub, "", ""),
|
|
430
|
-
(HKCR, rf"{clsid_sub}\LocalServer32", "", sys.executable),
|
|
431
|
-
]
|
|
432
|
-
self.assertEqual(expected, list(RegistryEntries(Cls)))
|
|
449
|
+
# We do not test the scenario where `frozen` is `'dll'` but
|
|
450
|
+
# `frozendllhandle` is `None`, as it is not a situation
|
|
451
|
+
# we anticipate.
|
|
433
452
|
|
|
434
|
-
|
|
435
|
-
def test_local_frozendllhandle(self, _sys):
|
|
436
|
-
_sys.mock_add_spec(["frozen", "frozendllhandle"])
|
|
437
|
-
_sys.frozen = "dll"
|
|
438
|
-
_sys.frozendllhandle = 1234
|
|
453
|
+
def test_local_dll(self):
|
|
439
454
|
reg_clsid = GUID.create_new()
|
|
440
455
|
reg_clsctx = comtypes.CLSCTX_LOCAL_SERVER
|
|
441
456
|
|
|
@@ -443,53 +458,30 @@ class Test_Frozen_RegistryEntries(ut.TestCase):
|
|
|
443
458
|
_reg_clsid_ = reg_clsid
|
|
444
459
|
_reg_clsctx_ = reg_clsctx
|
|
445
460
|
|
|
461
|
+
# In such cases, the server does not start because the
|
|
462
|
+
# InprocServer32/LocalServer32 keys are not registered.
|
|
446
463
|
expected = [(HKCR, rf"CLSID\{reg_clsid}", "", "")]
|
|
447
|
-
|
|
464
|
+
entries = FrozenRegistryEntries(Cls, frozen="dll", frozendllhandle=1234)
|
|
465
|
+
self.assertEqual(expected, list(entries))
|
|
448
466
|
|
|
449
|
-
|
|
450
|
-
def test_inproc_windows_exe(self, _sys):
|
|
451
|
-
_sys.mock_add_spec(["frozen"])
|
|
452
|
-
_sys.frozen = "windows_exe"
|
|
467
|
+
def test_local_windows_exe(self):
|
|
453
468
|
reg_clsid = GUID.create_new()
|
|
454
|
-
reg_clsctx = comtypes.
|
|
455
|
-
|
|
456
|
-
class Cls:
|
|
457
|
-
_reg_clsid_ = reg_clsid
|
|
458
|
-
_reg_clsctx_ = reg_clsctx
|
|
459
|
-
|
|
460
|
-
expected = [(HKCR, rf"CLSID\{reg_clsid}", "", "")]
|
|
461
|
-
self.assertEqual(expected, list(RegistryEntries(Cls)))
|
|
462
|
-
|
|
463
|
-
@mock.patch.object(register, "_get_serverdll", lambda: r"my\target\server.dll")
|
|
464
|
-
@mock.patch.object(register, "sys")
|
|
465
|
-
def test_inproc_dll_frozendllhandle_clsid_to_class(self, _sys):
|
|
466
|
-
_sys.mock_add_spec(["frozen", "frozendllhandle"])
|
|
467
|
-
_sys.frozen = "dll"
|
|
468
|
-
_sys.frozendllhandle = 1234
|
|
469
|
-
reg_clsid = GUID.create_new()
|
|
470
|
-
reg_clsctx = comtypes.CLSCTX_INPROC_SERVER
|
|
469
|
+
reg_clsctx = comtypes.CLSCTX_LOCAL_SERVER
|
|
471
470
|
|
|
472
471
|
class Cls:
|
|
473
472
|
_reg_clsid_ = reg_clsid
|
|
474
473
|
_reg_clsctx_ = reg_clsctx
|
|
475
474
|
|
|
476
|
-
clsid_sub = rf"CLSID\{reg_clsid}"
|
|
477
|
-
inproc_srv_sub = rf"{clsid_sub}\InprocServer32"
|
|
478
475
|
expected = [
|
|
479
|
-
(HKCR,
|
|
480
|
-
(HKCR,
|
|
476
|
+
(HKCR, rf"CLSID\{reg_clsid}", "", ""),
|
|
477
|
+
(HKCR, rf"CLSID\{reg_clsid}\LocalServer32", "", sys.executable),
|
|
481
478
|
]
|
|
479
|
+
self.assertEqual(
|
|
480
|
+
expected, list(FrozenRegistryEntries(Cls, frozen="windows_exe"))
|
|
481
|
+
)
|
|
482
482
|
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
self.assertEqual(expected, list(RegistryEntries(Cls)))
|
|
486
|
-
|
|
487
|
-
@mock.patch.object(register, "_get_serverdll", lambda: r"my\target\server.dll")
|
|
488
|
-
@mock.patch.object(register, "sys")
|
|
489
|
-
def test_inproc_dll(self, _sys):
|
|
490
|
-
_sys.mock_add_spec(["frozen", "modules"])
|
|
491
|
-
_sys.frozen = "dll"
|
|
492
|
-
_sys.modules = sys.modules
|
|
483
|
+
@mock.patch.object(register, "_get_serverdll", return_value=SERVERDLL)
|
|
484
|
+
def test_inproc_dll(self, get_serverdll):
|
|
493
485
|
reg_clsid = GUID.create_new()
|
|
494
486
|
reg_clsctx = comtypes.CLSCTX_INPROC_SERVER
|
|
495
487
|
|
|
@@ -499,21 +491,17 @@ class Test_Frozen_RegistryEntries(ut.TestCase):
|
|
|
499
491
|
|
|
500
492
|
clsid_sub = rf"CLSID\{reg_clsid}"
|
|
501
493
|
inproc_srv_sub = rf"{clsid_sub}\InprocServer32"
|
|
502
|
-
full_classname = f"{__name__}.Cls"
|
|
503
494
|
expected = [
|
|
504
495
|
(HKCR, clsid_sub, "", ""),
|
|
505
|
-
(HKCR, inproc_srv_sub, "",
|
|
506
|
-
(HKCR, inproc_srv_sub, "PythonClass", full_classname),
|
|
507
|
-
(HKCR, inproc_srv_sub, "PythonPath", os.path.dirname(__file__)),
|
|
496
|
+
(HKCR, inproc_srv_sub, "", self.SERVERDLL),
|
|
508
497
|
]
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
_sys.modules = sys.modules
|
|
498
|
+
|
|
499
|
+
entries = FrozenRegistryEntries(Cls, frozen="dll", frozendllhandle=1234)
|
|
500
|
+
self.assertEqual(expected, list(entries))
|
|
501
|
+
get_serverdll.assert_called_once_with(1234)
|
|
502
|
+
|
|
503
|
+
@mock.patch.object(register, "_get_serverdll", return_value=SERVERDLL)
|
|
504
|
+
def test_inproc_reg_threading(self, get_serverdll):
|
|
517
505
|
reg_clsid = GUID.create_new()
|
|
518
506
|
reg_threading = "Both"
|
|
519
507
|
reg_clsctx = comtypes.CLSCTX_INPROC_SERVER
|
|
@@ -525,12 +513,13 @@ class Test_Frozen_RegistryEntries(ut.TestCase):
|
|
|
525
513
|
|
|
526
514
|
clsid_sub = rf"CLSID\{reg_clsid}"
|
|
527
515
|
inproc_srv_sub = rf"{clsid_sub}\InprocServer32"
|
|
528
|
-
full_classname = f"{__name__}.Cls"
|
|
529
516
|
expected = [
|
|
530
517
|
(HKCR, clsid_sub, "", ""),
|
|
531
|
-
(HKCR, inproc_srv_sub, "",
|
|
532
|
-
(HKCR, inproc_srv_sub, "PythonClass", full_classname),
|
|
533
|
-
(HKCR, inproc_srv_sub, "PythonPath", os.path.dirname(__file__)),
|
|
518
|
+
(HKCR, inproc_srv_sub, "", self.SERVERDLL),
|
|
534
519
|
(HKCR, inproc_srv_sub, "ThreadingModel", reg_threading),
|
|
535
520
|
]
|
|
536
|
-
self.assertEqual(
|
|
521
|
+
self.assertEqual(
|
|
522
|
+
expected,
|
|
523
|
+
list(FrozenRegistryEntries(Cls, frozen="dll", frozendllhandle=1234)),
|
|
524
|
+
)
|
|
525
|
+
get_serverdll.assert_called_once_with(1234)
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
from pathlib import Path
|
|
2
1
|
import tempfile
|
|
3
2
|
import unittest as ut
|
|
3
|
+
from pathlib import Path
|
|
4
4
|
|
|
5
|
-
from comtypes import CoCreateInstance, GUID, shelllink
|
|
6
5
|
import comtypes.hresult
|
|
6
|
+
from comtypes import GUID, CoCreateInstance, shelllink
|
|
7
7
|
from comtypes.persist import IPersistFile
|
|
8
8
|
|
|
9
|
-
|
|
10
9
|
CLSID_ShellLink = GUID("{00021401-0000-0000-C000-000000000046}")
|
|
11
10
|
|
|
12
11
|
|
|
@@ -1,19 +1,18 @@
|
|
|
1
|
-
from _ctypes import COMError
|
|
2
|
-
from ctypes import byref, c_ubyte, POINTER
|
|
3
1
|
import contextlib
|
|
4
|
-
from pathlib import Path
|
|
5
2
|
import unittest
|
|
3
|
+
from _ctypes import COMError
|
|
4
|
+
from ctypes import HRESULT, POINTER, OleDLL, byref, c_ubyte
|
|
5
|
+
from ctypes.wintypes import DWORD, PWCHAR
|
|
6
|
+
from pathlib import Path
|
|
6
7
|
|
|
7
8
|
import comtypes
|
|
8
9
|
import comtypes.client
|
|
9
10
|
|
|
10
|
-
|
|
11
11
|
with contextlib.redirect_stdout(None): # supress warnings
|
|
12
12
|
mod = comtypes.client.GetModule("msvidctl.dll")
|
|
13
13
|
|
|
14
14
|
from comtypes.gen.MSVidCtlLib import IStorage
|
|
15
15
|
|
|
16
|
-
|
|
17
16
|
STATFLAG_DEFAULT = 0
|
|
18
17
|
STGC_DEFAULT = 0
|
|
19
18
|
STGM_CREATE = 0x00001000
|
|
@@ -29,6 +28,13 @@ STREAM_SEEK_SET = 0
|
|
|
29
28
|
STG_E_PATHNOTFOUND = -2147287038
|
|
30
29
|
|
|
31
30
|
|
|
31
|
+
_ole32 = OleDLL("ole32")
|
|
32
|
+
|
|
33
|
+
_StgCreateDocfile = _ole32.StgCreateDocfile
|
|
34
|
+
_StgCreateDocfile.argtypes = [PWCHAR, DWORD, DWORD, POINTER(POINTER(IStorage))]
|
|
35
|
+
_StgCreateDocfile.restype = HRESULT
|
|
36
|
+
|
|
37
|
+
|
|
32
38
|
class Test_IStorage(unittest.TestCase):
|
|
33
39
|
CREATE_DOC_FLAG = (
|
|
34
40
|
STGM_DIRECT
|
|
@@ -44,7 +50,7 @@ class Test_IStorage(unittest.TestCase):
|
|
|
44
50
|
|
|
45
51
|
def _create_docfile(self) -> IStorage:
|
|
46
52
|
stg = POINTER(IStorage)()
|
|
47
|
-
|
|
53
|
+
_StgCreateDocfile(None, self.CREATE_DOC_FLAG, 0, byref(stg))
|
|
48
54
|
return stg # type: ignore
|
|
49
55
|
|
|
50
56
|
def test_CreateStream(self):
|
|
@@ -1,23 +1,34 @@
|
|
|
1
1
|
import unittest as ut
|
|
2
|
+
from ctypes import HRESULT, POINTER, OleDLL, byref, c_ubyte, c_ulonglong, pointer
|
|
3
|
+
from ctypes.wintypes import BOOL, HGLOBAL, ULARGE_INTEGER
|
|
2
4
|
|
|
3
|
-
from ctypes import POINTER, byref, c_bool, c_ubyte, c_ulonglong, oledll, pointer
|
|
4
|
-
import comtypes
|
|
5
5
|
import comtypes.client
|
|
6
6
|
|
|
7
7
|
comtypes.client.GetModule("portabledeviceapi.dll")
|
|
8
8
|
from comtypes.gen.PortableDeviceApiLib import IStream
|
|
9
9
|
|
|
10
|
-
|
|
11
10
|
STGC_DEFAULT = 0
|
|
12
11
|
STREAM_SEEK_SET = 0
|
|
13
12
|
STREAM_SEEK_CUR = 1
|
|
14
13
|
STREAM_SEEK_END = 2
|
|
15
14
|
|
|
15
|
+
_ole32 = OleDLL("ole32")
|
|
16
|
+
|
|
17
|
+
_CreateStreamOnHGlobal = _ole32.CreateStreamOnHGlobal
|
|
18
|
+
_CreateStreamOnHGlobal.argtypes = [HGLOBAL, BOOL, POINTER(POINTER(IStream))]
|
|
19
|
+
_CreateStreamOnHGlobal.restype = HRESULT
|
|
20
|
+
|
|
21
|
+
_shlwapi = OleDLL("shlwapi")
|
|
22
|
+
|
|
23
|
+
_IStream_Size = _shlwapi.IStream_Size
|
|
24
|
+
_IStream_Size.argtypes = [POINTER(IStream), POINTER(ULARGE_INTEGER)]
|
|
25
|
+
_IStream_Size.restype = HRESULT
|
|
26
|
+
|
|
16
27
|
|
|
17
28
|
def _create_stream() -> IStream:
|
|
18
29
|
# Create an IStream
|
|
19
30
|
stream = POINTER(IStream)() # type: ignore
|
|
20
|
-
|
|
31
|
+
_CreateStreamOnHGlobal(None, True, byref(stream))
|
|
21
32
|
return stream # type: ignore
|
|
22
33
|
|
|
23
34
|
|
|
@@ -92,7 +103,7 @@ class Test_SetSize(ut.TestCase):
|
|
|
92
103
|
stream = _create_stream()
|
|
93
104
|
stream.SetSize(42)
|
|
94
105
|
pui = pointer(c_ulonglong())
|
|
95
|
-
|
|
106
|
+
_IStream_Size(stream, pui)
|
|
96
107
|
self.assertEqual(pui.contents.value, 42)
|
|
97
108
|
|
|
98
109
|
|
|
@@ -5,12 +5,11 @@ from comtypes.tools.codegenerator import typeannotator
|
|
|
5
5
|
from comtypes.tools.tlbparser import (
|
|
6
6
|
BSTR_type,
|
|
7
7
|
HRESULT_type,
|
|
8
|
-
VARIANT_type,
|
|
9
8
|
VARIANT_BOOL_type,
|
|
9
|
+
VARIANT_type,
|
|
10
10
|
void_type,
|
|
11
11
|
)
|
|
12
12
|
|
|
13
|
-
|
|
14
13
|
iunknown_type = typedesc.ComInterface(
|
|
15
14
|
"IUnknown", None, "{00000000-0000-0000-C000-000000000046}", ["hidden"], None
|
|
16
15
|
)
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import
|
|
1
|
+
import ctypes
|
|
2
|
+
import sys
|
|
2
3
|
import unittest
|
|
3
|
-
from ctypes import
|
|
4
|
+
from ctypes.wintypes import MAX_PATH
|
|
5
|
+
|
|
4
6
|
from comtypes import GUID, COMError
|
|
5
|
-
from comtypes.automation import DISPATCH_METHOD
|
|
6
7
|
from comtypes.typeinfo import (
|
|
7
|
-
|
|
8
|
+
TKIND_DISPATCH,
|
|
9
|
+
TKIND_INTERFACE,
|
|
10
|
+
GetModuleFileName,
|
|
8
11
|
LoadRegTypeLib,
|
|
12
|
+
LoadTypeLibEx,
|
|
9
13
|
QueryPathOfRegTypeLib,
|
|
10
|
-
TKIND_INTERFACE,
|
|
11
|
-
TKIND_DISPATCH,
|
|
12
|
-
TKIND_ENUM,
|
|
13
14
|
)
|
|
14
15
|
|
|
15
16
|
|
|
@@ -94,5 +95,33 @@ class Test(unittest.TestCase):
|
|
|
94
95
|
self.assertEqual(guid, ti.GetTypeAttr().guid)
|
|
95
96
|
|
|
96
97
|
|
|
98
|
+
class Test_GetModuleFileName(unittest.TestCase):
|
|
99
|
+
def test_null_handler(self):
|
|
100
|
+
self.assertEqual(GetModuleFileName(None, MAX_PATH), sys.executable)
|
|
101
|
+
|
|
102
|
+
def test_loaded_module_handle(self):
|
|
103
|
+
import _ctypes
|
|
104
|
+
|
|
105
|
+
dll_path = _ctypes.__file__
|
|
106
|
+
hmodule = ctypes.WinDLL(dll_path)._handle
|
|
107
|
+
self.assertEqual(GetModuleFileName(hmodule, MAX_PATH), dll_path)
|
|
108
|
+
|
|
109
|
+
def test_invalid_handle(self):
|
|
110
|
+
with self.assertRaises(OSError) as ce:
|
|
111
|
+
GetModuleFileName(1, MAX_PATH)
|
|
112
|
+
ERROR_MOD_NOT_FOUND = 126
|
|
113
|
+
self.assertEqual(ce.exception.winerror, ERROR_MOD_NOT_FOUND)
|
|
114
|
+
|
|
115
|
+
def test_invalid_nsize(self):
|
|
116
|
+
import _ctypes
|
|
117
|
+
|
|
118
|
+
dll_path = _ctypes.__file__
|
|
119
|
+
hmodule = ctypes.WinDLL(dll_path)._handle
|
|
120
|
+
with self.assertRaises(OSError) as ce:
|
|
121
|
+
GetModuleFileName(hmodule, 0)
|
|
122
|
+
ERROR_INSUFFICIENT_BUFFER = 122
|
|
123
|
+
self.assertEqual(ce.exception.winerror, ERROR_INSUFFICIENT_BUFFER)
|
|
124
|
+
|
|
125
|
+
|
|
97
126
|
if __name__ == "__main__":
|
|
98
127
|
unittest.main()
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import
|
|
1
|
+
import os
|
|
2
|
+
import unittest
|
|
2
3
|
from copy import copy
|
|
3
4
|
from ctypes import *
|
|
4
|
-
|
|
5
|
+
|
|
6
|
+
from comtypes.client import CreateObject, GetModule
|
|
7
|
+
from comtypes.GUID import _CoTaskMemFree
|
|
5
8
|
from comtypes.patcher import Patch
|
|
6
9
|
|
|
7
10
|
# ./urlhist.tlb was downloaded somewhere from the internet (?)
|
|
@@ -23,8 +26,8 @@ class _(object):
|
|
|
23
26
|
for n, _ in self._fields_:
|
|
24
27
|
setattr(result, n, getattr(self, n))
|
|
25
28
|
url, title = self.pwcsUrl, self.pwcsTitle
|
|
26
|
-
|
|
27
|
-
|
|
29
|
+
_CoTaskMemFree(cast_field(self, "pwcsUrl", c_void_p))
|
|
30
|
+
_CoTaskMemFree(cast_field(self, "pwcsTitle", c_void_p))
|
|
28
31
|
return result
|
|
29
32
|
|
|
30
33
|
|
|
@@ -66,7 +66,8 @@ class VariantTestCase(unittest.TestCase):
|
|
|
66
66
|
|
|
67
67
|
missing = VARIANT.missing
|
|
68
68
|
self.assertEqual(missing.vt, VT_ERROR)
|
|
69
|
-
self.assertRaises(NotImplementedError
|
|
69
|
+
with self.assertRaises(NotImplementedError):
|
|
70
|
+
missing.value
|
|
70
71
|
|
|
71
72
|
def test_com_refcounts(self):
|
|
72
73
|
# typelib for oleaut32
|
|
@@ -293,9 +294,10 @@ def run_test(rep, msg, func=None, previous={}, results={}):
|
|
|
293
294
|
|
|
294
295
|
|
|
295
296
|
def check_perf(rep=20000):
|
|
296
|
-
from ctypes import
|
|
297
|
-
|
|
297
|
+
from ctypes import byref, c_int
|
|
298
|
+
|
|
298
299
|
import comtypes.automation
|
|
300
|
+
from comtypes.automation import VARIANT
|
|
299
301
|
|
|
300
302
|
print(comtypes.automation)
|
|
301
303
|
variable = c_int()
|