1
0
mirror of https://github.com/EDCD/EDMarketConnector.git synced 2025-04-19 18:37:39 +03:00

Added more comments to windows DDE

# Conflicts:
#	protocol.py
This commit is contained in:
Athanasius 2021-03-22 14:25:32 +00:00
parent 96ac23a6eb
commit 67d41d63dc

@ -3,10 +3,10 @@
import sys import sys
import threading import threading
from typing import Optional
import urllib.error import urllib.error
import urllib.parse import urllib.parse
import urllib.request import urllib.request
from typing import Optional
from EDMCLogging import get_main_logger from EDMCLogging import get_main_logger
from config import appname, config from config import appname, config
@ -81,10 +81,12 @@ if sys.platform == 'darwin' and getattr(sys, 'frozen', False):
) )
return self return self
def handleEvent_withReplyEvent_(self, event, replyEvent): def handleEvent_withReplyEvent_(self, event, replyEvent): # noqa: N802 # Required to override
protocolhandler.lasturl = urllib.parse.unquote( protocolhandler.lasturl = urllib.parse.unquote( # type: ignore # Its going to be a DPH in this code
event.paramDescriptorForKeyword_(keyDirectObject).stringValue()).strip() event.paramDescriptorForKeyword_(keyDirectObject).stringValue()
protocolhandler.master.after(ProtocolHandler.POLL, protocolhandler.poll) ).strip()
protocolhandler.master.after(DarwinProtocolHandler.POLL, protocolhandler.poll) # type: ignore
elif sys.platform == 'win32' and getattr(sys, 'frozen', False) and not is_wine and not config.auth_force_localserver: elif sys.platform == 'win32' and getattr(sys, 'frozen', False) and not is_wine and not config.auth_force_localserver:
@ -153,6 +155,8 @@ elif sys.platform == 'win32' and getattr(sys, 'frozen', False) and not is_wine a
GlobalUnlock.argtypes = [HGLOBAL] GlobalUnlock.argtypes = [HGLOBAL]
GlobalUnlock.restype = BOOL GlobalUnlock.restype = BOOL
# Windows Message handler stuff (IPC)
# https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms633573(v=vs.85)
@WINFUNCTYPE(c_long, HWND, UINT, WPARAM, LPARAM) @WINFUNCTYPE(c_long, HWND, UINT, WPARAM, LPARAM)
def WndProc(hwnd: HWND, message: UINT, wParam, lParam): # noqa: N803 N802 def WndProc(hwnd: HWND, message: UINT, wParam, lParam): # noqa: N803 N802
""" """
@ -166,6 +170,7 @@ elif sys.platform == 'win32' and getattr(sys, 'frozen', False) and not is_wine a
""" """
if message != WM_DDE_INITIATE: if message != WM_DDE_INITIATE:
# Not a DDE init message, bail and tell windows to do the default # Not a DDE init message, bail and tell windows to do the default
# https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-defwindowproca?redirectedfrom=MSDN
return DefWindowProc(hwnd, message, wParam, lParam) return DefWindowProc(hwnd, message, wParam, lParam)
service = create_unicode_buffer(256) service = create_unicode_buffer(256)
@ -192,6 +197,7 @@ elif sys.platform == 'win32' and getattr(sys, 'frozen', False) and not is_wine a
SendMessage( SendMessage(
wParam, WM_DDE_ACK, hwnd, PackDDElParam(WM_DDE_ACK, GlobalAddAtom(appname), GlobalAddAtom('System')) wParam, WM_DDE_ACK, hwnd, PackDDElParam(WM_DDE_ACK, GlobalAddAtom(appname), GlobalAddAtom('System'))
) )
return 0 return 0
class WindowsProtocolHandler(GenericProtocolHandler): class WindowsProtocolHandler(GenericProtocolHandler):
@ -235,48 +241,52 @@ elif sys.platform == 'win32' and getattr(sys, 'frozen', False) and not is_wine a
wndclass.lpszMenuName = None wndclass.lpszMenuName = None
wndclass.lpszClassName = 'DDEServer' wndclass.lpszClassName = 'DDEServer'
if RegisterClass(byref(wndclass)): if not RegisterClass(byref(wndclass)):
hwnd = CreateWindowEx( print('Failed to register Dynamic Data Exchange for cAPI')
0, return
wndclass.lpszClassName,
"DDE Server",
0,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
self.master.winfo_id(), # Don't use HWND_MESSAGE since the window won't get DDE broadcasts
None,
wndclass.hInstance,
None
)
msg = MSG() # https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-createwindowexw
while GetMessage(byref(msg), None, 0, 0) != 0: hwnd = CreateWindowEx(
logger.trace(f'DDE message of type: {msg.message}') 0, # dwExStyle
if msg.message == WM_DDE_EXECUTE: wndclass.lpszClassName, # lpClassName
args = wstring_at(GlobalLock(msg.lParam)).strip() "DDE Server", # lpWindowName
GlobalUnlock(msg.lParam) 0, # dwStyle
if args.lower().startswith('open("') and args.endswith('")'): CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, # X, Y, nWidth, nHeight
logger.trace(f'args are: {args}') self.master.winfo_id(), # hWndParent # Don't use HWND_MESSAGE since the window won't get DDE broadcasts
url = urllib.parse.unquote(args[6:-2]).strip() None, # hMenu
logger.trace(f'Parsed url: {url}') wndclass.hInstance, # hInstance
if url.startswith(self.redirect): None # lpParam
logger.debug(f'Message starts with {self.redirect}') )
self.event(url)
SetForegroundWindow(GetParent(self.master.winfo_id())) # raise app window msg = MSG()
PostMessage(msg.wParam, WM_DDE_ACK, hwnd, PackDDElParam(WM_DDE_ACK, 0x80, msg.lParam)) # Calls GetMessageW: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getmessagew
while GetMessage(byref(msg), None, 0, 0) != 0:
if msg.message == WM_DDE_EXECUTE:
# GlobalLock does some sort of "please dont move this?"
# https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-globallock
args = wstring_at(GlobalLock(msg.lParam)).strip()
GlobalUnlock(msg.lParam) # Unlocks the GlobalLock-ed object
else: if args.lower().startswith('open("') and args.endswith('")'):
PostMessage(msg.wParam, WM_DDE_ACK, hwnd, PackDDElParam(WM_DDE_ACK, 0, msg.lParam)) url = urllib.parse.unquote(args[6:-2]).strip()
if url.startswith(self.redirect):
self.event(url)
elif msg.message == WM_DDE_TERMINATE: SetForegroundWindow(GetParent(self.master.winfo_id())) # raise app window
PostMessage(msg.wParam, WM_DDE_TERMINATE, hwnd, 0) # Send back a WM_DDE_ACK. this is _required_ with WM_DDE_EXECUTE
PostMessage(msg.wParam, WM_DDE_ACK, hwnd, PackDDElParam(WM_DDE_ACK, 0x80, msg.lParam))
else: else:
TranslateMessage(byref(msg)) # Send back a WM_DDE_ACK. this is _required_ with WM_DDE_EXECUTE
DispatchMessage(byref(msg)) PostMessage(msg.wParam, WM_DDE_ACK, hwnd, PackDDElParam(WM_DDE_ACK, 0, msg.lParam))
elif msg.message == WM_DDE_TERMINATE:
PostMessage(msg.wParam, WM_DDE_TERMINATE, hwnd, 0)
else:
TranslateMessage(byref(msg)) # "Translates virtual key messages into character messages" ???
DispatchMessage(byref(msg))
else:
print('Failed to register DDE for cAPI')
else: # Linux / Run from source else: # Linux / Run from source