@@ -69,16 +69,16 @@ def event(self, url: str) -> None:
69
69
# This could be false if you use auth_force_edmc_protocol, but then you get to keep the pieces
70
70
assert sys .platform == 'win32'
71
71
# spell-checker: words HBRUSH HICON WPARAM wstring WNDCLASS HMENU HGLOBAL
72
- from ctypes import ( # type: ignore
73
- windll , POINTER , WINFUNCTYPE , Structure , byref , c_long , c_void_p , create_unicode_buffer , wstring_at
72
+ from ctypes import (
73
+ windll , WINFUNCTYPE , Structure , byref , c_long , c_void_p , create_unicode_buffer , wstring_at
74
74
)
75
75
from ctypes .wintypes import (
76
- ATOM , BOOL , DWORD , HBRUSH , HGLOBAL , HICON , HINSTANCE , HMENU , HWND , INT , LPARAM , LPCWSTR , LPMSG , LPVOID , LPWSTR ,
76
+ ATOM , HBRUSH , HICON , HINSTANCE , HWND , INT , LPARAM , LPCWSTR , LPWSTR ,
77
77
MSG , UINT , WPARAM
78
78
)
79
- from win32con import CW_USEDEFAULT
80
79
import win32gui
81
80
import win32con
81
+ import win32api
82
82
83
83
class WNDCLASS (Structure ):
84
84
"""
@@ -101,37 +101,7 @@ class WNDCLASS(Structure):
101
101
('lpszClassName' , LPCWSTR )
102
102
]
103
103
104
-
105
- CreateWindowExW = windll .user32 .CreateWindowExW
106
- CreateWindowExW .argtypes = [DWORD , LPCWSTR , LPCWSTR , DWORD , INT , INT , INT , INT , HWND , HMENU , HINSTANCE , LPVOID ]
107
- CreateWindowExW .restype = HWND
108
- RegisterClassW = windll .user32 .RegisterClassW
109
- RegisterClassW .argtypes = [POINTER (WNDCLASS )]
110
- # DefWindowProcW
111
- # Ref: <https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-defwindowprocw>
112
- # LRESULT DefWindowProcW([in] HWND hWnd,[in] UINT Msg,[in] WPARAM wParam,[in] LPARAM lParam);
113
- # As per example at <https://docs.python.org/3/library/ctypes.html#ctypes.WINFUNCTYPE>
114
-
115
- prototype = WINFUNCTYPE (c_long , HWND , UINT , WPARAM , LPARAM )
116
- paramflags = (1 , "hWnd" ), (1 , "Msg" ), (1 , "wParam" ), (1 , "lParam" )
117
- DefWindowProcW = prototype (("DefWindowProcW" , windll .user32 ), paramflags )
118
-
119
- SetForegroundWindow = windll .user32 .SetForegroundWindow
120
-
121
- # <https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getmessagew>
122
- # NB: Despite 'BOOL' return type, it *can* be >0, 0 or -1, so is actually
123
- # c_long
124
- prototype = WINFUNCTYPE (c_long , LPMSG , HWND , UINT , UINT )
125
- paramflags = (1 , "lpMsg" ), (1 , "hWnd" ), (1 , "wMsgFilterMin" ), (1 , "wMsgFilterMax" )
126
- GetMessageW = prototype (("GetMessageW" , windll .user32 ), paramflags )
127
-
128
104
TranslateMessage = windll .user32 .TranslateMessage
129
- DispatchMessageW = windll .user32 .DispatchMessageW
130
- PostThreadMessageW = windll .user32 .PostThreadMessageW
131
- SendMessageW = windll .user32 .SendMessageW
132
- SendMessageW .argtypes = [HWND , UINT , WPARAM , LPARAM ]
133
- PostMessageW = windll .user32 .PostMessageW
134
- PostMessageW .argtypes = [HWND , UINT , WPARAM , LPARAM ]
135
105
136
106
# https://docs.microsoft.com/en-us/windows/win32/dataxchg/wm-dde-initiate
137
107
WM_DDE_INITIATE = 0x03E0
@@ -148,12 +118,6 @@ class WNDCLASS(Structure):
148
118
GlobalGetAtomNameW = windll .kernel32 .GlobalGetAtomNameW
149
119
GlobalGetAtomNameW .argtypes = [ATOM , LPWSTR , INT ]
150
120
GlobalGetAtomNameW .restype = UINT
151
- GlobalLock = windll .kernel32 .GlobalLock
152
- GlobalLock .argtypes = [HGLOBAL ]
153
- GlobalLock .restype = LPVOID
154
- GlobalUnlock = windll .kernel32 .GlobalUnlock
155
- GlobalUnlock .argtypes = [HGLOBAL ]
156
- GlobalUnlock .restype = BOOL
157
121
158
122
# Windows Message handler stuff (IPC)
159
123
# https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms633573(v=vs.85)
@@ -171,7 +135,7 @@ def WndProc(hwnd: HWND, message: UINT, wParam: WPARAM, lParam: LPARAM) -> c_long
171
135
if message != WM_DDE_INITIATE :
172
136
# Not a DDE init message, bail and tell windows to do the default
173
137
# https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-defwindowproca?redirectedfrom=MSDN
174
- return DefWindowProcW (hwnd , message , wParam , lParam )
138
+ return win32gui . DefWindowProc (hwnd , message , wParam , lParam )
175
139
176
140
service = create_unicode_buffer (256 )
177
141
topic = create_unicode_buffer (256 )
@@ -196,7 +160,7 @@ def WndProc(hwnd: HWND, message: UINT, wParam: WPARAM, lParam: LPARAM) -> c_long
196
160
197
161
if target_is_valid and topic_is_valid :
198
162
# if everything is happy, send an acknowledgement of the DDE request
199
- SendMessageW (
163
+ win32gui . SendMessage (
200
164
wParam , WM_DDE_ACK , hwnd , PackDDElParam (WM_DDE_ACK , GlobalAddAtomW (appname ), GlobalAddAtomW ('System' ))
201
165
)
202
166
@@ -229,7 +193,7 @@ def close(self) -> None:
229
193
thread = self .thread
230
194
if thread :
231
195
self .thread = None
232
- PostThreadMessageW (thread .ident , win32con .WM_QUIT , 0 , 0 )
196
+ win32api . PostThreadMessage (thread .ident , win32con .WM_QUIT , 0 , 0 )
233
197
thread .join () # Wait for it to quit
234
198
235
199
def worker (self ) -> None :
@@ -239,24 +203,25 @@ def worker(self) -> None:
239
203
wndclass .lpfnWndProc = WndProc
240
204
wndclass .cbClsExtra = 0
241
205
wndclass .cbWndExtra = 0
242
- wndclass .hInstance = windll . kernel32 . GetModuleHandleW (0 )
206
+ wndclass .hInstance = win32gui . GetModuleHandle (0 )
243
207
wndclass .hIcon = None
244
208
wndclass .hCursor = None
245
209
wndclass .hbrBackground = None
246
210
wndclass .lpszMenuName = None
247
211
wndclass .lpszClassName = 'DDEServer'
248
212
249
- if not RegisterClassW (byref (wndclass )):
213
+ if not win32gui . RegisterClass (byref (wndclass )):
250
214
print ('Failed to register Dynamic Data Exchange for cAPI' )
251
215
return
252
216
253
217
# https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-createwindowexw
254
- hwnd = CreateWindowExW (
218
+ hwnd = win32gui . CreateWindowEx (
255
219
0 , # dwExStyle
256
220
wndclass .lpszClassName , # lpClassName
257
221
"DDE Server" , # lpWindowName
258
222
0 , # dwStyle
259
- CW_USEDEFAULT , CW_USEDEFAULT , CW_USEDEFAULT , CW_USEDEFAULT , # X, Y, nWidth, nHeight
223
+ # X, Y, nWidth, nHeight
224
+ win32con .CW_USEDEFAULT , win32con .CW_USEDEFAULT , win32con .CW_USEDEFAULT , win32con .CW_USEDEFAULT ,
260
225
self .master .winfo_id (), # hWndParent # Don't use HWND_MESSAGE since the window won't get DDE broadcasts
261
226
None , # hMenu
262
227
wndclass .hInstance , # hInstance
@@ -276,13 +241,13 @@ def worker(self) -> None:
276
241
#
277
242
# But it does actually work. Either getting a non-0 value and
278
243
# entering the loop, or getting 0 and exiting it.
279
- while GetMessageW (byref (msg ), None , 0 , 0 ) != 0 :
244
+ while win32gui . GetMessage (byref (msg ), None , 0 , 0 ) != 0 :
280
245
logger .trace_if ('frontier-auth.windows' , f'DDE message of type: { msg .message } ' )
281
246
if msg .message == WM_DDE_EXECUTE :
282
247
# GlobalLock does some sort of "please dont move this?"
283
248
# https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-globallock
284
- args = wstring_at (GlobalLock (msg .lParam )).strip ()
285
- GlobalUnlock (msg .lParam ) # Unlocks the GlobalLock-ed object
249
+ args = wstring_at (win32gui . GlobalLock (msg .lParam )).strip ()
250
+ win32gui . GlobalUnlock (msg .lParam ) # Unlocks the GlobalLock-ed object
286
251
287
252
if args .lower ().startswith ('open("' ) and args .endswith ('")' ):
288
253
logger .trace_if ('frontier-auth.windows' , f'args are: { args } ' )
@@ -291,20 +256,20 @@ def worker(self) -> None:
291
256
logger .debug (f'Message starts with { self .redirect } ' )
292
257
self .event (url )
293
258
294
- SetForegroundWindow (win32gui .GetParent (self .master .winfo_id ())) # raise app window
259
+ win32gui . SetForegroundWindow (win32gui .GetParent (self .master .winfo_id ())) # raise app window
295
260
# Send back a WM_DDE_ACK. this is _required_ with WM_DDE_EXECUTE
296
- PostMessageW (msg .wParam , WM_DDE_ACK , hwnd , PackDDElParam (WM_DDE_ACK , 0x80 , msg .lParam ))
261
+ win32gui . PostMessage (msg .wParam , WM_DDE_ACK , hwnd , PackDDElParam (WM_DDE_ACK , 0x80 , msg .lParam ))
297
262
298
263
else :
299
264
# Send back a WM_DDE_ACK. this is _required_ with WM_DDE_EXECUTE
300
- PostMessageW (msg .wParam , WM_DDE_ACK , hwnd , PackDDElParam (WM_DDE_ACK , 0 , msg .lParam ))
265
+ win32gui . PostMessage (msg .wParam , WM_DDE_ACK , hwnd , PackDDElParam (WM_DDE_ACK , 0 , msg .lParam ))
301
266
302
267
elif msg .message == WM_DDE_TERMINATE :
303
- PostMessageW (msg .wParam , WM_DDE_TERMINATE , hwnd , 0 )
268
+ win32gui . PostMessage (msg .wParam , WM_DDE_TERMINATE , hwnd , 0 )
304
269
305
270
else :
306
271
TranslateMessage (byref (msg )) # "Translates virtual key messages into character messages" ???
307
- DispatchMessageW (byref (msg ))
272
+ win32gui . DispatchMessage (byref (msg ))
308
273
309
274
310
275
else : # Linux / Run from source
0 commit comments