2002-08-02 10:01:35 +00:00
/*
Copyright ( c ) 2002 Robert Rainwater
2004-01-01 17:39:21 +00:00
Contributors : Justin Frankel , Fritz Elfert , Amir Szekely , Sunil Kamath , Joost Verburg
2002-08-02 10:01:35 +00:00
This software is provided ' as - is ' , without any express or implied
warranty . In no event will the authors be held liable for any damages
arising from the use of this software .
Permission is granted to anyone to use this software for any purpose ,
including commercial applications , and to alter it and redistribute it
freely , subject to the following restrictions :
1. The origin of this software must not be misrepresented ; you must not
2002-12-24 20:35:26 +00:00
claim that you wrote the original software . If you use this software
in a product , an acknowledgment in the product documentation would be
appreciated but is not required .
2002-08-02 10:01:35 +00:00
2. Altered source versions must be plainly marked as such , and must not be
2002-12-24 20:35:26 +00:00
misrepresented as being the original software .
2002-08-02 10:01:35 +00:00
3. This notice may not be removed or altered from any source distribution .
2010-03-24 17:22:56 +00:00
Unicode support by Jim Park - - 08 / 20 / 2007
2002-08-02 10:01:35 +00:00
*/
2005-05-12 16:49:50 +00:00
2002-08-02 10:01:35 +00:00
# include "makensisw.h"
2005-05-12 16:49:50 +00:00
# include "resource.h"
2003-05-28 04:51:20 +00:00
# include "toolbar.h"
2010-04-12 16:00:17 +00:00
# include <shlwapi.h>
2002-08-02 10:01:35 +00:00
2018-11-07 00:26:29 +00:00
# ifndef MONITOR_DEFAULTTONEAREST
# define MONITOR_DEFAULTTONEAREST 2
WINUSERAPI HMONITOR WINAPI MonitorFromWindow ( HWND hwnd , DWORD dwFlags ) ;
# endif
# ifndef GRADIENT_FILL_RECT_H
# define GRADIENT_FILL_RECT_H 0
# if !defined(_WIN32_WINNT) || _WIN32_WINNT-0 < 0x0410
2018-11-07 02:36:21 +00:00
WINGDIAPI BOOL WINAPI GradientFill ( HDC , TRIVERTEX * , ULONG , PVOID , ULONG , ULONG ) ;
2018-11-07 00:26:29 +00:00
# endif
# endif
2013-08-07 19:26:03 +00:00
2002-10-09 20:41:37 +00:00
NTOOLTIP g_tip ;
2002-09-19 22:38:46 +00:00
LRESULT CALLBACK TipHookProc ( int nCode , WPARAM wParam , LPARAM lParam ) ;
2010-03-24 17:22:56 +00:00
TCHAR g_mru_list [ MRU_LIST_SIZE ] [ MAX_PATH ] = { _T ( " " ) , _T ( " " ) , _T ( " " ) , _T ( " " ) , _T ( " " ) } ;
2003-08-12 17:57:14 +00:00
2002-10-09 20:41:37 +00:00
extern NSCRIPTDATA g_sdata ;
2011-11-09 18:12:57 +00:00
extern const TCHAR * compressor_names [ ] ;
2002-09-19 15:29:16 +00:00
2013-05-26 19:47:22 +00:00
void MemSafeFree ( void * mem ) { if ( mem ) GlobalFree ( mem ) ; }
void * MemAllocZI ( SIZE_T cb ) { return GlobalAlloc ( GPTR , cb ) ; }
2018-11-11 22:05:32 +00:00
HMODULE LoadSysLibrary ( LPCSTR Mod )
{
TCHAR buf [ MAX_PATH + 20 ] , * path ;
UINT dirmax = MAX_PATH , cch ;
if ( ( cch = GetSystemDirectory ( buf , dirmax ) ) > = dirmax ) cch = 0 ;
wsprintf ( buf + cch , _T ( " \\ %hs.dll " ) , Mod ) ; // Note: We always append ".dll"
path = buf + ! cch ; // Full path or just the filename
return LoadLibrary ( path ) ;
}
2021-01-17 20:57:20 +00:00
# ifdef DECLSPEC_NOINLINE
DECLSPEC_NOINLINE
# endif
2018-11-11 22:05:32 +00:00
FARPROC GetSysProcAddr ( LPCSTR Mod , LPCSTR FuncName )
{
return GetProcAddress ( LoadSysLibrary ( Mod ) , FuncName ) ;
}
2014-10-12 20:09:35 +00:00
static bool WriteFile ( HANDLE hFile , const void * pData , DWORD cb )
{
DWORD cbio ;
return WriteFile ( hFile , pData , cb , & cbio , 0 ) & & cb = = cbio ;
}
bool WriteUTF16LEBOM ( HANDLE hFile )
{
static const unsigned char u16lb [ ] = { 0xFF , 0xFE } ;
return WriteFile ( hFile , u16lb , sizeof ( u16lb ) ) ;
}
2021-08-20 14:56:26 +00:00
BOOL InitCCExHelper ( UINT icc ) {
INITCOMMONCONTROLSEX icx = { sizeof ( icx ) , icc } ;
BOOL suppw95 = SupportsW95 ( ) ;
FARPROC icce = suppw95 ? GetSysProcAddr ( " COMCTL32 " , " InitCommonControlsEx " ) : ( FARPROC ) InitCommonControlsEx ;
return ( ! suppw95 | | icce ) & & ( ( BOOL ( WINAPI * ) ( const INITCOMMONCONTROLSEX * ) ) icce ) ( & icx ) ;
}
2021-08-21 22:18:38 +00:00
UINT GetScreenBPP ( HWND hWnd ) {
HDC hDc = GetDC ( hWnd ) ;
UINT bpp = GetDeviceCaps ( hDc , BITSPIXEL ) * GetDeviceCaps ( hDc , PLANES ) ; // TODO: COLORRES if RASTERCAPS&RC_PALETTE?
ReleaseDC ( hWnd , hDc ) ;
return bpp ;
}
2013-05-26 19:47:22 +00:00
int SetArgv ( const TCHAR * cmdLine , TCHAR * * * argv ) {
2010-03-24 17:22:56 +00:00
const TCHAR * p ;
TCHAR * arg , * argSpace ;
2003-12-17 16:13:04 +00:00
int size , argSpaceSize , inquote , copy , slashes ;
size = 2 ;
2010-03-24 17:22:56 +00:00
for ( p = cmdLine ; * p ! = _T ( ' \0 ' ) ; p + + ) {
if ( ( * p = = _T ( ' ' ) ) | | ( * p = = _T ( ' \t ' ) ) ) {
2003-12-17 16:13:04 +00:00
size + + ;
2010-03-24 17:22:56 +00:00
while ( ( * p = = _T ( ' ' ) ) | | ( * p = = _T ( ' \t ' ) ) ) {
2003-12-17 16:13:04 +00:00
p + + ;
}
2010-03-24 17:22:56 +00:00
if ( * p = = _T ( ' \0 ' ) ) {
2003-12-17 16:13:04 +00:00
break ;
}
}
}
2003-11-21 21:57:39 +00:00
2010-04-19 10:06:48 +00:00
argSpaceSize = ( size + 1 ) * sizeof ( TCHAR * ) + ( lstrlen ( cmdLine ) + 1 ) * sizeof ( TCHAR ) ;
2013-05-26 19:47:22 +00:00
argSpace = ( TCHAR * ) MemAlloc ( argSpaceSize ) ;
2010-04-19 10:06:48 +00:00
* argv = ( TCHAR * * ) argSpace ;
2003-12-17 16:13:04 +00:00
if ( ! argSpace )
return 0 ;
2010-04-12 16:00:17 +00:00
argSpace = ( TCHAR * ) ( ( * argv ) + size ) ;
2003-12-17 16:13:04 +00:00
size - - ;
p = cmdLine ;
2010-04-19 10:06:48 +00:00
int argc ;
for ( argc = 0 ; argc < size ; argc + + ) {
( * argv ) [ argc ] = arg = argSpace ;
2010-03-24 17:22:56 +00:00
while ( ( * p = = _T ( ' ' ) ) | | ( * p = = _T ( ' \t ' ) ) ) {
2003-12-17 16:13:04 +00:00
p + + ;
}
2010-03-24 17:22:56 +00:00
if ( * p = = _T ( ' \0 ' ) ) {
2003-12-17 16:13:04 +00:00
break ;
}
inquote = 0 ;
slashes = 0 ;
while ( 1 ) {
copy = 1 ;
2010-03-24 17:22:56 +00:00
while ( * p = = _T ( ' \\ ' ) ) {
2003-12-17 16:13:04 +00:00
slashes + + ;
p + + ;
}
2010-03-24 17:22:56 +00:00
if ( * p = = _T ( ' " ' ) ) {
2003-12-17 16:13:04 +00:00
if ( ( slashes & 1 ) = = 0 ) {
copy = 0 ;
2010-03-24 17:22:56 +00:00
if ( ( inquote ) & & ( p [ 1 ] = = _T ( ' " ' ) ) ) {
2003-12-17 16:13:04 +00:00
p + + ;
copy = 1 ;
}
else {
inquote = ! inquote ;
}
}
slashes > > = 1 ;
}
while ( slashes ) {
2010-03-24 17:22:56 +00:00
* arg = _T ( ' \\ ' ) ;
2003-12-17 16:13:04 +00:00
arg + + ;
slashes - - ;
}
2010-03-24 17:22:56 +00:00
if ( ( * p = = _T ( ' \0 ' ) ) | | ( ! inquote & & ( ( * p = = _T ( ' ' ) ) | | ( * p = = _T ( ' \t ' ) ) ) ) ) {
2003-12-17 16:13:04 +00:00
break ;
}
if ( copy ! = 0 ) {
* arg = * p ;
arg + + ;
}
p + + ;
}
2010-03-24 17:22:56 +00:00
* arg = _T ( ' \0 ' ) ;
2003-12-17 16:13:04 +00:00
argSpace = arg + 1 ;
}
2010-04-19 10:06:48 +00:00
( * argv ) [ argc ] = NULL ;
2003-11-21 21:57:39 +00:00
2010-04-19 10:06:48 +00:00
return argc ;
2003-11-21 21:57:39 +00:00
}
2011-11-09 18:12:57 +00:00
void SetTitle ( HWND hwnd , const TCHAR * substr ) {
2010-03-24 17:22:56 +00:00
TCHAR title [ 64 ] ;
2021-07-27 18:56:42 +00:00
wsprintf ( title , substr ? _T ( " MakeNSISW - %s " ) : _T ( " MakeNSISW " ) , substr ) ;
2002-12-24 20:35:26 +00:00
SetWindowText ( hwnd , title ) ;
2002-08-02 10:01:35 +00:00
}
2019-10-13 16:49:35 +00:00
typedef struct { LPCSTR SoundName ; int MBFallback ; } PLAYAPPSOUNDDATA ;
static DWORD CALLBACK PlayAppSoundProc ( LPVOID ThreadParam ) {
PLAYAPPSOUNDDATA * p = ( PLAYAPPSOUNDDATA * ) ThreadParam ;
BOOL succ = PlaySoundA ( p - > SoundName , NULL , ( SND_APPLICATION | SND_ALIAS | SND_NODEFAULT ) & ~ SND_ASYNC ) ; // Cannot use SND_ASYNC because we need to detect if the sound played
if ( ! succ & & p - > MBFallback > = 0 ) succ = MessageBeep ( p - > MBFallback ) ;
MemFree ( p ) ;
return succ ;
}
void PlayAppSoundAsync ( LPCSTR SoundName , int MBFallback ) {
DWORD tid ;
PLAYAPPSOUNDDATA * p = ( PLAYAPPSOUNDDATA * ) MemAlloc ( sizeof ( PLAYAPPSOUNDDATA ) ) ;
if ( p ) {
p - > SoundName = SoundName , p - > MBFallback = MBFallback ; // Note: The string must be valid until the sound has started because we don't copy it
2021-07-28 15:07:19 +00:00
HANDLE hThread = CreateThread ( NULL , 0 , PlayAppSoundProc , p , 0 , SupportsW9X ( ) ? & tid : 0 ) ;
2019-10-13 16:49:35 +00:00
if ( hThread ) CloseHandle ( hThread ) ; else PlayAppSoundProc ( p ) ;
}
}
2002-08-02 10:01:35 +00:00
void CopyToClipboard ( HWND hwnd ) {
2015-09-28 16:08:54 +00:00
if ( ! hwnd | | ! OpenClipboard ( hwnd ) ) return ;
LRESULT len = SendDlgItemMessage ( hwnd , IDC_LOGWIN , WM_GETTEXTLENGTH , 0 , 0 ) ;
HGLOBAL mem = GlobalAlloc ( GMEM_MOVEABLE , ( + + len ) * sizeof ( TCHAR ) ) ;
2002-12-24 20:35:26 +00:00
if ( ! mem ) { CloseClipboard ( ) ; return ; }
2015-09-28 16:08:54 +00:00
TCHAR * txt = ( TCHAR * ) GlobalLock ( mem ) ;
if ( ! txt ) { CloseClipboard ( ) ; return ; }
2002-12-24 20:35:26 +00:00
EmptyClipboard ( ) ;
2015-09-28 16:08:54 +00:00
txt [ 0 ] = 0 ;
SendDlgItemMessage ( hwnd , IDC_LOGWIN , WM_GETTEXT , ( WPARAM ) ( len ) , ( LPARAM ) txt ) ;
2002-12-24 20:35:26 +00:00
GlobalUnlock ( mem ) ;
2010-03-29 14:24:47 +00:00
# ifdef _UNICODE
2015-09-28 16:08:54 +00:00
SetClipboardData ( CF_UNICODETEXT , mem ) ;
2010-03-29 14:24:47 +00:00
# else
2015-09-28 16:08:54 +00:00
SetClipboardData ( CF_TEXT , mem ) ;
2010-03-29 14:24:47 +00:00
# endif
2002-12-24 20:35:26 +00:00
CloseClipboard ( ) ;
2002-08-02 10:01:35 +00:00
}
2021-08-18 23:48:20 +00:00
# include <shlobj.h>
# if defined(MSFTEDIT_CLASS)
# include <tom.h>
# define RE_HAS_TOM
# define IID_ITextDocument NSIS_IID_ITextDocument
static const GUID IID_ITextDocument = { 0x8cc497c0 , 0xa1df , 0x11ce , { 0x80 , 0x98 , 0x0 , 0xaa , 0x0 , 0x47 , 0xbe , 0x5d } } ;
# endif
void ReleaseLogWindow ( ) {
# ifdef RE_HAS_TOM
if ( g_sdata . pLogTextDoc ) ( ( IUnknown * ) g_sdata . pLogTextDoc ) - > Release ( ) ;
# endif
}
void InitializeLogWindow ( ) {
2021-08-26 17:09:42 +00:00
HWND hRE = GetDlgItem ( g_sdata . hwnd , IDC_LOGWIN ) ;
2021-08-18 23:48:20 +00:00
# ifdef RE_HAS_TOM
IUnknown * pTD = 0 , * pREO ;
2021-08-26 17:09:42 +00:00
if ( SendMessage ( hRE , EM_GETOLEINTERFACE , 0 , ( LPARAM ) & pREO ) & & pREO ) {
2021-08-18 23:48:20 +00:00
if ( FAILED ( pREO - > QueryInterface ( IID_ITextDocument , ( void * * ) & pTD ) ) ) pTD = 0 ;
pREO - > Release ( ) ;
}
g_sdata . pLogTextDoc = pTD ;
# endif
2021-08-26 17:09:42 +00:00
SendMessage ( hRE , EM_SETTEXTMODE , TM_PLAINTEXT , 0 ) ;
2021-08-18 23:48:20 +00:00
}
2021-09-01 18:58:53 +00:00
HRESULT RicheditFreeze ( void * pITextDocument , SIZE_T Freeze )
{
HRESULT hr = E_NOTIMPL ;
# ifdef RE_HAS_TOM
ITextDocument * pTD = ( ITextDocument * ) pITextDocument ;
if ( pTD ) {
if ( Freeze )
hr = pTD - > Freeze ( 0 ) ;
else
hr = pTD - > Unfreeze ( 0 ) ;
}
# endif
return hr ;
}
2019-10-13 16:49:35 +00:00
void SetLogColor ( enum LOGCOLOR lc )
{
enum { em_seteditstyle = ( WM_USER + 204 ) , ses_extendbackcolor = 4 } ;
HWND hEd = GetDlgItem ( g_sdata . hwnd , IDC_LOGWIN ) ;
bool sysclr = lc > = LC_SYSCOLOR | | ! ReadRegSettingDW ( REGCOLORIZE , true ) ;
2019-10-16 19:55:33 +00:00
static const COLORREF clrs [ ] = { RGB ( 0 , 50 , 0 ) , RGB ( 210 , 255 , 210 ) , RGB ( 50 , 30 , 0 ) , RGB ( 255 , 220 , 190 ) , RGB ( 50 , 0 , 0 ) , RGB ( 255 , 210 , 210 ) } ;
2019-10-13 16:49:35 +00:00
CHARFORMAT cf ;
cf . cbSize = sizeof ( cf ) , cf . dwMask = CFM_COLOR ;
cf . dwEffects = sysclr ? CFE_AUTOCOLOR : 0 ;
cf . crTextColor = sysclr ? RGB ( 0 , 0 , 0 ) : clrs [ ( lc * 2 ) + 0 ] ;
SendMessage ( hEd , em_seteditstyle , sysclr ? 0 : ses_extendbackcolor , ses_extendbackcolor ) ;
SendMessage ( hEd , EM_SETCHARFORMAT , 0 , ( LPARAM ) & cf ) ;
SendMessage ( hEd , EM_SETBKGNDCOLOR , sysclr , sysclr ? sysclr /*Irrelevant*/ : clrs [ ( lc * 2 ) + 1 ] ) ;
}
2002-08-02 10:01:35 +00:00
void ClearLog ( HWND hwnd ) {
2010-03-24 17:22:56 +00:00
SetDlgItemText ( hwnd , IDC_LOGWIN , _T ( " " ) ) ;
2019-10-13 16:49:35 +00:00
SetLogColor ( LC_SYSCOLOR ) ;
2018-11-07 00:26:29 +00:00
SendMessage ( g_sdata . hwnd , WM_MAKENSIS_UPDATEUISTATE , 0 , 0 ) ;
2002-08-02 10:01:35 +00:00
}
2010-03-24 17:22:56 +00:00
void LogMessage ( HWND hwnd , const TCHAR * str ) {
2021-08-18 23:48:20 +00:00
HWND hLogWin = GetDlgItem ( hwnd , IDC_LOGWIN ) ;
# ifdef RE_HAS_TOM
2021-08-26 17:09:42 +00:00
HRESULT hr = ( HRESULT ) SendMessage ( hwnd , WM_MAKENSIS_FREEZEEDITOR , 0 , true ) ; // Force COM calls to UI thread
2021-08-18 23:48:20 +00:00
# endif
SendMessage ( hLogWin , EM_SETSEL , g_sdata . logLength , g_sdata . logLength ) ;
SendMessage ( hLogWin , EM_REPLACESEL , 0 , ( LPARAM ) str ) ;
SendMessage ( hLogWin , EM_SCROLLCARET , 0 , 0 ) ;
# ifdef RE_HAS_TOM
2021-08-26 17:09:42 +00:00
if ( SUCCEEDED ( hr ) ) SendMessage ( hwnd , WM_MAKENSIS_FREEZEEDITOR , 0 , false ) ;
2021-08-18 23:48:20 +00:00
# endif
2002-12-24 20:35:26 +00:00
g_sdata . logLength + = lstrlen ( str ) ;
2002-08-02 10:01:35 +00:00
}
2010-03-24 17:22:56 +00:00
void ErrorMessage ( HWND hwnd , const TCHAR * str ) {
2002-12-24 20:35:26 +00:00
if ( ! str ) return ;
2010-03-24 17:22:56 +00:00
TCHAR buf [ 1028 ] ;
2015-09-28 16:08:54 +00:00
wsprintf ( buf , _T ( " [Error] %s \r \n " ) , str ) ;
2002-12-24 20:35:26 +00:00
LogMessage ( hwnd , buf ) ;
2002-08-02 10:01:35 +00:00
}
2018-10-16 16:55:37 +00:00
static void CenterOnParent ( HWND hwnd , HWND hParent )
{
RECT r ;
GetWindowRect ( hwnd , & r ) ;
UINT w = ( r . right - r . left ) , h = ( r . bottom - r . top ) , swp = SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE ;
if ( GetWindowRect ( hParent , & r ) )
SetWindowPos ( hwnd , 0 , r . left + ( ( r . right - r . left ) / 2 ) - ( w / 2 ) , r . top + ( ( r . bottom - r . top ) / 2 ) - ( h / 2 ) , 0 , 0 , swp ) ;
}
void CenterOnParent ( HWND hwnd )
{
CenterOnParent ( hwnd , GetWindow ( hwnd , GW_OWNER ) ) ;
}
2013-08-07 19:26:03 +00:00
void SetDialogFocus ( HWND hDlg , HWND hCtl )
{
//blogs.msdn.com/b/oldnewthing/archive/2004/08/02/205624.aspx
SendMessage ( hDlg , WM_NEXTDLGCTL , ( WPARAM ) hCtl , TRUE ) ;
}
2018-11-04 21:25:52 +00:00
HWND GetComboEdit ( HWND hCB )
{
/* CB_GETCOMBOBOXINFO crashes on 64-bit NT 5.x (KB947841).
We are left with GetComboBoxInfo ( ) , FindWindowEx ( ) * 2 and
ChildWindowFromPoint ( h , { 1 , 1 } ) ( docs . microsoft . com / en - us / windows / desktop / Controls / subclass - a - combo - box # ) . */
if ( ! SupportsWNT4 ( ) & & ! SupportsW95 ( ) )
{
COMBOBOXINFO cbi ;
cbi . cbSize = FIELD_OFFSET ( COMBOBOXINFO , hwndList ) + sizeof ( HWND ) ;
BOOL succ = GetComboBoxInfo ( hCB , & cbi ) ;
return succ ? cbi . hwndItem : ( HWND ) ( INT_PTR ) succ ;
}
HWND hList = FindWindowEx ( hCB , 0 , 0 , 0 ) ;
return FindWindowEx ( hCB , hList , 0 , 0 ) ;
}
2021-08-20 11:46:56 +00:00
void EnableDisableItems ( int on )
2013-08-07 19:26:03 +00:00
{
2021-08-20 11:46:56 +00:00
HWND hwndDlg = g_sdata . hwnd ;
const HWND hCloseBtn = GetDlgItem ( hwndDlg , IDCANCEL ) ;
const HWND hTestBtn = GetDlgItem ( hwndDlg , IDC_TEST ) ;
2013-08-07 19:26:03 +00:00
const HMENU hMenu = g_sdata . menu ;
const UINT mf = ( ! on ? MF_GRAYED : MF_ENABLED ) ;
const UINT nmf = ( ! on ? MF_ENABLED : MF_GRAYED ) ;
const bool compsuccess = ! g_sdata . retcode & & on ;
if ( ! on ) g_sdata . focused_hwnd = GetFocus ( ) ;
if ( compsuccess | | ! on ) {
EnableWindow ( hTestBtn , on ) ;
EnableToolBarButton ( IDM_TEST , on ) ;
EnableMenuItem ( hMenu , IDM_TEST , mf ) ;
}
EnableMenuItem ( hMenu , IDM_CANCEL , nmf ) ;
2021-08-20 11:46:56 +00:00
EnableWindow ( hCloseBtn , false ) ;
2013-08-07 19:26:03 +00:00
static const PACKEDCMDID_T cmds [ ] = {
PACKCMDID ( IDM_EXIT ) , PACKCMDID ( IDM_LOADSCRIPT ) , PACKCMDID ( IDM_EDITSCRIPT ) ,
2020-04-21 18:53:55 +00:00
PACKCMDID ( IDM_SAVE ) , PACKCMDID ( IDM_CLEARLOG ) , PACKCMDID ( IDM_GUIDGEN ) ,
2013-08-07 19:26:03 +00:00
PACKCMDID ( IDM_COMPRESSOR ) , PACKCMDID ( IDM_COMPRESSOR_SUBMENU ) ,
PACKCMDID ( IDM_RECOMPILE ) , PACKCMDID ( IDM_RECOMPILE_TEST )
2013-05-26 19:47:22 +00:00
} ;
2013-08-07 19:26:03 +00:00
for ( UINT i = 0 ; i < COUNTOF ( cmds ) ; + + i ) {
UINT id = UNPACKCMDID ( cmds [ i ] ) ;
EnableMenuItem ( hMenu , id , mf ) ;
if ( IDM_COPYSELECTED ! = id & & IDM_COMPRESSOR_SUBMENU ! = id )
EnableToolBarButton ( id , on ) ;
2002-12-24 20:35:26 +00:00
}
2013-08-07 19:26:03 +00:00
2021-08-20 11:46:56 +00:00
SendMessage ( hwndDlg , WM_MAKENSIS_UPDATEUISTATE , 0 , 0 ) ;
2018-11-07 00:26:29 +00:00
EnableMenuItem ( hMenu , IDM_FILE , mf ) ; // Disable the whole File menu because of the MRU list
2021-08-20 11:46:56 +00:00
DrawMenuBar ( hwndDlg ) ;
2018-11-07 00:26:29 +00:00
2013-08-07 19:26:03 +00:00
HWND hFocus = g_sdata . focused_hwnd , hOptimal = hTestBtn ;
if ( on & & hCloseBtn = = hFocus ) hFocus = hOptimal ;
2021-08-20 11:46:56 +00:00
if ( ! IsWindowEnabled ( hFocus ) ) hFocus = GetDlgItem ( hwndDlg , IDC_LOGWIN ) ;
SetDialogFocus ( hwndDlg , hOptimal ) ;
SetDialogFocus ( hwndDlg , hFocus ) ;
SetTimer ( hwndDlg , TID_CONFIGURECLOSEORABORT , 1000 , 0 ) ;
2002-08-02 10:01:35 +00:00
}
2003-11-19 04:38:14 +00:00
void SetCompressorStats ( )
{
2014-10-12 20:09:35 +00:00
DWORD_PTR line_count , i ;
2010-03-24 17:22:56 +00:00
TCHAR buf [ 1024 ] ;
2003-11-19 04:38:14 +00:00
bool found = false ;
line_count = SendDlgItemMessage ( g_sdata . hwnd , IDC_LOGWIN , EM_GETLINECOUNT , 0 , 0 ) ;
for ( i = 0 ; i < line_count ; i + + ) {
2014-10-26 18:57:52 +00:00
* ( ( LPWORD ) buf ) = COUNTOF ( buf ) ;
2014-10-23 15:34:10 +00:00
LRESULT cchLine = SendDlgItemMessage ( g_sdata . hwnd , IDC_LOGWIN , EM_GETLINE , ( WPARAM ) i , ( LPARAM ) buf ) ;
buf [ cchLine ] = _T ( ' \0 ' ) ;
2003-11-19 04:38:14 +00:00
if ( found ) {
DWORD len = lstrlen ( TOTAL_SIZE_COMPRESSOR_STAT ) ;
lstrcat ( g_sdata . compressor_stats , buf ) ;
2010-04-12 16:00:17 +00:00
if ( ! StrCmpN ( buf , TOTAL_SIZE_COMPRESSOR_STAT , len ) ) {
2003-11-19 04:38:14 +00:00
break ;
}
}
else {
DWORD len = lstrlen ( EXE_HEADER_COMPRESSOR_STAT ) ;
2010-04-12 16:00:17 +00:00
if ( ! StrCmpN ( buf , EXE_HEADER_COMPRESSOR_STAT , len ) ) {
2003-11-19 04:38:14 +00:00
found = true ;
2010-03-24 17:22:56 +00:00
lstrcpy ( g_sdata . compressor_stats , _T ( " \n \n " ) ) ;
2003-11-19 04:38:14 +00:00
lstrcat ( g_sdata . compressor_stats , buf ) ;
}
}
}
}
2018-11-07 00:26:29 +00:00
static void SetUIState_NoScript ( )
{
static const PACKEDCMDID_T cmds [ ] = {
PACKCMDID ( IDM_RECOMPILE ) , PACKCMDID ( IDM_RECOMPILE_TEST ) , PACKCMDID ( IDM_TEST ) ,
PACKCMDID ( IDM_BROWSESCR ) , PACKCMDID ( IDM_EDITSCRIPT )
} ;
for ( UINT i = 0 ; i < COUNTOF ( cmds ) ; + + i )
EnableUICommand ( UNPACKCMDID ( cmds [ i ] ) , FALSE ) ;
EnableWindow ( GetDlgItem ( g_sdata . hwnd , IDC_TEST ) , FALSE ) ;
}
2002-08-02 10:01:35 +00:00
void CompileNSISScript ( ) {
2002-12-24 20:35:26 +00:00
DragAcceptFiles ( g_sdata . hwnd , FALSE ) ;
ClearLog ( g_sdata . hwnd ) ;
SetTitle ( g_sdata . hwnd , NULL ) ;
2018-11-07 00:26:29 +00:00
PostMessage ( g_sdata . hwnd , WM_MAKENSIS_UPDATEUISTATE , 0 , 0 ) ;
2020-04-21 18:53:55 +00:00
if ( ! g_sdata . script [ 0 ] ) {
2002-12-24 20:35:26 +00:00
LogMessage ( g_sdata . hwnd , USAGE ) ;
2018-11-07 00:26:29 +00:00
SetUIState_NoScript ( ) ;
2002-12-24 20:35:26 +00:00
DragAcceptFiles ( g_sdata . hwnd , TRUE ) ;
return ;
}
2007-04-10 21:07:21 +00:00
if ( ! g_sdata . compile_command ) {
2010-03-24 17:22:56 +00:00
TCHAR * symbols = BuildSymbols ( ) ;
TCHAR compressor [ 40 ] ;
2013-05-26 19:47:22 +00:00
2014-05-19 22:03:09 +00:00
compressor [ 0 ] = _T ( ' \0 ' ) ;
if ( * g_sdata . compressor_name )
2010-03-24 17:22:56 +00:00
wsprintf ( compressor , _T ( " /X \" SetCompressor /FINAL %s \" " ) , g_sdata . compressor_name ) ;
2003-11-19 04:38:14 +00:00
2010-03-24 17:22:56 +00:00
TCHAR * args = ( TCHAR * ) GlobalLock ( g_sdata . script_cmd_args ) ;
2007-04-18 18:19:02 +00:00
2010-03-29 14:24:47 +00:00
size_t byteSize = sizeof ( TCHAR ) * (
2013-06-08 18:48:38 +00:00
/* makensis.exe */ lstrlen ( EXENAME ) + /* space */ 1 +
/* script path */ lstrlen ( g_sdata . script ) + /* space */ 1 +
/* script cmd args */ lstrlen ( args ) + /* space */ 1 +
/* defines /Dblah=... */ lstrlen ( symbols ) + /* space */ 1 +
/* /XSetCompressor... */ lstrlen ( compressor ) + /* space */ 1 +
/* /V + UINT8 */ 2 + 3 + /* space */ 1 +
2010-04-19 10:06:48 +00:00
/* /NOTIFYHWND + HWND */ COUNTOF ( _T ( " /NOTIFYHWND -4294967295 " ) ) + /* space */ 1
2010-03-29 14:24:47 +00:00
+ 6 ) ; /* for -- \"\" and NULL */
2013-05-26 19:47:22 +00:00
g_sdata . compile_command = ( TCHAR * ) MemAlloc ( byteSize ) ;
2007-04-10 21:07:21 +00:00
wsprintf (
g_sdata . compile_command ,
2013-06-08 18:48:38 +00:00
_T ( " %s /V%u %s %s /NOTIFYHWND %d %s -- \" %s \" " ) ,
2007-04-10 21:07:21 +00:00
EXENAME ,
2013-06-08 18:48:38 +00:00
g_sdata . verbosity ,
2007-04-10 21:07:21 +00:00
compressor ,
symbols ,
g_sdata . hwnd ,
2007-04-18 18:19:02 +00:00
args ,
2007-04-10 21:07:21 +00:00
g_sdata . script
) ;
2007-09-18 20:14:25 +00:00
GlobalUnlock ( g_sdata . script_cmd_args ) ;
2013-05-26 19:47:22 +00:00
MemFree ( symbols ) ;
2002-12-24 20:35:26 +00:00
}
2013-05-26 19:47:22 +00:00
MemSafeFree ( g_sdata . input_script ) ;
MemSafeFree ( g_sdata . output_exe ) ;
2002-12-24 20:35:26 +00:00
g_sdata . input_script = 0 ;
g_sdata . output_exe = 0 ;
g_sdata . warnings = 0 ;
g_sdata . logLength = 0 ;
// Disable buttons during compile
DisableItems ( g_sdata . hwnd ) ;
2013-05-26 19:47:22 +00:00
DWORD tid ;
g_sdata . thread = CreateThread ( NULL , 0 , MakeNSISProc , 0 , 0 , & tid ) ;
2002-08-02 10:01:35 +00:00
}
2015-09-28 16:08:54 +00:00
static DWORD RegWriteString ( HKEY hKey , LPCTSTR Name , LPCTSTR Data )
{
const DWORD cb = ( lstrlen ( Data ) + 1 ) * sizeof ( * Data ) ;
return RegSetValueEx ( hKey , Name , 0 , REG_SZ , ( LPBYTE ) Data , cb ) ;
}
static DWORD RegReadString ( HKEY hKey , LPCTSTR Name , LPTSTR Buf , DWORD cbBufSize ) {
DWORD ec , rt , cb = cbBufSize , cbCh = sizeof ( * Buf ) ;
ec = RegQueryValueEx ( hKey , Name , NULL , & rt , ( BYTE * ) Buf , & cb ) ;
if ( cbBufSize ) {
#if 0
if ( rt = = REG_DWORD ) cb = cbCh * wsprintf ( Buf , _T ( " %d " ) , * ( ( INT32 * ) Buf ) ) ;
# endif
if ( cb + cbCh < cbBufSize ) Buf [ cb / cbCh ] = _T ( ' \0 ' ) ; // Add a \0 after the data if there is room
Buf [ ( cbBufSize / cbCh ) - 1 ] = _T ( ' \0 ' ) ; // Always \0 terminate, truncating data if necessary
}
return ec ;
}
2021-01-17 20:57:20 +00:00
DWORD RegOpenKeyForReading ( HKEY hRoot , LPCTSTR SubKey , HKEY * pKey ) {
2015-09-28 16:08:54 +00:00
return RegOpenKeyEx ( hRoot , SubKey , 0 , KEY_READ , pKey ) ;
}
2007-01-24 12:51:26 +00:00
static bool InternalOpenRegSettingsKey ( HKEY root , HKEY & key , bool create ) {
if ( create ) {
if ( RegCreateKey ( root , REGKEY , & key ) = = ERROR_SUCCESS )
return true ;
} else {
2015-09-28 16:08:54 +00:00
if ( RegOpenKeyForReading ( root , REGKEY , & key ) = = ERROR_SUCCESS )
2007-01-24 12:51:26 +00:00
return true ;
}
return false ;
}
bool OpenRegSettingsKey ( HKEY & hKey , bool create ) {
2015-09-28 16:08:54 +00:00
return InternalOpenRegSettingsKey ( REGSEC , hKey , create )
| | InternalOpenRegSettingsKey ( REGSECDEF , hKey , create ) ;
2007-01-24 12:51:26 +00:00
}
2013-06-08 18:48:38 +00:00
DWORD ReadRegSettingDW ( LPCTSTR name , const DWORD defval ) {
DWORD val = defval , siz = sizeof ( val ) , typ ;
HKEY hKey ;
if ( OpenRegSettingsKey ( hKey ) ) {
if ( RegQueryValueEx ( hKey , name , NULL , & typ , ( LPBYTE ) & val , & siz ) | | REG_DWORD ! = typ | | sizeof ( val ) ! = siz )
val = defval ;
RegCloseKey ( hKey ) ;
}
return val ;
}
2002-08-02 10:01:35 +00:00
void RestoreWindowPos ( HWND hwnd ) {
2002-12-24 20:35:26 +00:00
HKEY hKey ;
WINDOWPLACEMENT p ;
2007-01-24 12:51:26 +00:00
if ( OpenRegSettingsKey ( hKey ) ) {
2002-12-24 20:35:26 +00:00
DWORD l = sizeof ( p ) ;
DWORD t ;
2010-03-24 17:22:56 +00:00
if ( ( RegQueryValueEx ( hKey , REGLOC , NULL , & t , ( LPBYTE ) & p , & l ) = = ERROR_SUCCESS ) & & ( t = = REG_BINARY ) & & ( l = = sizeof ( p ) ) ) {
2004-01-20 15:03:23 +00:00
int width , height ;
2004-01-20 17:00:48 +00:00
int windowWidth , windowHeight ;
2004-01-20 15:03:23 +00:00
width = GetSystemMetrics ( SM_CXFULLSCREEN ) ;
height = GetSystemMetrics ( SM_CYFULLSCREEN ) ;
height + = GetSystemMetrics ( SM_CYCAPTION ) ;
2004-01-20 17:00:48 +00:00
windowWidth = p . rcNormalPosition . right - p . rcNormalPosition . left ;
if ( windowWidth > width ) {
2004-01-20 15:03:23 +00:00
p . rcNormalPosition . left = 0 ;
p . rcNormalPosition . right = width ;
}
2004-01-20 18:10:30 +00:00
else if ( p . rcNormalPosition . right > width ) {
p . rcNormalPosition . left = width - windowWidth ;
p . rcNormalPosition . right = width ;
}
else if ( p . rcNormalPosition . left < 0 ) {
p . rcNormalPosition . left = 0 ;
p . rcNormalPosition . right = windowWidth ;
2004-01-20 15:03:23 +00:00
}
2004-01-20 17:00:48 +00:00
windowHeight = p . rcNormalPosition . bottom - p . rcNormalPosition . top ;
if ( windowHeight > height ) {
2004-01-20 15:03:23 +00:00
p . rcNormalPosition . top = 0 ;
p . rcNormalPosition . bottom = height ;
}
2004-01-20 18:10:30 +00:00
else if ( p . rcNormalPosition . bottom > height ) {
p . rcNormalPosition . top = height - windowHeight ;
p . rcNormalPosition . bottom = height ;
}
else if ( p . rcNormalPosition . top < 0 ) {
p . rcNormalPosition . top = 0 ;
p . rcNormalPosition . bottom = windowHeight ;
2004-01-20 15:03:23 +00:00
}
2002-12-24 20:35:26 +00:00
p . length = sizeof ( p ) ;
SetWindowPlacement ( hwnd , & p ) ;
}
RegCloseKey ( hKey ) ;
}
2002-08-02 10:01:35 +00:00
}
void SaveWindowPos ( HWND hwnd ) {
2002-12-24 20:35:26 +00:00
HKEY hKey ;
WINDOWPLACEMENT p ;
p . length = sizeof ( p ) ;
2021-01-17 20:57:20 +00:00
if ( ! GetWindowPlacement ( hwnd , & p ) ) p . length = 0 ;
if ( p . length & & CreateRegSettingsKey ( hKey ) ) {
RegSetValueEx ( hKey , REGLOC , 0 , REG_BINARY , ( LPBYTE ) & p , p . length ) ;
2002-12-24 20:35:26 +00:00
RegCloseKey ( hKey ) ;
}
2002-08-02 10:01:35 +00:00
}
2002-09-09 16:43:45 +00:00
2015-09-28 16:08:54 +00:00
void RestoreSymbols ( ) {
2003-12-30 19:43:15 +00:00
g_sdata . symbols = LoadSymbolSet ( NULL ) ;
}
2015-09-28 16:08:54 +00:00
void SaveSymbols ( ) {
2003-12-30 19:43:15 +00:00
SaveSymbolSet ( NULL , g_sdata . symbols ) ;
}
2015-09-28 16:08:54 +00:00
# define SYMSET_SUBKEY_MAXLEN (100 + SYMSETNAME_MAXLEN) // REGSYMSUBKEY + [\name]
static int CreateSymbolSetSubkeyPath ( const TCHAR * name , TCHAR * buffer ) {
return wsprintf ( buffer , name ? _T ( " %s \\ %s " ) : _T ( " %s " ) , REGSYMSUBKEY , name ) ;
}
void FreeSymbolSet ( TCHAR * * symbols ) {
if ( symbols ) {
for ( SIZE_T i = 0 ; symbols [ i ] ; + + i )
MemSafeFree ( symbols [ i ] ) ;
GlobalFree ( ( HGLOBAL ) symbols ) ;
2003-12-30 19:43:15 +00:00
}
}
2015-09-28 16:08:54 +00:00
void DeleteSymbolSet ( const TCHAR * name ) {
2003-12-17 16:13:04 +00:00
HKEY hKey ;
2015-09-28 16:08:54 +00:00
if ( name & & OpenRegSettingsKey ( hKey ) ) {
TCHAR subkey [ SYMSET_SUBKEY_MAXLEN + 1 ] ;
CreateSymbolSetSubkeyPath ( name , subkey ) ;
RegDeleteKey ( hKey , subkey ) ;
RegCloseKey ( hKey ) ;
}
}
TCHAR * * LoadSymbolSet ( const TCHAR * name ) {
HKEY hCfgKey , hSymKey ;
2010-03-24 17:22:56 +00:00
TCHAR * * symbols = NULL ;
2015-09-28 16:08:54 +00:00
if ( OpenRegSettingsKey ( hCfgKey ) ) {
TCHAR subkey [ SYMSET_SUBKEY_MAXLEN + 1 ] ;
CreateSymbolSetSubkeyPath ( name , subkey ) ;
if ( RegOpenKeyForReading ( hCfgKey , subkey , & hSymKey ) = = ERROR_SUCCESS ) {
TCHAR bufName [ 8 ] ;
for ( DWORD i = 0 , rt , cbBuf , cbData ; ; ) {
cbBuf = sizeof ( bufName ) ;
if ( RegEnumValue ( hSymKey , i , bufName , & cbBuf , NULL , & rt , NULL , & cbData ) = = ERROR_SUCCESS & & rt = = REG_SZ ) {
2003-12-30 19:43:15 +00:00
if ( symbols ) {
2015-09-28 16:08:54 +00:00
HGLOBAL newmem = GlobalReAlloc ( symbols , ( i + 2 ) * sizeof ( TCHAR * ) , GMEM_MOVEABLE | GMEM_ZEROINIT ) ;
if ( ! newmem ) FreeSymbolSet ( symbols ) ;
symbols = ( TCHAR * * ) newmem ;
2003-12-30 19:43:15 +00:00
}
else {
2015-09-28 16:08:54 +00:00
symbols = ( TCHAR * * ) GlobalAlloc ( GPTR , ( i + 2 ) * sizeof ( TCHAR * ) ) ;
2003-12-30 19:43:15 +00:00
}
2015-09-28 16:08:54 +00:00
if ( ! symbols ) break ; // Out of memory, abort!
symbols [ i ] = ( TCHAR * ) MemAllocZI ( cbData + = sizeof ( TCHAR ) ) ;
if ( ! symbols [ i ] | | RegReadString ( hSymKey , bufName , symbols [ i ] , cbData ) ) {
FreeSymbolSet ( symbols ) ;
2003-12-30 19:43:15 +00:00
break ;
2003-12-17 16:13:04 +00:00
}
2015-09-28 16:08:54 +00:00
symbols [ + + i ] = NULL ; // The symbols array is terminated by a NULL pointer
2003-12-30 19:43:15 +00:00
}
2015-09-28 16:08:54 +00:00
else
2003-12-30 19:43:15 +00:00
break ;
2003-12-17 16:13:04 +00:00
}
2015-09-28 16:08:54 +00:00
RegCloseKey ( hSymKey ) ;
2003-05-28 04:51:20 +00:00
}
2015-09-28 16:08:54 +00:00
RegCloseKey ( hCfgKey ) ;
2003-12-17 16:13:04 +00:00
}
2003-12-30 19:43:15 +00:00
return symbols ;
2003-05-28 04:51:20 +00:00
}
2015-09-28 16:08:54 +00:00
void SaveSymbolSet ( const TCHAR * name , TCHAR * * symbols ) {
HKEY hCfgKey , hSymKey ;
if ( CreateRegSettingsKey ( hCfgKey ) ) {
TCHAR subkey [ SYMSET_SUBKEY_MAXLEN + 1 ] , bufName [ 8 ] ;
CreateSymbolSetSubkeyPath ( name , subkey ) ;
if ( RegOpenKey ( hCfgKey , subkey , & hSymKey ) = = ERROR_SUCCESS ) {
// Cannot use DeleteSymbolSet because name might be NULL and named sets are stored inside the base symbols key
for ( DWORD cb ; ; ) {
cb = sizeof ( bufName ) ;
if ( RegEnumValue ( hSymKey , 0 , bufName , & cb , NULL , NULL , NULL , NULL ) ! = ERROR_SUCCESS ) break ;
RegDeleteValue ( hSymKey , bufName ) ;
2003-12-30 19:43:15 +00:00
}
2015-09-28 16:08:54 +00:00
RegCloseKey ( hSymKey ) ;
2003-12-30 19:43:15 +00:00
}
if ( symbols ) {
2015-09-28 16:08:54 +00:00
if ( RegCreateKey ( hCfgKey , subkey , & hSymKey ) = = ERROR_SUCCESS ) {
for ( SIZE_T i = 0 ; symbols [ i ] ; + + i ) {
wsprintf ( bufName , _T ( " %d " ) , ( INT ) i ) ;
RegWriteString ( hSymKey , bufName , symbols [ i ] ) ;
2003-05-28 04:51:20 +00:00
}
2015-09-28 16:08:54 +00:00
RegCloseKey ( hSymKey ) ;
2003-12-17 16:13:04 +00:00
}
2003-05-28 04:51:20 +00:00
}
2015-09-28 16:08:54 +00:00
RegCloseKey ( hCfgKey ) ;
2003-12-17 16:13:04 +00:00
}
2003-05-28 04:51:20 +00:00
}
2002-09-09 16:43:45 +00:00
void ResetObjects ( ) {
2013-05-26 19:47:22 +00:00
MemSafeFree ( g_sdata . compile_command ) ;
g_sdata . compile_command = NULL ;
2003-05-28 04:51:20 +00:00
g_sdata . warnings = FALSE ;
g_sdata . retcode = - 1 ;
g_sdata . thread = NULL ;
}
2003-12-30 19:43:15 +00:00
void ResetSymbols ( ) {
2015-09-28 16:08:54 +00:00
FreeSymbolSet ( g_sdata . symbols ) ;
g_sdata . symbols = NULL ;
2002-09-19 15:29:16 +00:00
}
2013-05-04 13:32:47 +00:00
void FreeSpawn ( PROCESS_INFORMATION * pPI , HANDLE hRd , HANDLE hWr ) {
if ( pPI ) {
GetExitCodeProcess ( pPI - > hProcess , & pPI - > dwProcessId ) ;
CloseHandle ( pPI - > hProcess ) ;
CloseHandle ( pPI - > hThread ) ;
}
CloseHandle ( hRd ) ;
CloseHandle ( hWr ) ;
}
BOOL InitSpawn ( STARTUPINFO & si , HANDLE & hRd , HANDLE & hWr ) {
2019-10-16 19:55:33 +00:00
OSVERSIONINFO osv ;
GetVersionEx ( ( osv . dwOSVersionInfoSize = sizeof ( osv ) , & osv ) ) ;
2013-05-04 13:32:47 +00:00
const bool winnt = VER_PLATFORM_WIN32_NT = = osv . dwPlatformId ;
memset ( & si , 0 , sizeof ( STARTUPINFO ) ) ;
si . cb = sizeof ( STARTUPINFO ) ;
GetStartupInfo ( & si ) ;
si . dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW ;
si . wShowWindow = SW_HIDE ;
SECURITY_ATTRIBUTES sa = { sizeof ( sa ) } ;
SECURITY_DESCRIPTOR sd ;
if ( winnt ) {
InitializeSecurityDescriptor ( & sd , SECURITY_DESCRIPTOR_REVISION ) ;
SetSecurityDescriptorDacl ( & sd , true , NULL , false ) ;
sa . lpSecurityDescriptor = & sd ;
}
sa . bInheritHandle = true ;
BOOL okp = CreatePipe ( & hRd , & hWr , & sa , 0 ) ;
si . hStdOutput = hWr , si . hStdError = hWr ;
si . hStdInput = INVALID_HANDLE_VALUE ;
return okp ;
}
2002-09-19 15:29:16 +00:00
int InitBranding ( ) {
2013-05-04 13:32:47 +00:00
const TCHAR * opt = _T ( " /version " ) ;
UINT cch = lstrlen ( EXENAME ) + lstrlen ( opt ) + 1 ;
2013-05-26 19:47:22 +00:00
TCHAR * cmd = ( TCHAR * ) MemAlloc ( cch * sizeof ( TCHAR ) ) ;
if ( ! cmd ) return 0 ;
lstrcpy ( cmd , EXENAME ) ;
lstrcat ( cmd , opt ) ;
STARTUPINFO si ;
HANDLE newstdout , read_stdout ;
char szBuf [ 1024 ] , retval = 0 ;
if ( InitSpawn ( si , read_stdout , newstdout ) ) {
PROCESS_INFORMATION pi , * ppi = 0 ;
if ( CreateProcess ( 0 , cmd , 0 , 0 , TRUE , CREATE_NEW_CONSOLE , 0 , 0 , & si , & pi ) ) {
DWORD dwRead = 0 ;
if ( WAIT_OBJECT_0 = = WaitForSingleObject ( pi . hProcess , 10000 ) ) {
ReadFile ( read_stdout , szBuf , sizeof ( szBuf ) - 1 , & dwRead , NULL ) ;
retval = 1 ;
}
szBuf [ dwRead ] = 0 , ppi = & pi ;
int len = lstrlenA ( szBuf ) ;
2017-10-24 21:23:46 +00:00
while ( len & & ( ( szBuf [ len - 1 ] = = ' \n ' ) | ( szBuf [ len - 1 ] = = ' \r ' ) ) ) szBuf [ - - len ] = ' \0 ' ;
2013-05-26 19:47:22 +00:00
if ( ! len ) retval = 0 ;
g_sdata . branding = ( TCHAR * ) MemAlloc ( ( len + 6 ) * sizeof ( TCHAR ) ) ; // LEAKED
wsprintf ( g_sdata . branding , _T ( " NSIS %hs " ) , szBuf ) ;
g_sdata . brandingv = ( char * ) MemAlloc ( len + 1 ) ; // LEAKED
lstrcpyA ( g_sdata . brandingv , szBuf ) ;
2002-12-24 20:35:26 +00:00
}
2013-05-26 19:47:22 +00:00
FreeSpawn ( ppi , read_stdout , newstdout ) ;
2002-12-24 20:35:26 +00:00
}
2013-05-26 19:47:22 +00:00
MemFree ( cmd ) ;
return retval ;
2002-09-19 15:29:16 +00:00
}
2021-08-20 14:56:26 +00:00
LRESULT SetTooltipText ( HWND hWnd , UINT_PTR Id , LPCTSTR Text ) {
TOOLINFO ti ;
ti . cbSize = SizeOfStruct ( ti ) ;
ti . uFlags = Id > 0x7fff ? TTF_IDISHWND : 0 ;
ti . hwnd = hWnd , ti . uId = Id ;
ti . hinst = g_sdata . hInstance , ti . lpszText = const_cast < LPTSTR > ( Text ) ;
return SendMessage ( g_tip . tip , TTM_UPDATETIPTEXT , 0 , ( LPARAM ) ( LPTOOLINFO ) & ti ) ;
}
void UpdateCloseButtonTooltip ( ) {
LPCTSTR txt = g_sdata . thread ? _T ( " " ) : CLOSEBTN_TIPTEXT ;
SetTooltipText ( g_tip . tip_p , ( UINT_PTR ) GetDlgItem ( g_sdata . hwnd , IDCANCEL ) , txt ) ;
}
2002-09-19 15:29:16 +00:00
void InitTooltips ( HWND h ) {
2002-12-24 20:35:26 +00:00
if ( h = = NULL ) return ;
2021-08-20 14:56:26 +00:00
InitCCEx ( ICC_BAR_CLASSES ) ;
DWORD s = WS_POPUP | WS_BORDER | TTS_ALWAYSTIP , xs = WS_EX_TOOLWINDOW | WS_EX_TOPMOST ;
g_tip . hook = 0 ;
2002-12-24 20:35:26 +00:00
g_tip . tip_p = h ;
2021-08-20 14:56:26 +00:00
g_tip . tip = CreateWindowEx ( xs , TOOLTIPS_CLASS , NULL , s , 0 , 0 , 0 , 0 , h , NULL , HINST_APPLICATION , NULL ) ;
2002-12-24 20:35:26 +00:00
if ( ! g_tip . tip ) return ;
2021-08-20 14:56:26 +00:00
g_tip . hook = SetWindowsHookEx ( WH_GETMESSAGE , TipHookProc , NULL , GetCurrentThreadId ( ) ) ;
AddTip ( GetDlgItem ( h , IDCANCEL ) , CLOSEBTN_TIPTEXT ) ;
AddTip ( GetDlgItem ( h , IDC_TEST ) , TESTBTN_TIPTEXT ) ;
2003-05-28 04:51:20 +00:00
AddToolBarTooltips ( ) ;
2002-09-19 15:29:16 +00:00
}
void DestroyTooltips ( ) {
2002-12-24 20:35:26 +00:00
UnhookWindowsHookEx ( g_tip . hook ) ;
2002-09-19 15:29:16 +00:00
}
2021-08-20 14:56:26 +00:00
void AddTip ( HWND hWnd , LPCTSTR lpszToolTip ) {
2002-12-24 20:35:26 +00:00
TOOLINFO ti ;
2021-08-20 14:56:26 +00:00
ti . cbSize = SizeOfStruct ( ti ) ;
2002-12-24 20:35:26 +00:00
ti . uFlags = TTF_IDISHWND ;
ti . hwnd = g_tip . tip_p ;
2015-05-14 20:17:14 +00:00
ti . uId = ( UINT_PTR ) hWnd ;
2016-03-07 14:34:21 +00:00
ti . lpszText = const_cast < LPTSTR > ( lpszToolTip ) ;
2002-12-24 20:35:26 +00:00
SendMessage ( g_tip . tip , TTM_ADDTOOL , 0 , ( LPARAM ) ( LPTOOLINFO ) & ti ) ;
2002-09-19 15:29:16 +00:00
}
LRESULT CALLBACK TipHookProc ( int nCode , WPARAM wParam , LPARAM lParam ) {
2002-12-24 20:35:26 +00:00
if ( nCode < 0 ) return CallNextHookEx ( g_tip . hook , nCode , wParam , lParam ) ;
switch ( ( ( MSG * ) lParam ) - > message ) {
case WM_MOUSEMOVE :
if ( IsChild ( g_tip . tip_p , ( ( MSG * ) lParam ) - > hwnd ) )
2003-05-08 16:41:07 +00:00
SendMessage ( g_tip . tip , TTM_RELAYEVENT , 0 , lParam ) ;
2002-12-24 20:35:26 +00:00
break ;
default :
break ;
}
return CallNextHookEx ( g_tip . hook , nCode , wParam , lParam ) ;
2002-09-20 14:52:14 +00:00
}
void ShowDocs ( ) {
2010-03-24 17:22:56 +00:00
TCHAR pathf [ MAX_PATH ] , * path ;
2002-12-24 20:35:26 +00:00
GetModuleFileName ( NULL , pathf , sizeof ( pathf ) ) ;
2010-04-12 16:00:17 +00:00
path = _tcsrchr ( pathf , _T ( ' \\ ' ) ) ;
2002-12-24 20:35:26 +00:00
if ( path ! = NULL ) * path = 0 ;
lstrcat ( pathf , LOCALDOCS ) ;
2015-09-17 14:30:07 +00:00
if ( ( int ) ( INT_PTR ) ShellExecute ( g_sdata . hwnd , _T ( " open " ) , pathf , NULL , NULL , SW_SHOWNORMAL ) < = 32 )
ShellExecuteA ( g_sdata . hwnd , " open " , DOCPATH , NULL , NULL , SW_SHOWNORMAL ) ;
2003-05-08 16:41:07 +00:00
}
2010-03-24 17:22:56 +00:00
TCHAR * BuildSymbols ( )
2003-05-08 16:41:07 +00:00
{
2010-03-24 17:22:56 +00:00
TCHAR * buf = NULL ;
2003-05-08 16:41:07 +00:00
2003-12-30 19:43:15 +00:00
if ( g_sdata . symbols ) {
2003-05-08 16:41:07 +00:00
int i = 0 ;
2003-12-30 19:43:15 +00:00
while ( g_sdata . symbols [ i ] ) {
2003-05-08 16:41:07 +00:00
if ( buf ) {
2013-05-26 19:47:22 +00:00
TCHAR * buf3 = ( TCHAR * ) MemAlloc ( ( lstrlen ( buf ) + lstrlen ( g_sdata . symbols [ i ] ) + 6 ) * sizeof ( TCHAR ) ) ;
2010-03-24 17:22:56 +00:00
wsprintf ( buf3 , _T ( " %s \" /D%s \" " ) , buf , g_sdata . symbols [ i ] ) ;
2013-05-26 19:47:22 +00:00
MemFree ( buf ) ;
2003-05-08 16:41:07 +00:00
buf = buf3 ;
}
else {
2013-05-26 19:47:22 +00:00
buf = ( TCHAR * ) MemAlloc ( ( lstrlen ( g_sdata . symbols [ i ] ) + 5 ) * sizeof ( TCHAR ) ) ;
2010-03-24 17:22:56 +00:00
wsprintf ( buf , _T ( " \" /D%s \" " ) , g_sdata . symbols [ i ] ) ;
2003-05-08 16:41:07 +00:00
}
i + + ;
}
}
else {
2013-05-26 19:47:22 +00:00
buf = ( TCHAR * ) MemAlloc ( sizeof ( TCHAR ) ) ;
2010-03-24 17:22:56 +00:00
buf [ 0 ] = _T ( ' \0 ' ) ;
2003-05-08 16:41:07 +00:00
}
return buf ;
2003-08-12 17:57:14 +00:00
}
2012-10-16 08:12:47 +00:00
static inline bool IsValidFile ( const TCHAR * fname )
{
return FileExists ( fname ) ;
}
2010-03-24 17:22:56 +00:00
BOOL PopMRUFile ( TCHAR * fname )
2003-08-12 17:57:14 +00:00
{
int i ;
2003-08-13 16:02:42 +00:00
for ( i = 0 ; i < MRU_LIST_SIZE ; i + + ) {
if ( ! lstrcmpi ( g_mru_list [ i ] , fname ) ) {
2003-08-12 17:57:14 +00:00
break ;
}
}
2003-08-13 16:02:42 +00:00
if ( i < MRU_LIST_SIZE ) {
2003-08-12 17:57:14 +00:00
int j ;
2003-08-13 16:02:42 +00:00
for ( j = i ; j < MRU_LIST_SIZE - 1 ; j + + ) {
lstrcpy ( g_mru_list [ j ] , g_mru_list [ j + 1 ] ) ;
2003-08-12 17:57:14 +00:00
}
2010-03-24 17:22:56 +00:00
g_mru_list [ MRU_LIST_SIZE - 1 ] [ 0 ] = _T ( ' \0 ' ) ;
2003-08-12 17:57:14 +00:00
return TRUE ;
}
else {
return FALSE ;
}
}
2010-03-24 17:22:56 +00:00
void PushMRUFile ( TCHAR * fname )
2003-08-12 17:57:14 +00:00
{
2010-03-24 17:22:56 +00:00
TCHAR full_file_name [ MAX_PATH + 1 ] ;
2003-08-12 17:57:14 +00:00
2010-03-24 17:22:56 +00:00
if ( ! fname | | fname [ 0 ] = = _T ( ' \0 ' ) | | fname [ 0 ] = = _T ( ' / ' ) | | fname [ 0 ] = = _T ( ' - ' ) ) {
2003-08-12 17:57:14 +00:00
return ;
}
2015-10-30 03:55:30 +00:00
DWORD rv = GetFullPathName ( fname , COUNTOF ( full_file_name ) , full_file_name , NULL ) ;
if ( rv = = 0 | | rv > = COUNTOF ( full_file_name ) ) {
2003-08-13 16:02:42 +00:00
return ;
}
2003-11-21 21:57:39 +00:00
if ( IsValidFile ( full_file_name ) ) {
2015-10-30 03:55:30 +00:00
int i ;
2003-11-21 21:57:39 +00:00
PopMRUFile ( full_file_name ) ;
for ( i = MRU_LIST_SIZE - 2 ; i > = 0 ; i - - ) {
lstrcpy ( g_mru_list [ i + 1 ] , g_mru_list [ i ] ) ;
}
lstrcpy ( g_mru_list [ 0 ] , full_file_name ) ;
BuildMRUMenus ( ) ;
2003-08-12 17:57:14 +00:00
}
}
2003-08-23 04:34:31 +00:00
void BuildMRUMenus ( )
2003-08-12 17:57:14 +00:00
{
2003-08-23 04:34:31 +00:00
HMENU hMenu = g_sdata . fileSubmenu ;
2012-10-16 08:12:47 +00:00
int i , n ;
2003-08-12 17:57:14 +00:00
MENUITEMINFO mii ;
2010-03-24 17:22:56 +00:00
TCHAR buf [ MRU_DISPLAY_LENGTH + 5 /*number*/ + 1 /*null*/ ] ;
TCHAR buf2 [ MRU_DISPLAY_LENGTH - 6 ] ;
TCHAR buf3 [ MRU_DISPLAY_LENGTH + 1 ] ;
2012-10-16 08:12:47 +00:00
mii . cbSize = sizeof ( mii ) ;
2003-08-12 17:57:14 +00:00
2003-08-13 16:02:42 +00:00
for ( i = 0 ; i < MRU_LIST_SIZE ; i + + ) {
2003-08-12 17:57:14 +00:00
DeleteMenu ( hMenu , IDM_MRU_FILE + i , MF_BYCOMMAND ) ;
}
2003-08-22 22:01:39 +00:00
n = GetMenuItemCount ( hMenu ) ;
2012-10-16 08:12:47 +00:00
// Remove MRU separator
int seppos = n - 1 ;
2015-10-30 03:55:30 +00:00
mii . fMask = MIIM_TYPE , mii . cch = 0 ;
2012-10-16 08:12:47 +00:00
if ( GetMenuItemInfo ( hMenu , seppos , TRUE , & mii ) ) {
if ( MFT_SEPARATOR & mii . fType ) {
DeleteMenu ( hMenu , seppos , MF_BYPOSITION ) ;
n - - ;
}
}
2003-08-13 16:02:42 +00:00
for ( i = 0 ; i < MRU_LIST_SIZE ; i + + ) {
if ( g_mru_list [ i ] [ 0 ] ) {
2012-10-16 08:12:47 +00:00
if ( seppos ) {
// We have MRU items so add the separator
mii . fMask = MIIM_TYPE ;
mii . fType = MFT_SEPARATOR ;
InsertMenuItem ( hMenu , n + + , TRUE , & mii ) ;
seppos = 0 ;
}
2010-04-12 16:00:17 +00:00
memset ( buf , 0 , sizeof ( buf ) ) ;
2003-08-12 17:57:14 +00:00
mii . fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE ;
mii . wID = IDM_MRU_FILE + i ;
mii . fType = MFT_STRING ;
2010-03-24 17:22:56 +00:00
wsprintf ( buf , _T ( " &%d " ) , i + 1 ) ;
2003-08-13 16:02:42 +00:00
if ( lstrlen ( g_mru_list [ i ] ) > MRU_DISPLAY_LENGTH ) {
2010-04-12 16:00:17 +00:00
TCHAR * p = _tcsrchr ( g_mru_list [ i ] , _T ( ' \\ ' ) ) ;
2003-08-13 16:02:42 +00:00
if ( p ) {
p + + ;
if ( lstrlen ( p ) > MRU_DISPLAY_LENGTH - 7 ) {
2012-10-16 08:12:47 +00:00
* buf2 = 0 ;
2003-08-13 16:02:42 +00:00
lstrcpyn ( buf2 , p , MRU_DISPLAY_LENGTH - 9 ) ;
2010-03-24 17:22:56 +00:00
lstrcat ( buf2 , _T ( " ... " ) ) ;
2003-08-13 16:02:42 +00:00
2007-02-02 16:34:40 +00:00
lstrcpyn ( buf3 , g_mru_list [ i ] , 4 ) ;
lstrcat ( buf , buf3 ) ;
2010-03-24 17:22:56 +00:00
lstrcat ( buf , _T ( " ... \\ " ) ) ;
2003-08-13 16:02:42 +00:00
lstrcat ( buf , buf2 ) ;
}
else {
2007-02-02 16:34:40 +00:00
lstrcpyn ( buf3 , g_mru_list [ i ] , ( MRU_DISPLAY_LENGTH - lstrlen ( p ) - 3 ) ) ;
lstrcat ( buf , buf3 ) ;
2010-03-24 17:22:56 +00:00
lstrcat ( buf , _T ( " ... \\ " ) ) ;
2003-08-13 16:02:42 +00:00
lstrcat ( buf , p ) ;
}
}
else {
2007-02-02 16:34:40 +00:00
lstrcpyn ( buf3 , g_mru_list [ i ] , ( MRU_DISPLAY_LENGTH - 2 ) ) ;
lstrcat ( buf , buf3 ) ;
2010-03-24 17:22:56 +00:00
lstrcat ( buf , _T ( " ... " ) ) ;
2003-08-13 16:02:42 +00:00
}
}
else {
2007-02-02 16:34:40 +00:00
lstrcat ( buf , g_mru_list [ i ] ) ;
2003-08-13 16:02:42 +00:00
}
mii . dwTypeData = buf ;
2003-08-13 16:24:05 +00:00
mii . cch = lstrlen ( buf ) + 1 ;
2003-08-12 17:57:14 +00:00
mii . fState = MFS_ENABLED ;
2003-08-22 22:01:39 +00:00
InsertMenuItem ( hMenu , n + + , TRUE , & mii ) ;
2003-08-12 17:57:14 +00:00
}
else {
break ;
}
}
2003-08-23 04:34:31 +00:00
hMenu = g_sdata . toolsSubmenu ;
mii . fMask = MIIM_STATE ;
2012-10-16 08:12:47 +00:00
mii . fState = g_mru_list [ 0 ] [ 0 ] ? MFS_ENABLED : MFS_GRAYED ;
2003-08-23 04:34:31 +00:00
SetMenuItemInfo ( hMenu , IDM_CLEAR_MRU_LIST , FALSE , & mii ) ;
2003-08-12 17:57:14 +00:00
}
void LoadMRUFile ( int position )
{
2003-08-13 16:02:42 +00:00
if ( ! g_sdata . thread & & position > = 0 & & position < MRU_LIST_SIZE & & g_mru_list [ position ] [ 0 ] ) {
2007-04-10 21:07:21 +00:00
SetScript ( g_mru_list [ position ] ) ;
2003-11-21 21:57:39 +00:00
if ( IsValidFile ( g_mru_list [ position ] ) ) {
2003-08-13 16:02:42 +00:00
PushMRUFile ( g_mru_list [ position ] ) ;
}
else {
PopMRUFile ( g_mru_list [ position ] ) ;
2003-08-23 04:34:31 +00:00
BuildMRUMenus ( ) ;
2003-08-13 16:02:42 +00:00
}
2003-08-12 17:57:14 +00:00
ResetObjects ( ) ;
CompileNSISScript ( ) ;
}
}
void RestoreMRUList ( )
{
2015-09-28 16:08:54 +00:00
HKEY hCfgKey , hMRUKey ;
UINT n = 0 , i ;
if ( OpenRegSettingsKey ( hCfgKey ) ) {
if ( RegOpenKeyForReading ( hCfgKey , REGMRUSUBKEY , & hMRUKey ) = = ERROR_SUCCESS ) {
2003-12-17 16:13:04 +00:00
for ( int i = 0 ; i < MRU_LIST_SIZE ; i + + ) {
2015-09-28 16:08:54 +00:00
TCHAR bufName [ 8 ] ;
wsprintf ( bufName , _T ( " %d " ) , i ) ;
DWORD ec = RegReadString ( hMRUKey , bufName , g_mru_list [ n ] , sizeof ( g_mru_list [ n ] ) ) ;
2012-10-16 08:12:47 +00:00
if ( ! ec & & g_mru_list [ n ] [ 0 ] ! = _T ( ' \0 ' ) ) {
2003-12-17 16:13:04 +00:00
n + + ;
2003-08-12 17:57:14 +00:00
}
2003-12-17 16:13:04 +00:00
}
2015-09-28 16:08:54 +00:00
RegCloseKey ( hMRUKey ) ;
2003-08-12 17:57:14 +00:00
}
2015-09-28 16:08:54 +00:00
RegCloseKey ( hCfgKey ) ;
2003-12-17 16:13:04 +00:00
}
for ( i = n ; i < MRU_LIST_SIZE ; i + + ) {
2010-03-24 17:22:56 +00:00
g_mru_list [ i ] [ 0 ] = _T ( ' \0 ' ) ;
2003-12-17 16:13:04 +00:00
}
2003-08-23 04:34:31 +00:00
2003-12-17 16:13:04 +00:00
BuildMRUMenus ( ) ;
2003-08-12 17:57:14 +00:00
}
void SaveMRUList ( )
{
2015-09-28 16:08:54 +00:00
UINT c = 0 , i ;
for ( i = 0 ; i < MRU_LIST_SIZE ; + + i )
if ( * g_mru_list [ i ] )
+ + c ;
HKEY hCfgKey , hMRUKey ;
if ( CreateRegSettingsKey ( hCfgKey ) ) {
if ( ( c ? RegCreateKey : RegOpenKey ) ( hCfgKey , REGMRUSUBKEY , & hMRUKey ) = = ERROR_SUCCESS ) {
for ( i = 0 ; i < MRU_LIST_SIZE ; + + i ) {
TCHAR bufName [ 8 ] ;
wsprintf ( bufName , _T ( " %d " ) , i ) ;
if ( * g_mru_list [ i ] )
RegWriteString ( hMRUKey , bufName , g_mru_list [ i ] ) ;
else
RegDeleteValue ( hMRUKey , bufName ) ;
2003-12-17 16:13:04 +00:00
}
2015-09-28 16:08:54 +00:00
RegCloseKey ( hMRUKey ) ;
2003-08-12 17:57:14 +00:00
}
2015-09-28 16:08:54 +00:00
RegCloseKey ( hCfgKey ) ;
2003-12-17 16:13:04 +00:00
}
2003-08-12 17:57:14 +00:00
}
2003-08-13 16:02:42 +00:00
void ClearMRUList ( )
{
2015-09-28 16:08:54 +00:00
for ( UINT i = 0 ; i < MRU_LIST_SIZE ; + + i ) {
2010-03-24 17:22:56 +00:00
g_mru_list [ i ] [ 0 ] = _T ( ' \0 ' ) ;
2003-08-13 16:02:42 +00:00
}
2003-08-23 04:34:31 +00:00
BuildMRUMenus ( ) ;
}
2003-11-19 04:38:14 +00:00
void RestoreCompressor ( )
{
HKEY hKey ;
2003-11-25 21:06:37 +00:00
NCOMPRESSOR v = COMPRESSOR_SCRIPT ;
2007-01-24 12:51:26 +00:00
if ( OpenRegSettingsKey ( hKey ) ) {
2010-03-24 17:22:56 +00:00
TCHAR compressor_name [ 32 ] ;
2015-09-28 16:08:54 +00:00
if ( RegReadString ( hKey , REGCOMPRESSOR , compressor_name , sizeof ( compressor_name ) ) = = ERROR_SUCCESS ) {
for ( UINT i = ( UINT ) COMPRESSOR_SCRIPT ; i < = ( UINT ) COMPRESSOR_BEST ; i + + ) {
if ( ! lstrcmpi ( compressor_names [ i ] , compressor_name ) ) {
2003-11-25 21:06:37 +00:00
v = ( NCOMPRESSOR ) i ;
break ;
}
}
2003-11-19 04:38:14 +00:00
}
RegCloseKey ( hKey ) ;
}
2015-09-28 16:08:54 +00:00
g_sdata . default_compressor = v ;
2003-11-19 04:38:14 +00:00
}
void SaveCompressor ( )
{
2003-11-25 21:06:37 +00:00
HKEY hKey ;
int n = ( int ) COMPRESSOR_SCRIPT ;
NCOMPRESSOR v = g_sdata . default_compressor ;
if ( v > = COMPRESSOR_SCRIPT & & v < = COMPRESSOR_BEST ) {
n = ( int ) v ;
}
2015-09-28 16:08:54 +00:00
if ( CreateRegSettingsKey ( hKey ) ) {
if ( compressor_names [ n ] [ 0 ] )
RegWriteString ( hKey , REGCOMPRESSOR , compressor_names [ n ] ) ;
else
RegDeleteValue ( hKey , REGCOMPRESSOR ) ;
2003-11-25 21:06:37 +00:00
RegCloseKey ( hKey ) ;
2003-11-19 04:38:14 +00:00
}
}
2012-10-16 08:12:47 +00:00
bool FileExists ( const TCHAR * fname )
2003-11-19 04:38:14 +00:00
{
WIN32_FIND_DATA wfd ;
2013-05-26 19:47:22 +00:00
HANDLE h = FindFirstFile ( fname , & wfd ) ;
2012-10-16 08:12:47 +00:00
if ( INVALID_HANDLE_VALUE ! = h ) {
2003-11-19 04:38:14 +00:00
FindClose ( h ) ;
return true ;
}
2012-10-16 08:12:47 +00:00
return false ;
2003-11-19 04:38:14 +00:00
}
2006-04-07 18:49:03 +00:00
2015-09-07 21:31:50 +00:00
bool OpenUrlInDefaultBrowser ( HWND hwnd , LPCSTR Url )
{
2018-10-16 16:55:37 +00:00
return ( int ) ( INT_PTR ) ShellExecuteA ( hwnd , NULL , Url , NULL , NULL , SW_SHOWNORMAL ) > 32 ;
2015-09-07 21:31:50 +00:00
}
2006-04-07 18:49:03 +00:00
HMENU FindSubMenu ( HMENU hMenu , UINT uId )
{
2013-05-26 19:47:22 +00:00
MENUITEMINFO mii ;
mii . cbSize = sizeof ( MENUITEMINFO ) ;
mii . fMask = MIIM_SUBMENU ;
return GetMenuItemInfo ( hMenu , uId , FALSE , & mii ) ? mii . hSubMenu : 0 ;
}
2006-04-07 18:49:03 +00:00
2018-11-04 21:25:52 +00:00
static UINT DpiGetClassicSystemDpiY ( ) { HDC hDC = GetDC ( NULL ) ; UINT dpi = GetDeviceCaps ( hDC , LOGPIXELSY ) ; ReleaseDC ( NULL , hDC ) ; return dpi ; }
static HRESULT WINAPI DpiFallbackGetDpiForMonitor ( HMONITOR hMon , int MDT , UINT * pX , UINT * pY ) { return ( * pX = * pY = DpiGetClassicSystemDpiY ( ) , S_OK ) ; }
static UINT WINAPI DpiFallbackGetDpiForWindow ( HWND hWnd ) { return 0 ; }
2019-10-16 19:55:33 +00:00
static HMONITOR WINAPI DpiFallbackMonitorFromWindow ( HWND hWnd , DWORD Flags ) { return NULL ; }
2018-11-04 21:25:52 +00:00
static UINT DpiNativeGetForMonitor ( HMONITOR hMon )
{
static HRESULT ( WINAPI * f ) ( HMONITOR , int , UINT * , UINT * ) ;
2018-11-11 22:05:32 +00:00
if ( ! f & & ! ( ( FARPROC & ) f = GetSysProcAddr ( " SHCORE " , " GetDpiForMonitor " ) ) ) f = DpiFallbackGetDpiForMonitor ;
2018-11-04 21:25:52 +00:00
UINT x , y , mdt_effective_dpi = 0 ;
return SUCCEEDED ( f ( hMon , mdt_effective_dpi , & x , & y ) ) ? y : 0 ;
}
2019-10-16 19:55:33 +00:00
UINT DpiGetForMonitor ( HWND hWnd )
2018-11-04 21:25:52 +00:00
{
2019-10-16 19:55:33 +00:00
HMONITOR ( WINAPI * monitorfromwindow ) ( HWND , DWORD ) ;
if ( SupportsWNT4 ( ) | | SupportsW95 ( ) )
{
static HMONITOR ( WINAPI * g ) ( HWND , DWORD ) ;
if ( ! g & & ! ( ( FARPROC & ) g = GetSysProcAddr ( " USER32 " , " MonitorFromWindow " ) ) ) g = DpiFallbackMonitorFromWindow ;
monitorfromwindow = g ;
}
else
{
monitorfromwindow = MonitorFromWindow ;
}
HMONITOR hMon = monitorfromwindow ( hWnd , MONITOR_DEFAULTTONEAREST ) ;
2018-11-04 21:25:52 +00:00
return hMon ? DpiNativeGetForMonitor ( hMon ) : ( UINT ) ( UINT_PTR ) hMon ;
}
UINT DpiGetForWindow ( HWND hWnd )
{
UINT dpi ;
if ( DpiAwarePerMonitor ( ) | | DpiAwarePerMonitor2 ( ) )
{
static UINT ( WINAPI * f ) ( HWND ) ;
2018-11-11 22:05:32 +00:00
if ( ! f & & ! ( ( FARPROC & ) f = GetSysProcAddr ( " USER32 " , " GetDpiForWindow " ) ) ) f = DpiFallbackGetDpiForWindow ;
2018-11-04 21:25:52 +00:00
if ( ( dpi = f ( hWnd ) ) ) return dpi ;
}
if ( DpiAwarePerMonitor ( ) & & ( dpi = DpiGetForMonitor ( hWnd ) ) ) return dpi ;
return DpiGetClassicSystemDpiY ( ) ;
}
int DpiScaleY ( HWND hWnd , int Val )
2013-05-26 19:47:22 +00:00
{
2018-11-04 21:25:52 +00:00
return MulDiv ( Val , DpiGetForWindow ( hWnd ) , 96 ) ;
2006-04-07 18:49:03 +00:00
}
2018-10-18 17:45:47 +00:00
2018-11-04 21:25:52 +00:00
HFONT CreateFontHelper ( INT_PTR Data , int Height , DWORD p1 , LPCTSTR Face )
{
2018-11-06 21:04:37 +00:00
WORD w = LOBYTE ( p1 ) < < 2 , flags = HIBYTE ( p1 ) , cs = HIWORD ( LOBYTE ( p1 ) ) , paf = HIWORD ( HIBYTE ( p1 ) ) ;
2018-11-04 21:25:52 +00:00
if ( flags & CFF_DPIPT )
{
UINT dpi = ( flags & CFF_DPIFROMHWND ) ? DpiGetForWindow ( ( HWND ) Data ) : ( UINT ) Data ;
Height = - MulDiv ( Height , dpi , 72 ) ;
}
return CreateFont ( Height , 0 , 0 , 0 , w , FALSE , FALSE , FALSE , cs , OUT_DEFAULT_PRECIS , CLIP_DEFAULT_PRECIS , DEFAULT_QUALITY , paf , Face ) ;
}
2021-01-01 20:10:26 +00:00
BOOL CALLBACK FontExistsCallback ( const LOGFONT * pLF , const TEXTMETRIC * pTM , DWORD Type , LPARAM Cookie )
{
* ( ( BOOL * ) Cookie ) = TRUE ;
return FALSE ;
}
BOOL FontExists ( LPCTSTR Face )
{
BOOL ret = FALSE ;
HDC hDC = GetDC ( 0 ) ;
EnumFonts ( hDC , Face , FontExistsCallback , ( LPARAM ) & ret ) ;
ReleaseDC ( 0 , hDC ) ;
return ret ;
}
2019-10-16 19:55:33 +00:00
BOOL FillRectColor ( HDC hDC , const RECT & Rect , COLORREF Color )
{
COLORREF orgclr = SetBkColor ( hDC , Color ) ;
ExtTextOut ( hDC , 0 , 0 , ETO_OPAQUE , & Rect , _T ( " " ) , 0 , NULL ) ;
return TRUE | SetBkColor ( hDC , orgclr ) ;
}
2018-11-04 21:25:52 +00:00
static BOOL DrawHorzGradient ( HDC hDC , const RECT & rect , COLOR16 r1 , COLOR16 g1 , COLOR16 b1 , COLOR16 r2 , COLOR16 g2 , COLOR16 b2 )
{
TRIVERTEX v [ 2 ] = { { rect . left , rect . top , r1 , g1 , b1 , 0xffff } , { rect . right , rect . bottom , r2 , g2 , b2 , 0xffff } } ;
GRADIENT_RECT r = { 0 , 1 } ;
BOOL ( WINAPI * gf ) ( HDC , TRIVERTEX * , ULONG , VOID * , ULONG , ULONG ) ;
if ( SupportsWNT4 ( ) | | SupportsW95 ( ) )
{
2018-11-11 22:05:32 +00:00
if ( ! ( ( FARPROC & ) gf = GetSysProcAddr ( " MSIMG32 " , " GradientFill " ) ) )
2018-11-04 21:25:52 +00:00
{
2019-10-16 19:55:33 +00:00
return FillRectColor ( hDC , rect , RGB ( ( ( ( UINT ) r1 + r2 ) / 2 ) > > 8 , ( ( ( UINT ) g1 + g2 ) / 2 ) > > 8 , ( ( ( UINT ) b1 + b2 ) / 2 ) > > 8 ) ) ; // TODO: Actually try to draw a gradient
2018-11-04 21:25:52 +00:00
}
}
else
gf = GradientFill ;
return gf ( hDC , v , 2 , & r , 1 , GRADIENT_FILL_RECT_H ) ;
}
BOOL DrawHorzGradient ( HDC hDC , LONG l , LONG t , LONG r , LONG b , COLORREF c1 , COLORREF c2 )
{
RECT rect = { l , t , r , b } ;
2018-11-06 21:04:37 +00:00
return DrawHorzGradient ( hDC , rect , ( WORD ) GetRValue ( c1 ) < < 8 , ( WORD ) GetGValue ( c1 ) < < 8 , ( WORD ) GetBValue ( c1 ) < < 8 , ( WORD ) GetRValue ( c2 ) < < 8 , ( WORD ) GetGValue ( c2 ) < < 8 , ( WORD ) GetBValue ( c2 ) < < 8 ) ;
2018-11-04 21:25:52 +00:00
}
long DlgUnitToPixelX ( HWND hDlg , long x ) { RECT r = { x , 0 , 0 , 0 } ; MapDialogRect ( hDlg , & r ) ; return r . left ; }
2018-11-06 21:04:37 +00:00
long DlgUnitToPixelY ( HWND hDlg , long y ) { RECT r = { 0 , y , 0 , 0 } ; MapDialogRect ( hDlg , & r ) ; return r . top ; }
2018-11-04 21:25:52 +00:00
2018-10-18 17:45:47 +00:00
# ifndef SP_GRIPPER
# ifndef HTHEME
# define HTHEME HTHEME_OLDSDK
struct OLDSDK_TYPE_HTHEME { int unused ; } ; typedef struct OLDSDK_TYPE_HTHEME * HTHEME ;
# endif
# define SP_GRIPPER 3
# endif
struct VisualStyles {
VisualStyles ( ) : m_OpenThemeData ( NULL ) { }
static HTHEME WINAPI Compat_OpenThemeData ( HWND hWnd , LPCWSTR Class ) { return NULL ; }
HTHEME OpenThemeData ( HWND hWnd , LPCWSTR Class ) { return ( InitUXTheme ( ) , m_OpenThemeData ( hWnd , Class ) ) ; }
void InitUXTheme ( )
{
if ( m_OpenThemeData ) return ;
2018-11-11 22:05:32 +00:00
HMODULE hUXT = LoadSysLibrary ( " UXTHEME " ) ;
2018-10-18 17:45:47 +00:00
if ( ! ( ( FARPROC & ) m_OpenThemeData = GetProcAddress ( hUXT , " OpenThemeData " ) ) ) m_OpenThemeData = Compat_OpenThemeData ;
( FARPROC & ) CloseThemeData = GetProcAddress ( hUXT , " CloseThemeData " ) ;
( FARPROC & ) DrawThemeBackground = GetProcAddress ( hUXT , " DrawThemeBackground " ) ;
}
HTHEME ( WINAPI * m_OpenThemeData ) ( HWND , LPCWSTR ) ;
HRESULT ( WINAPI * CloseThemeData ) ( HTHEME ) ;
HRESULT ( WINAPI * DrawThemeBackground ) ( HTHEME , HDC , int , int , LPCRECT , LPCRECT ) ;
} VS ;
void DrawGripper ( HWND hWnd , HDC hDC , const RECT & r )
{
HTHEME hTheme = VS . OpenThemeData ( hWnd , L " STATUS " ) ;
if ( hTheme )
{
VS . DrawThemeBackground ( hTheme , hDC , SP_GRIPPER , 0 , & r , NULL ) ;
VS . CloseThemeData ( hTheme ) ;
}
else
{
DrawFrameControl ( hDC , const_cast < LPRECT > ( & r ) , DFC_SCROLL , DFCS_SCROLLSIZEGRIP ) ;
}
}
2018-11-07 01:28:41 +00:00
bool RicheditHasSelection ( HWND hRE )
{
CHARRANGE tr ;
SendMessage ( hRE , EM_EXGETSEL , 0 , ( LPARAM ) & tr ) ;
return tr . cpMax - tr . cpMin < = 0 ? FALSE : TRUE ;
}
2018-11-07 02:36:21 +00:00
void EnableUICommand ( UINT Id , INT_PTR Enabled )
{
EnableToolBarButton ( Id , ! ! Enabled ) ;
EnableMenuItem ( g_sdata . menu , Id , Enabled ? MF_ENABLED : MF_GRAYED ) ;
2018-11-07 16:58:43 +00:00
}