1
0
mirror of https://github.com/EDCD/EDMarketConnector.git synced 2025-04-14 08:17:13 +03:00

Work around Windows limit on ShellExecute arg len

This commit is contained in:
Jonathan Harris 2016-11-20 00:58:04 +00:00
parent 170d1435fb
commit d1cdc89ecd
2 changed files with 68 additions and 1 deletions

View File

@ -134,6 +134,9 @@ This app uses Elite: Dangerous' “journal” files to track the systems and sta
### Error: Can't connect to EDDN
EDMC needs to talk to eddn-gateway.elite-markets.net on port 8080. If you consistently receive this error check that your router or VPN configuration allows port 8080 / tcp outbound.
### Import failed: No ship loadout found
Complex ship loadouts with Engineers' mods can cause you to hit an Internet Explorer / Edge limitation on the length of URLs. Switch to a browser that doesn't suck.
Running from source
--------

View File

@ -5,6 +5,33 @@ import Tkinter as tk
import ttk
import tkFont
if platform == 'win32':
import subprocess
import ctypes
from ctypes.wintypes import *
HKEY_CLASSES_ROOT = 0x80000000
HKEY_CURRENT_USER = 0x80000001
KEY_READ = 0x00020019
KEY_ALL_ACCESS = 0x000F003F
REG_SZ = 1
REG_DWORD = 4
REG_MULTI_SZ = 7
RegOpenKeyEx = ctypes.windll.advapi32.RegOpenKeyExW
RegOpenKeyEx.restype = LONG
RegOpenKeyEx.argtypes = [HKEY, LPCWSTR, DWORD, DWORD, ctypes.POINTER(HKEY)]
RegCloseKey = ctypes.windll.advapi32.RegCloseKey
RegCloseKey.restype = LONG
RegCloseKey.argtypes = [HKEY]
RegQueryValueEx = ctypes.windll.advapi32.RegQueryValueExW
RegQueryValueEx.restype = LONG
RegQueryValueEx.argtypes = [HKEY, LPCWSTR, LPCVOID, ctypes.POINTER(DWORD), LPCVOID, ctypes.POINTER(DWORD)]
# A clickable ttk Label
#
@ -89,7 +116,7 @@ class HyperlinkLabel(platform == 'darwin' and tk.Label or ttk.Label, object):
url = self.url(self['text']) if callable(self.url) else self.url
if url:
self._leave(event) # Remove underline before we change window to browser
webbrowser.open(url)
openurl(url)
def _contextmenu(self, event):
if self['text'] and (self.popup_copy(self['text']) if callable(self.popup_copy) else self.popup_copy):
@ -100,3 +127,40 @@ class HyperlinkLabel(platform == 'darwin' and tk.Label or ttk.Label, object):
self.clipboard_append(self['text'])
def openurl(url):
if platform == 'win32':
# On Windows webbrowser.open calls os.startfile which calls ShellExecute which can't handle long arguments,
# so discover and launch the browser directly.
# https://blogs.msdn.microsoft.com/oldnewthing/20031210-00/?p=41553
hkey = HKEY()
cls = 'http'
if not RegOpenKeyEx(HKEY_CURRENT_USER, r'Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice', 0, KEY_READ, ctypes.byref(hkey)):
typ = DWORD()
size = DWORD()
if not RegQueryValueEx(hkey, 'ProgId', 0, ctypes.byref(typ), None, ctypes.byref(size)) and typ.value in [REG_SZ, REG_MULTI_SZ]:
buf = ctypes.create_unicode_buffer(size.value / 2)
if not RegQueryValueEx(hkey, 'ProgId', 0, ctypes.byref(typ), buf, ctypes.byref(size)):
if buf.value in ['IE.HTTP', 'AppXq0fevzme2pys62n3e0fbqa7peapykr8v']:
# IE and Edge can't handle long arguments so just use webbrowser.open and hope
# https://blogs.msdn.microsoft.com/ieinternals/2014/08/13/url-length-limits/
cls = None
else:
cls = buf.value
RegCloseKey(hkey)
if cls and not RegOpenKeyEx(HKEY_CLASSES_ROOT, r'%s\shell\open\command' % cls, 0, KEY_READ, ctypes.byref(hkey)):
typ = DWORD()
size = DWORD()
if not RegQueryValueEx(hkey, None, 0, ctypes.byref(typ), None, ctypes.byref(size)) and typ.value in [REG_SZ, REG_MULTI_SZ]:
buf = ctypes.create_unicode_buffer(size.value / 2)
if not RegQueryValueEx(hkey, None, 0, ctypes.byref(typ), buf, ctypes.byref(size)) and 'iexplore' not in buf.value.lower():
RegCloseKey(hkey)
if '%1' in buf.value:
subprocess.Popen(buf.value.replace('%1', url))
else:
subprocess.Popen('%s "%s"' % (buf.value, url))
return
RegCloseKey(hkey)
webbrowser.open(url)