From 60ab777e21a5a1e83f63b950bcffb8a436555c16 Mon Sep 17 00:00:00 2001 From: anders_k Date: Sun, 17 Jan 2021 20:57:20 +0000 Subject: [PATCH] Added string lookup tool git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@7251 212acab6-be3b-0410-9dea-997c60f758d6 --- Contrib/Makensisw/Readme.txt | 3 +- Contrib/Makensisw/SConscript | 4 +- Contrib/Makensisw/lookup.cpp | 324 ++++++++++++++++++++++++++++++++ Contrib/Makensisw/makensisw.cpp | 64 +++---- Contrib/Makensisw/makensisw.h | 8 +- Contrib/Makensisw/resource.h | 9 +- Contrib/Makensisw/resource.rc | 15 +- Contrib/Makensisw/utils.cpp | 11 +- Contrib/Makensisw/utils.h | 23 +++ Contrib/Makensisw/wndspy.cpp | 8 +- 10 files changed, 426 insertions(+), 43 deletions(-) create mode 100644 Contrib/Makensisw/lookup.cpp diff --git a/Contrib/Makensisw/Readme.txt b/Contrib/Makensisw/Readme.txt index e6487182..ebf07902 100644 --- a/Contrib/Makensisw/Readme.txt +++ b/Contrib/Makensisw/Readme.txt @@ -211,7 +211,8 @@ Version History 2.3.6 - Added GUID generator tool -2.3.7 +2.4 +- Added Lookup tool - Use Consolas font if it exists Copyright Information diff --git a/Contrib/Makensisw/SConscript b/Contrib/Makensisw/SConscript index a8732607..a424ddf5 100644 --- a/Contrib/Makensisw/SConscript +++ b/Contrib/Makensisw/SConscript @@ -6,6 +6,7 @@ files = Split(""" utils.cpp version.cpp update.cpp + lookup.cpp wndspy.cpp """) @@ -42,6 +43,7 @@ libs = Split(""" wininet winmm kernel32 + ole32 """) docs = Split(""" @@ -58,7 +60,7 @@ BuildUtil( res = res, resources = resources, entry = None, - defines = ['RELEASE=2.3.7'], + defines = ['RELEASE=2.4'], docs = docs, root_util = True ) diff --git a/Contrib/Makensisw/lookup.cpp b/Contrib/Makensisw/lookup.cpp new file mode 100644 index 00000000..27abfadb --- /dev/null +++ b/Contrib/Makensisw/lookup.cpp @@ -0,0 +1,324 @@ +// Copyright (C) 2020-2021 Anders Kjersem +// +// This file is a part of NSIS. +// +// Licensed under the zlib/libpng license (the "License"); +// you may not use this file except in compliance with the License. +// +// Licence details can be found in the file COPYING. +// +// This software is provided 'as-is', without any express or implied +// warranty. + +#include "makensisw.h" +#include +#include +#include +#include +#include "utils.h" +#include "resource.h" + +enum { reg_mui_string_truncate = 0x01 }; + +static void StrTToW(LPCTSTR Src, LPWSTR Dst, UINT cch) +{ + if (sizeof(*Src) == sizeof(*Dst)) + lstrcpynW(Dst, (LPCWSTR) Src, cch); + else + MultiByteToWideChar(CP_ACP, 0, (LPCSTR) Src, -1, Dst, cch); +} + +template static LPWSTR SmartStrTToW(T*Src, LPWSTR Dst, UINT cch) +{ + if (sizeof(T) == sizeof(*Dst)) return (LPWSTR) Src; + return (StrTToW(Src, Dst, cch), Dst); +} + +template static int WINAPI StrBase10ToSInt(const T*str) +{ + unsigned int v = 0, neg = 0, c, i = 0, base = 10; + if (str[i] == '-') ++neg, ++i; + for (; (c = str[i]) >= T('0') && c <= T('9'); ++i) c -= T('0'), v *= base, v += c; + return neg ? (int) v * -1 : v; +} + +template static int WINAPI PathParseIconLocationFallback(T*Path) +{ + int idx = 0; + SIZE_T i, comma = 0; + for (i = 0; Path[i]; ++i) + { + if (Path[i] == ',') comma = i; + if (FSPath::IsAgnosticSeparator(Path[i])) comma = 0; + } + if (comma) + { + Path[comma] = T('\0'); + idx = StrBase10ToSInt(Path + comma + 1); + } + return idx; +} + +static HRESULT GetSpecialFolderPath(HWND hWnd, LPTSTR Buf, UINT csidl) +{ + UINT create = csidl & CSIDL_FLAG_CREATE, succ, ec; + csidl &= ~CSIDL_FLAG_CREATE; + if (SupportsWNT4() || SupportsW95()) + { + LPITEMIDLIST pidl; + HRESULT hr = SHGetSpecialFolderLocation(hWnd, csidl, &pidl); + if (SUCCEEDED(hr)) + { + hr = SHGetPathFromIDList(pidl, Buf) ? S_OK : E_FAIL, CoTaskMemFree(pidl); + if (SUCCEEDED(hr) && create) + { + succ = CreateDirectory(Buf, NULL); + hr = (succ || (ec = GetLastError()) == ERROR_ALREADY_EXISTS) ? S_OK : HRESULT_FROM_WIN32(ec); + } + } + return hr; + } + succ = SHGetSpecialFolderPath(hWnd, Buf, csidl, false); + if (!succ && create) succ = SHGetSpecialFolderPath(hWnd, Buf, csidl, create); + return succ ? S_OK : E_FAIL; +} + +static HICON LoadIconFromLocation(LPCTSTR Path, int Idx) +{ + // web.archive.org/web/201901/https://blogs.msdn.microsoft.com/oldnewthing/20100505-00/?p=14153# -1 is special + HICON hIco = ExtractIcon(NULL, Path, Idx == -1 ? 0 : Idx); + if (!hIco && !GetLastError()) SetLastError(ERROR_NOT_FOUND); + return hIco; +} + +template static void AppendText(HWND hEdit, const T*Str) +{ + SNDMSG(hEdit, EM_SETSEL, 0, -1), SNDMSG(hEdit, EM_SETSEL, -1, -1); + if (sizeof(T) > 1) + SendMessageW(hEdit, EM_REPLACESEL, 0, (SIZE_T) Str); + else + SendMessageA(hEdit, EM_REPLACESEL, 0, (SIZE_T) Str); +} + +static int AddComboStringWithData(HWND hWnd, LPCSTR Str, SIZE_T Data) +{ + int idx = (int) SendMessageA(hWnd, CB_INSERTSTRING, (INT_PTR) -1, (SIZE_T) const_cast(Str)); + if (idx >= 0) SendMessage(hWnd, CB_SETITEMDATA, idx, Data); + return idx; +} + +template static HKEY ParseRegPath(I*In, O*&Path, O*&Name) +{ + HKEY hKey = GetRegRootKey(In); + I*pp = 0, *pn = 0; + if (hKey) + { + SIZE_T i; + for (i = 0; In[i]; ++i) + if (In[i] == I('\\')) + (!pp ? pp : pn) = &In[i + 1]; // First separator after HK* or last separator + if (pn) pn[-1] = I('\0'); // Split path and name + } + return (Path = const_cast(pp), Name = const_cast(pn), hKey); +} + +HRESULT (WINAPI*g_SHLIS)(LPCWSTR s, LPWSTR o, UINT cch, PVOID*ppvReserved); +HRESULT (WINAPI*g_RLMSOld)(HKEY hKey, LPCWSTR pszValue, LPWSTR pszOutBuf, DWORD cbOutBuf); + +static LSTATUS WINAPI RegLoadMUIStringFallbackW(HKEY hKey, LPCWSTR Name, LPWSTR Out, DWORD cbOutBuf, LPDWORD pcbData, DWORD Flags, LPCSTR pszDirectory) +{ + if ((Flags & reg_mui_string_truncate) && pcbData) return ERROR_INVALID_PARAMETER; + if (g_RLMSOld) + { + HRESULT hr = g_RLMSOld(hKey, Name, Out, cbOutBuf); + if (SUCCEEDED(hr)) + { + if (pcbData) *pcbData = (StrLenT(Out) + 1) * sizeof(*Out); + return ERROR_SUCCESS; + } + if (pcbData) *pcbData = (cbOutBuf|1) * 2; // We have no real value to set, caller just has to loop until success + return hr; // Note: Not converting E_* here, FormatMessage knows what to do. + } + return ERROR_NOT_SUPPORTED; +} + +enum { LM_SHGLN, LM_SHLIS, LM_RLMS, LM_PPIL }; +LPCSTR g_ModeLbl[] = { "Path:", "Path:", "Registry:", "Path:" }; + +struct DIALOGDATA { + HRESULT (WINAPI*SHGLN)(PCWSTR p, PWSTR m, UINT cch, int*rid); + LSTATUS (WINAPI*RLMS)(HKEY hKey, LPCWSTR pszValue, LPWSTR pszOutBuf, DWORD cbOutBuf, LPDWORD pcbData, DWORD Flags, LPCSTR pszDirectory); + int (WINAPI*PPIL)(LPTSTR p); + void*OrgParentDlgData; + HWND hMode, hExtra, hOutTxt, hOutIco; + + DIALOGDATA() { extern void* g_ModalDlgData; OrgParentDlgData = g_ModalDlgData, g_ModalDlgData = this; } + ~DIALOGDATA() { extern void* g_ModalDlgData; g_ModalDlgData = OrgParentDlgData; } + static DIALOGDATA* Get(HWND hDlg) { return (DIALOGDATA*) g_ModalDlgData; } + static inline void Set(HWND hDlg, DIALOGDATA*p) { } +}; + +static INT_PTR CALLBACK LookupDlgProc(HWND hDlg, UINT Msg, WPARAM WParam, LPARAM LParam) +{ + DIALOGDATA*pDD = DIALOGDATA::Get(hDlg); + int idx = pDD ? (int) SendMessage(pDD->hMode, CB_GETCURSEL, 0, 0) : 0; + UINT mode = pDD ? (UINT) SendMessage(pDD->hMode, CB_GETITEMDATA, idx, 0) : 0; + HRESULT hr; + TCHAR buf[MAX_PATH + 1 + 6]; // Path + ',' + resid + + switch(Msg) + { + case WM_INITDIALOG: + DIALOGDATA::Set(hDlg, (pDD = (DIALOGDATA*) LParam)); + CenterOnParent(hDlg); + pDD->hMode = GetDlgItem(hDlg, IDC_LUMODE); + pDD->hExtra = GetDlgItem(hDlg, IDC_LUEXTRATEXT); + pDD->hOutTxt = GetDlgItem(hDlg, IDC_LUOUTPUTTEXT); + pDD->hOutIco = CreateWindowEx(WS_EX_TRANSPARENT, _T("STATIC"), 0, WS_CHILD|WS_VISIBLE|SS_ICON|SS_CENTERIMAGE|SS_REALSIZECONTROL, 0, 0, 0, 0, pDD->hOutTxt, 0, 0, 0); + if (pDD->SHGLN) AddComboStringWithData(pDD->hMode, "SHGetLocalizedName", LM_SHGLN); + if (g_SHLIS) AddComboStringWithData(pDD->hMode, "SHLoadIndirectString", LM_SHLIS); + if (pDD->RLMS) AddComboStringWithData(pDD->hMode, "RegLoadMUIString", LM_RLMS); + if (pDD->PPIL) AddComboStringWithData(pDD->hMode, "PathParseIconLocation", LM_PPIL); + SNDMSG(pDD->hExtra, EM_LIMITTEXT, COUNTOF(buf), 0); + SNDMSG(pDD->hMode, CB_SETCURSEL, (SIZE_T) 0, 0), SNDMSG(hDlg, WM_COMMAND, MAKELONG(IDC_LUMODE, CBN_SELENDOK), (SIZE_T) pDD->hMode); + return TRUE; + case WM_CLOSE: close: + return EndDialog(hDlg, 0); + case WM_DESTROY: + { + HICON hOld = (HICON) SNDMSG(pDD->hOutIco, STM_SETICON, (SIZE_T) NULL, 0); + if (hOld) DestroyIcon(hOld); + } + break; + case WM_COMMAND: + switch((UINT) WParam) + { + case IDCANCEL: + goto close; + case MAKELONG(IDC_LUMODE, CBN_SELENDOK): + { + SendMessageA(GetDlgItem(hDlg, IDC_LUEXTRALABEL), WM_SETTEXT, 0, (SIZE_T) const_cast(g_ModeLbl[mode])); + LPCTSTR extra = buf; + *buf = '\0'; + switch(mode) + { + case LM_SHGLN: + GetSpecialFolderPath(NULL, buf, CSIDL_COMMON_DESKTOPDIRECTORY); + break; + case LM_SHLIS: + extra = _T("@shell32,-4097"); + break; + case LM_RLMS: + extra = _T("HKCR\\AudioCD\\shell\\play\\MUIVerb"); + break; + case LM_PPIL: + extra = _T("%WINDIR%\\Explorer.exe,-101"); + break; + } + ShowWindow(pDD->hOutIco, SW_HIDE); + SetWindowText(pDD->hExtra, extra); + } + break; + case MAKELONG(IDC_LUEXTRATEXT, EN_UPDATE): + SendMessage(pDD->hExtra, WM_GETTEXT, COUNTOF(buf), (SIZE_T) buf); + SetWindowText(pDD->hOutTxt, _T("")); + switch(mode) + { + case LM_SHGLN: + { + int resid; + WCHAR path[COUNTOF(buf)], mod[MAX_PATH], *pis; + pis = SmartStrTToW(buf, path, COUNTOF(path)); + hr = pDD->SHGLN(pis, mod, COUNTOF(mod), &resid); + if (SUCCEEDED(hr)) + { + AppendText(pDD->hOutTxt, mod); + AppendText(pDD->hOutTxt, (wsprintfW(path, L",%d\r\n\r\n", resid), path)); + if (ExpandEnvironmentStringsW(mod, path, ARRAYSIZE(path))) + { + if (HMODULE hMod = LoadLibraryExW(path, NULL, LOAD_LIBRARY_AS_DATAFILE)) + { + if (LoadStringW(hMod, resid, mod, ARRAYSIZE(mod))) + { + AppendText(pDD->hOutTxt, mod); + } + FreeLibrary(hMod); + } + } + } + else die_hr: + { + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, NULL, hr, 0, buf, COUNTOF(buf), NULL); + AppendText(pDD->hOutTxt, (wsprintfW(path, L"%#x: ", hr), path)); + AppendText(pDD->hOutTxt, buf); + } + } + break; + case LM_SHLIS: + { + WCHAR is[COUNTOF(buf)], os[MAX_PATH], *pis; + pis = SmartStrTToW(buf, is, COUNTOF(is)); + hr = g_SHLIS(pis, os, COUNTOF(os), NULL); + if (FAILED(hr)) goto die_hr; + AppendText(pDD->hOutTxt, os); + } + break; + case LM_RLMS: + { + UINT ec; + TCHAR *pkey, *pname; + if (HKEY hKey = ParseRegPath(buf, pkey, pname)) + { + if (!(ec = RegOpenKeyForReading(hKey, pkey, &hKey))) + { + WCHAR namebuf[255+!0], outbuf[MAX_PATH], *pwn = SmartStrTToW(pname, namebuf, COUNTOF(namebuf)); + ec = pDD->RLMS(hKey, pwn, outbuf, sizeof(outbuf), NULL, reg_mui_string_truncate, NULL); + if (!ec) AppendText(pDD->hOutTxt, outbuf); + RegCloseKey(hKey); + } + if (FAILED(hr = HRESULT_FROM_WIN32(ec))) goto die_hr; + } + } + break; + case LM_PPIL: + { + RECT r; + int idx = pDD->PPIL(buf); + HICON hIco = LoadIconFromLocation(buf, idx), hOld; + hr = GetLastError(); + GetClientRect(pDD->hOutTxt, &r); + SetWindowPos(pDD->hOutIco, HWND_TOP, 0, 0, r.right, r.bottom, SWP_NOACTIVATE|(hIco ? SWP_SHOWWINDOW : SWP_HIDEWINDOW)); + hOld = (HICON) SNDMSG(pDD->hOutIco, STM_SETICON, (SIZE_T) hIco, 0); + if (hOld) DestroyIcon(hOld); + if (!hIco) goto die_hr; + } + break; + } + break; + } + break; + } + return FALSE; +} + +INT_PTR ShowLookupDialog(HWND hOwner) +{ + DIALOGDATA dd; + (FARPROC&) dd.SHGLN = GetSysProcAddr("SHELL32", "SHGetLocalizedName"); + (FARPROC&) g_SHLIS = GetSysProcAddr("SHLWAPI", (LPCSTR) 487); + (FARPROC&) dd.RLMS = GetSysProcAddr("ADVAPI32", "RegLoadMUIStringW"); // Note: RegLoadMUIStringA always returns ERROR_CALL_NOT_IMPLEMENTED + if (!dd.RLMS && ((FARPROC&) g_RLMSOld = GetSysProcAddr("SHLWAPI", (LPCSTR) 439))) dd.RLMS = RegLoadMUIStringFallbackW; + (FARPROC&) dd.PPIL = + #ifdef _WIN64 + (FARPROC) PathParseIconLocation; + #else + GetSysProcAddr("SHLWAPI", sizeof(TCHAR) == 1 ? "PathParseIconLocationA" : "PathParseIconLocationW"); + if (!dd.PPIL || (SupportsWNT4() || IsWin9598ME())) + { + (FARPROC&) dd.PPIL = GetSysProcAddr("SHELL32", (LPCSTR) 249); // PathParseIconLocationT + if (sizeof(TCHAR) == 1) (FARPROC&) dd.PPIL = (FARPROC) PathParseIconLocationFallback; + } + #endif + + return DialogBoxParam(HINST_APPLICATION, MAKEINTRESOURCE(DLG_LOOKUP), hOwner, LookupDlgProc, (LPARAM) &dd); +} \ No newline at end of file diff --git a/Contrib/Makensisw/makensisw.cpp b/Contrib/Makensisw/makensisw.cpp index 12983683..6aa4344e 100644 --- a/Contrib/Makensisw/makensisw.cpp +++ b/Contrib/Makensisw/makensisw.cpp @@ -45,6 +45,7 @@ NFINDREPLACE g_find; TCHAR g_findbuf[128]; extern NTOOLBAR g_toolbar; void* g_ModalDlgData; +BYTE g_MiniCommand = false; NSIS_ENTRYPOINT_SIMPLEGUI int WINAPI _tWinMain(HINSTANCE hInst,HINSTANCE hOldInst,LPTSTR CmdLineParams,int ShowCmd) { @@ -86,12 +87,12 @@ int WINAPI _tWinMain(HINSTANCE hInst,HINSTANCE hOldInst,LPTSTR CmdLineParams,int return 1; } ResetObjects(); + HACCEL haccel = LoadAccelerators(g_sdata.hInstance, MAKEINTRESOURCE(IDK_ACCEL)); HWND hDialog = CreateDialog(g_sdata.hInstance,MAKEINTRESOURCE(DLG_MAIN),0,DialogProc); - if (!hDialog) { + if (!hDialog && !g_MiniCommand) { MessageBox(0,DLGERROR,ERRBOXTITLE,MB_ICONEXCLAMATION|MB_OK|MB_TASKMODAL); return 1; } - HACCEL haccel = LoadAccelerators(g_sdata.hInstance, MAKEINTRESOURCE(IDK_ACCEL)); MSG msg; int status; while ((status=GetMessage(&msg,0,0,0))!=0) { @@ -146,22 +147,21 @@ static void AddScriptCmdArgs(const TCHAR *arg) GlobalUnlock(g_sdata.script_cmd_args); } -static void ProcessCommandLine() +enum { CMD_PICKCOMP = 0x0001, CMD_SPY = 0x0080, CMD_LOOKUP = 0x8000 }; +static UINT ProcessCommandLine() { TCHAR **argv; - int i, j; + int i, j, retflags = 0; int argc = SetArgv((TCHAR *)GetCommandLine(), &argv); if (argc > 1) { for (i = 1; i < argc; i++) { - if (!StrCmpNI(argv[i], _T("/XSetCompressor "), lstrlen(_T("/XSetCompressor ")))) + if (!lstrcmpi(argv[i], _T("/Spy"))) retflags |= CMD_SPY; + else if (!lstrcmpi(argv[i], _T("/Lookup"))) retflags |= CMD_LOOKUP; + else if (!StrCmpNI(argv[i], _T("/XSetCompressor "), COUNTOF("/XSetCompressor ") - !0)) { - TCHAR *p = argv[i] + lstrlen(_T("/XSetCompressor ")); - if(!StrCmpNI(p,_T("/FINAL "), lstrlen(_T("/FINAL ")))) - { - p += lstrlen(_T("/FINAL ")); - } - + TCHAR *p = argv[i] + lstrlen(_T("/XSetCompressor ")), cchSlashFinalSpace = COUNTOF("/FINAL ") - !0; + if (!StrCmpNI(p,_T("/FINAL "), cchSlashFinalSpace)) p += cchSlashFinalSpace; while (*p == _T(' ')) p++; for (j = (int) COMPRESSOR_SCRIPT + 1; j < (int) COMPRESSOR_BEST; j++) @@ -174,7 +174,7 @@ static void ProcessCommandLine() } else if (!lstrcmpi(argv[i], _T("/ChooseCompressor"))) { - g_sdata.userSelectCompressor = TRUE; + retflags |= CMD_PICKCOMP; } else if (argv[i][0] == _T('-') || argv[i][0] == _T('/')) { @@ -189,6 +189,7 @@ static void ProcessCommandLine() } } MemSafeFree(argv); + return retflags; } DWORD CALLBACK SaveFileStreamCallback(DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb) @@ -261,7 +262,6 @@ INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam // Altered by Darren Owen (DrO) on 29/9/2003 // Added in receiving of mouse and key events from the richedit control SendDlgItemMessage(hwndDlg,IDC_LOGWIN,EM_SETEVENTMASK,(WPARAM)NULL,ENM_SELCHANGE|ENM_MOUSEEVENTS|ENM_KEYEVENTS); - DragAcceptFiles(g_sdata.hwnd,FALSE); g_sdata.menu = GetMenu(g_sdata.hwnd); g_sdata.fileSubmenu = FindSubMenu(g_sdata.menu, IDM_FILE); g_sdata.editSubmenu = FindSubMenu(g_sdata.menu, IDM_EDIT); @@ -286,20 +286,27 @@ INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam } HFONT hFont = CreateFontPt(hwndDlg,fontsize,FW_NORMAL,FIXED_PITCH|FF_DONTCARE,fontcharset,fontname); SendDlgItemMessage(hwndDlg,IDC_LOGWIN,WM_SETFONT,(WPARAM)hFont,0); - RestoreWindowPos(g_sdata.hwnd); - RestoreCompressor(); - SetScript(_T("")); g_sdata.compressor = COMPRESSOR_NONE_SELECTED; - g_sdata.userSelectCompressor = FALSE; + SetScript(_T("")); + RestoreCompressor(); ToolBarSizeChanged(hwndDlg); - ProcessCommandLine(); + UINT docmd = ProcessCommandLine(); + if ((docmd & (CMD_SPY|CMD_LOOKUP))) + { + INT_PTR r = ((docmd & CMD_LOOKUP) ? ShowLookupDialog : ShowWndSpy)(0); + g_sdata.hwnd = NULL; // Don't save window pos + g_MiniCommand++; + return SendMessage(hwndDlg, WM_CLOSE, r, r); + } + + RestoreWindowPos(g_sdata.hwnd); if(g_sdata.compressor == COMPRESSOR_NONE_SELECTED) { SetCompressor(g_sdata.default_compressor); } - if(g_sdata.userSelectCompressor) { + if(docmd & CMD_PICKCOMP) { if (DialogBox(g_sdata.hInstance,MAKEINTRESOURCE(DLG_COMPRESSOR),g_sdata.hwnd,API_cast(CompressorProc))) { EnableItems(g_sdata.hwnd); return TRUE; @@ -320,7 +327,6 @@ INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam } case WM_DESTROY: { - DragAcceptFiles(g_sdata.hwnd, FALSE); SaveSymbols(); SaveMRUList(); SaveWindowPos(g_sdata.hwnd); @@ -331,10 +337,11 @@ INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam PostQuitMessage(0); return TRUE; } - case WM_CLOSE: + case WM_CLOSE: tryquitapp: { if (!g_sdata.thread) { DestroyWindow(hwndDlg); + PostQuitMessage((int) wParam); } return TRUE; } @@ -699,11 +706,8 @@ INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam DialogBox(g_sdata.hInstance,MAKEINTRESOURCE(DLG_SETTINGS),g_sdata.hwnd,API_cast(SettingsProc)); return TRUE; } - case IDM_WNDSPY: - { - extern INT_PTR ShowWndSpy(HWND hOwner); - return ShowWndSpy(g_sdata.hwnd); - } + case IDM_WNDSPY: return ShowWndSpy(hwndDlg); + case IDM_LOOKUP: return ShowLookupDialog(hwndDlg); case IDM_GUIDGEN: { GUID guid; @@ -740,12 +744,8 @@ INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam } case IDCANCEL: case IDM_EXIT: - { - if (!g_sdata.thread) { - DestroyWindow(g_sdata.hwnd); - } - return TRUE; - } + wParam = 0; + goto tryquitapp; case IDM_CANCEL: { SetEvent(g_sdata.sigint_event); diff --git a/Contrib/Makensisw/makensisw.h b/Contrib/Makensisw/makensisw.h index 2c54fb8a..6ec58fe8 100644 --- a/Contrib/Makensisw/makensisw.h +++ b/Contrib/Makensisw/makensisw.h @@ -39,6 +39,9 @@ #define SupportsW95() ( FALSE && SupportsW9X() && !DpiAwarePerMonitor() ) #define SupportsW2000() ( sizeof(void*) == 4 ) +static bool IsWin9598ME() { return SupportsW9X() && (int) GetVersion() < 0; } +static bool IsWin95() { return SupportsW95() && (GetVersion() & (0x8000FFFF & ~0x0300)) == 0x80000004; } + // Defines #define NSIS_URL "https://nsis.sourceforge.io/" #define NSIS_FORUM_URL "http://forums.winamp.com/forumdisplay.php?forumid=65" @@ -220,7 +223,6 @@ typedef struct NSISScriptData { char *brandingv; TCHAR **symbols; int retcode; - bool userSelectCompressor; unsigned char verbosity; DWORD logLength; DWORD warnings; @@ -265,4 +267,8 @@ typedef struct ToolTipStruct { HHOOK hook; } NTOOLTIP; + +extern INT_PTR ShowWndSpy(HWND hOwner); +extern INT_PTR ShowLookupDialog(HWND hOwner); + #endif diff --git a/Contrib/Makensisw/resource.h b/Contrib/Makensisw/resource.h index 2ded8cb6..7b43ebc1 100644 --- a/Contrib/Makensisw/resource.h +++ b/Contrib/Makensisw/resource.h @@ -37,6 +37,7 @@ #define IDB_LOGO 115 #define DLG_SETTINGS 116 #define DLG_WNDSPY 117 +#define DLG_LOOKUP 118 #define IDB_TOOLBAR 122 #define DLG_COMPRESSOR 124 #define DLG_SYMBOLSET 125 @@ -83,6 +84,11 @@ #define IDC_WNDPHYSSIZE 227 #define IDC_WNDINFO 229 #define IDC_WNDDPI 230 +#define IDC_LUMODE 220 +#define IDC_LUEXTRALABEL 221 +#define IDC_LUEXTRATEXT 222 +#define IDC_LUOUTPUTTEXT 223 +#define IDC_LUOUTPUTICON 224 #define IDM_MRU_FILE 6000 #define IDM_CMDBASE 500 @@ -127,6 +133,7 @@ #define IDM_UI_SWITCHOWNEDWINDOW 538 // Alt+F6 #define IDM_UI_SWITCHSECTION 539 // F6 #define IDM_GUIDGEN 540 +#define IDM_LOOKUP 541 // Next default values for new objects @@ -134,7 +141,7 @@ #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 138 -#define _APS_NEXT_COMMAND_VALUE 541 +#define _APS_NEXT_COMMAND_VALUE 542 #define _APS_NEXT_CONTROL_VALUE 241 #define _APS_NEXT_SYMED_VALUE 101 #endif diff --git a/Contrib/Makensisw/resource.rc b/Contrib/Makensisw/resource.rc index 7069f6d1..1c4108d4 100644 --- a/Contrib/Makensisw/resource.rc +++ b/Contrib/Makensisw/resource.rc @@ -111,6 +111,7 @@ BEGIN MENUITEM "&Settings\tCtrl+S", IDM_SETTINGS MENUITEM "", -1, MFT_SEPARATOR MENUITEM "&Window Info", IDM_WNDSPY + MENUITEM "&Lookup", IDM_LOOKUP MENUITEM "Generate &GUID", IDM_GUIDGEN MENUITEM "", -1, MFT_SEPARATOR MENUITEM "Clear Recent &Files List", IDM_CLEAR_MRU_LIST @@ -249,7 +250,7 @@ BEGIN END DLG_WNDSPY DIALOGEX 0, 0, 236, 130 -STYLE DS_SETFONT | DS_FIXEDSYS | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +STYLE DS_SETFONT | DS_FIXEDSYS | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | DS_CENTER CAPTION "Window Info" FONT 8, "MS Shell Dlg", 0, 0, 0x0 BEGIN @@ -275,6 +276,18 @@ BEGIN CONTROL "", IDC_WNDDPI, "Edit", ES_LEFT | ES_READONLY | WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL , 39, 114, 190, 10 END +DLG_LOOKUP DIALOGEX 0, 0, 301, 150 +STYLE DS_SETFONT | DS_FIXEDSYS | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU | DS_CENTER +CAPTION "Lookup" +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + CONTROL "Source", -1, BUTTON, BS_GROUPBOX | WS_CHILD | WS_VISIBLE, 7, 7, 285, 65 + CONTROL "", IDC_LUMODE, COMBOBOX, CBS_DROPDOWNLIST | CBS_HASSTRINGS | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 16, 20, 268, 114 + CONTROL "", IDC_LUEXTRALABEL, STATIC, SS_LEFT | WS_CHILD | WS_VISIBLE | WS_GROUP, 16, 38, 268, 10 + CONTROL "", IDC_LUEXTRATEXT, EDIT, ES_LEFT | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 16, 50, 268, 14 + CONTROL "", IDC_LUOUTPUTTEXT, EDIT, ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_READONLY | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VSCROLL | WS_TABSTOP, 7, 80, 286, 60 +END + ///////////////////////////////////////////////////////////////////////////// // // DESIGNINFO diff --git a/Contrib/Makensisw/utils.cpp b/Contrib/Makensisw/utils.cpp index 606ffb1a..366d56d2 100644 --- a/Contrib/Makensisw/utils.cpp +++ b/Contrib/Makensisw/utils.cpp @@ -60,6 +60,9 @@ HMODULE LoadSysLibrary(LPCSTR Mod) return LoadLibrary(path); } +#ifdef DECLSPEC_NOINLINE +DECLSPEC_NOINLINE +#endif FARPROC GetSysProcAddr(LPCSTR Mod, LPCSTR FuncName) { return GetProcAddress(LoadSysLibrary(Mod), FuncName); @@ -436,7 +439,7 @@ static DWORD RegReadString(HKEY hKey, LPCTSTR Name, LPTSTR Buf, DWORD cbBufSize) return ec; } -static DWORD RegOpenKeyForReading(HKEY hRoot, LPCTSTR SubKey, HKEY*pKey) { +DWORD RegOpenKeyForReading(HKEY hRoot, LPCTSTR SubKey, HKEY*pKey) { return RegOpenKeyEx(hRoot, SubKey, 0, KEY_READ, pKey); } @@ -519,9 +522,9 @@ void SaveWindowPos(HWND hwnd) { HKEY hKey; WINDOWPLACEMENT p; p.length = sizeof(p); - GetWindowPlacement(hwnd, &p); - if (CreateRegSettingsKey(hKey)) { - RegSetValueEx(hKey, REGLOC, 0, REG_BINARY, (LPBYTE)&p, sizeof(p)); + if (!GetWindowPlacement(hwnd, &p)) p.length = 0; + if (p.length && CreateRegSettingsKey(hKey)) { + RegSetValueEx(hKey, REGLOC, 0, REG_BINARY, (LPBYTE)&p, p.length); RegCloseKey(hKey); } } diff --git a/Contrib/Makensisw/utils.h b/Contrib/Makensisw/utils.h index 7659a25d..01477276 100644 --- a/Contrib/Makensisw/utils.h +++ b/Contrib/Makensisw/utils.h @@ -111,6 +111,29 @@ struct FSPath { } }; +template UINT StrLenT(const T*s) { return sizeof(T) > 1 ? lstrlenW((WCHAR*) s) : lstrlenA((CHAR*) s) ; } +template T AsciiLoCh(T ch) { return ch >= 'A' && ch <= 'Z' ? (ch | 32) : ch; } + +template int AsciiCmpNI(const A*a, const B*b, SIZE_T len) +{ + int cmp = 0; + for (SIZE_T i = 0;; ++i) + if (i == len || (cmp = AsciiLoCh(a[i]) - AsciiLoCh(b[i])) || !a[i]) + return cmp; +} +template inline bool AsciiMatchNI(const A*a, const B*b, SIZE_T c) { return !AsciiCmpNI(a, b, c); } +template bool AsciiMatchPrefixI(const A*s, const B*p) { return AsciiMatchNI(s, p, StrLenT(p)); } + +template HKEY GetRegRootKey(const T*Str) +{ + if (AsciiMatchPrefixI(Str, "HKEY_CLASSES_ROOT") || AsciiMatchPrefixI(Str, "HKCR")) return HKEY_CLASSES_ROOT; + if (AsciiMatchPrefixI(Str, "HKEY_CURRENT_USER") || AsciiMatchPrefixI(Str, "HKCU")) return HKEY_CURRENT_USER; + if (AsciiMatchPrefixI(Str, "HKEY_LOCAL_MACHINE") || AsciiMatchPrefixI(Str, "HKLM")) return HKEY_LOCAL_MACHINE; + if (AsciiMatchPrefixI(Str, "HKEY_USERS") || AsciiMatchPrefixI(Str, "HKU")) return HKEY_USERS; + return (HKEY) NULL; +} +DWORD RegOpenKeyForReading(HKEY hRoot, LPCTSTR SubKey, HKEY*pKey); + bool FileExists(const TCHAR *fname); bool OpenUrlInDefaultBrowser(HWND hwnd, LPCSTR Url); diff --git a/Contrib/Makensisw/wndspy.cpp b/Contrib/Makensisw/wndspy.cpp index fc049311..f6691061 100644 --- a/Contrib/Makensisw/wndspy.cpp +++ b/Contrib/Makensisw/wndspy.cpp @@ -106,6 +106,7 @@ typedef struct _DIALOGDATA { int DialogAwarenessContext; // Canonical DPI awareness context _DIALOGDATA() : hWndOutline(0) {} static struct _DIALOGDATA* Get(HWND hDlg) { return (struct _DIALOGDATA*) GetWindowLongPtr(hDlg, DWLP_USER); } + static void Set(HWND hDlg, void*pDD) { SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR) pDD); } } DIALOGDATA; typedef struct { @@ -281,7 +282,7 @@ static INT_PTR CALLBACK SpyDlgProc(HWND hDlg, UINT Msg, WPARAM WParam, LPARAM LP switch(Msg) { case WM_INITDIALOG: - SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR) (pDD = (DIALOGDATA*) LParam)); + DIALOGDATA::Set(hDlg, (pDD = (DIALOGDATA*) LParam)); CenterOnParent(hDlg); // On >= 10FU1703 we are PMv2 and Windows scales our dialog and child controls. // On >= 10FU1607 && < 10FU1703 we are System aware but try to upgrade this thread to @@ -336,7 +337,10 @@ static INT_PTR CALLBACK SpyDlgProc(HWND hDlg, UINT Msg, WPARAM WParam, LPARAM LP RECT r; GetPhysicalWindowRect(pDD->hWndTarget, r, hDlg), PhysicalToLogical(pDD->hWndOutline, r, hDlg); if (GetAncestor(pDD->hWndTarget, GA_ROOT) != hDlg) - SetWindowPos(pDD->hWndOutline, HWND_TOPMOST, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_SHOWWINDOW|SWP_NOCOPYBITS|SWP_NOACTIVATE|SWP_NOOWNERZORDER); + { + SetWindowPos(pDD->hWndOutline, HWND_TOPMOST, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_HIDEWINDOW|SWP_NOCOPYBITS|SWP_NOACTIVATE|SWP_NOOWNERZORDER); + ShowWindow(pDD->hWndOutline, SW_SHOW); // To avoid a small Windows redraw bug, don't show the window until after it has the correct size + } SetTimer(hDlg, TID_OUTLINE, 2 * 1000, NULL); } ReleaseCapture();