2013-11-30 22:15:42 +08:00
# include <windows.h>
# include <tchar.h>
# include <Shlwapi.h>
# include "resource.h"
2013-12-07 22:17:35 +08:00
# include <vector>
2018-03-13 23:38:27 +08:00
# include <shlobj.h>
2018-03-14 06:40:07 +08:00
# include <regex>
# include <iostream>
2016-02-01 05:35:57 +08:00
2013-11-30 22:15:42 +08:00
# pragma comment(lib, "Shlwapi.lib")
2018-09-05 07:52:42 +08:00
# pragma comment(lib, "comctl32.lib")
2018-09-01 06:02:56 +08:00
# pragma warning( disable : 4091 )
2013-11-30 22:15:42 +08:00
2013-12-07 22:17:35 +08:00
# ifndef UNICODE
# error "Must be compiled with unicode support."
# endif
2013-11-30 22:15:42 +08:00
2013-12-07 22:17:35 +08:00
# define USE_TASKBAR_API (_WIN32_WINNT >= _WIN32_WINNT_WIN7)
# define MB_TITLE L"Cmder Launcher"
2014-02-28 07:34:37 +08:00
# define SHELL_MENU_REGISTRY_PATH_BACKGROUND L"Directory\\Background\\shell\\Cmder"
# define SHELL_MENU_REGISTRY_PATH_LISTITEM L"Directory\\shell\\Cmder"
2019-03-17 07:15:36 +08:00
# define SHELL_MENU_REGISTRY_DRIVE_PATH_BACKGROUND L"Drive\\Background\\shell\\Cmder"
# define SHELL_MENU_REGISTRY_DRIVE_PATH_LISTITEM L"Drive\\shell\\Cmder"
2013-12-07 22:17:35 +08:00
2015-09-05 04:16:30 +08:00
# define streqi(a, b) (_wcsicmp((a), (b)) == 0)
2013-12-07 22:17:35 +08:00
# define WIDEN2(x) L ## x
# define WIDEN(x) WIDEN2(x)
# define __WFUNCTION__ WIDEN(__FUNCTION__)
# define FAIL_ON_ERROR(x) { DWORD ec; if ((ec = (x)) != ERROR_SUCCESS) { ShowErrorAndExit(ec, __WFUNCTION__, __LINE__); } }
2018-09-05 07:52:42 +08:00
void TaskDialogOpen ( PCWSTR mainStr , PCWSTR contentStr )
{
HRESULT hr = NULL ;
TASKDIALOGCONFIG tsk = { sizeof ( tsk ) } ;
HWND hOwner = NULL ;
HINSTANCE hInstance = GetModuleHandle ( NULL ) ;
PCWSTR tskTitle = MAKEINTRESOURCE ( IDS_TITLE ) ;
tsk . hInstance = hInstance ;
tsk . pszMainIcon = MAKEINTRESOURCE ( IDI_CMDER ) ;
tsk . pszWindowTitle = tskTitle ;
2022-09-10 01:01:25 +08:00
tsk . pszMainInstruction = mainStr ;
2018-09-05 07:52:42 +08:00
tsk . pszContent = contentStr ;
TASKDIALOG_BUTTON btns [ 1 ] = {
{ IDOK , L " OK " }
} ;
tsk . dwFlags = TDF_ALLOW_DIALOG_CANCELLATION | TDF_ENABLE_HYPERLINKS ;
tsk . pButtons = btns ;
tsk . cButtons = _countof ( btns ) ;
tsk . hwndParent = hOwner ;
int selectedButtonId = IDOK ;
hr = TaskDialogIndirect ( & tsk , & selectedButtonId , NULL , NULL ) ;
}
2013-12-07 22:17:35 +08:00
void ShowErrorAndExit ( DWORD ec , const wchar_t * func , int line )
2013-11-30 22:15:42 +08:00
{
2013-12-07 22:17:35 +08:00
wchar_t * buffer ;
2015-09-05 04:16:30 +08:00
if ( FormatMessage ( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS ,
2016-04-14 02:16:58 +08:00
NULL , ec , 0 , ( LPWSTR ) & buffer , 0 , NULL ) = = 0 )
2013-12-07 22:17:35 +08:00
{
buffer = L " Unknown error. FormatMessage failed. " ;
}
wchar_t message [ 1024 ] ;
swprintf_s ( message , L " %s \n Function: %s \n Line: %d " , buffer , func , line ) ;
LocalFree ( buffer ) ;
2013-11-30 22:15:42 +08:00
2013-12-07 22:17:35 +08:00
MessageBox ( NULL , message , MB_TITLE , MB_OK | MB_ICONERROR ) ;
exit ( 1 ) ;
}
typedef struct _option
{
std : : wstring name ;
bool hasVal ;
std : : wstring value ;
bool set ;
} option ;
typedef std : : pair < std : : wstring , std : : wstring > optpair ;
2015-08-19 07:13:22 +08:00
bool FileExists ( const wchar_t * filePath )
{
HANDLE hFile = CreateFile ( filePath , GENERIC_READ , FILE_SHARE_READ , NULL , OPEN_EXISTING , 0 , NULL ) ;
if ( hFile ! = INVALID_HANDLE_VALUE )
{
CloseHandle ( hFile ) ;
return true ;
}
return false ;
}
2020-06-24 13:23:28 +08:00
void StartCmder ( std : : wstring path = L " " , bool is_single_mode = false , std : : wstring taskName = L " " , std : : wstring title = L " " , std : : wstring iconPath = L " " , std : : wstring cfgRoot = L " " , bool use_user_cfg = true , std : : wstring conemu_args = L " " )
2013-12-07 22:17:35 +08:00
{
2013-11-30 22:15:42 +08:00
# if USE_TASKBAR_API
2013-12-07 22:17:35 +08:00
wchar_t appId [ MAX_PATH ] = { 0 } ;
2013-11-30 22:15:42 +08:00
# endif
2013-12-07 22:17:35 +08:00
wchar_t exeDir [ MAX_PATH ] = { 0 } ;
wchar_t icoPath [ MAX_PATH ] = { 0 } ;
wchar_t cfgPath [ MAX_PATH ] = { 0 } ;
2016-10-03 11:23:12 +08:00
wchar_t backupCfgPath [ MAX_PATH ] = { 0 } ;
2016-10-03 10:50:56 +08:00
wchar_t cpuCfgPath [ MAX_PATH ] = { 0 } ;
wchar_t userCfgPath [ MAX_PATH ] = { 0 } ;
2018-03-13 23:38:27 +08:00
wchar_t defaultCfgPath [ MAX_PATH ] = { 0 } ;
2013-12-07 22:17:35 +08:00
wchar_t conEmuPath [ MAX_PATH ] = { 0 } ;
2018-03-13 23:38:27 +08:00
wchar_t configDirPath [ MAX_PATH ] = { 0 } ;
wchar_t userConfigDirPath [ MAX_PATH ] = { 0 } ;
wchar_t userBinDirPath [ MAX_PATH ] = { 0 } ;
wchar_t userProfiledDirPath [ MAX_PATH ] = { 0 } ;
2018-09-01 06:02:56 +08:00
wchar_t userProfilePath [ MAX_PATH ] = { 0 } ;
wchar_t legacyUserProfilePath [ MAX_PATH ] = { 0 } ;
2018-09-02 06:17:09 +08:00
wchar_t userAliasesPath [ MAX_PATH ] = { 0 } ;
wchar_t legacyUserAliasesPath [ MAX_PATH ] = { 0 } ;
2013-12-07 22:17:35 +08:00
wchar_t args [ MAX_PATH * 2 + 256 ] = { 0 } ;
2018-11-11 06:25:17 +08:00
wchar_t userConEmuCfgPath [ MAX_PATH ] = { 0 } ;
2013-11-30 22:15:42 +08:00
2018-03-13 23:38:27 +08:00
std : : wstring cmderStart = path ;
std : : wstring cmderTask = taskName ;
2020-06-24 13:17:48 +08:00
std : : wstring cmderTitle = title ;
2019-05-20 04:54:47 +08:00
std : : wstring cmderConEmuArgs = conemu_args ;
2018-03-13 23:38:27 +08:00
std : : copy ( cfgRoot . begin ( ) , cfgRoot . end ( ) , userConfigDirPath ) ;
userConfigDirPath [ cfgRoot . length ( ) ] = 0 ;
2013-11-30 22:15:42 +08:00
GetModuleFileName ( NULL , exeDir , sizeof ( exeDir ) ) ;
# if USE_TASKBAR_API
2013-12-07 22:17:35 +08:00
wcscpy_s ( appId , exeDir ) ;
2013-11-30 22:15:42 +08:00
# endif
PathRemoveFileSpec ( exeDir ) ;
2020-06-24 08:50:15 +08:00
if ( PathFileExists ( iconPath . c_str ( ) ) )
{
std : : copy ( iconPath . begin ( ) , iconPath . end ( ) , icoPath ) ;
icoPath [ iconPath . length ( ) ] = 0 ;
}
else
{
PathCombine ( icoPath , exeDir , L " icons \\ cmder.ico " ) ;
}
2015-11-01 06:29:10 +08:00
2018-03-13 23:38:27 +08:00
PathCombine ( configDirPath , exeDir , L " config " ) ;
2018-09-01 06:02:56 +08:00
2018-11-09 10:25:42 +08:00
/*
Convert legacy user - profile . cmd to new name user_profile . cmd
*/
2018-09-01 06:02:56 +08:00
PathCombine ( legacyUserProfilePath , configDirPath , L " user-profile.cmd " ) ;
2018-11-09 10:25:42 +08:00
if ( PathFileExists ( legacyUserProfilePath ) )
{
2018-09-01 06:02:56 +08:00
PathCombine ( userProfilePath , configDirPath , L " user_profile.cmd " ) ;
char * lPr = ( char * ) malloc ( MAX_PATH ) ;
char * pR = ( char * ) malloc ( MAX_PATH ) ;
size_t i ;
wcstombs_s ( & i , lPr , ( size_t ) MAX_PATH ,
legacyUserProfilePath , ( size_t ) MAX_PATH ) ;
wcstombs_s ( & i , pR , ( size_t ) MAX_PATH ,
userProfilePath , ( size_t ) MAX_PATH ) ;
rename ( lPr , pR ) ;
}
2018-11-09 10:25:42 +08:00
/*
Convert legacy user - aliases . cmd to new name user_aliases . cmd
*/
2018-09-02 06:17:09 +08:00
PathCombine ( legacyUserAliasesPath , configDirPath , L " user-aliases.cmd " ) ;
2018-11-09 10:25:42 +08:00
if ( PathFileExists ( legacyUserAliasesPath ) )
{
2018-09-02 06:17:09 +08:00
PathCombine ( userAliasesPath , configDirPath , L " user_aliases.cmd " ) ;
char * lPr = ( char * ) malloc ( MAX_PATH ) ;
char * pR = ( char * ) malloc ( MAX_PATH ) ;
size_t i ;
wcstombs_s ( & i , lPr , ( size_t ) MAX_PATH ,
legacyUserAliasesPath , ( size_t ) MAX_PATH ) ;
wcstombs_s ( & i , pR , ( size_t ) MAX_PATH ,
userAliasesPath , ( size_t ) MAX_PATH ) ;
rename ( lPr , pR ) ;
}
2022-10-15 17:16:13 +08:00
2018-11-09 10:25:42 +08:00
/*
2018-11-11 21:04:35 +08:00
Was / c [ path ] specified ?
2018-11-09 10:25:42 +08:00
*/
2018-03-13 23:38:27 +08:00
if ( wcscmp ( userConfigDirPath , L " " ) = = 0 )
{
2022-09-10 01:01:25 +08:00
// No - It wasn't.
2018-03-13 23:38:27 +08:00
PathCombine ( userConfigDirPath , exeDir , L " config " ) ;
}
else
{
2018-11-09 10:25:42 +08:00
// Yes - It was.
2018-03-13 23:38:27 +08:00
PathCombine ( userBinDirPath , userConfigDirPath , L " bin " ) ;
SHCreateDirectoryEx ( 0 , userBinDirPath , 0 ) ;
PathCombine ( userConfigDirPath , userConfigDirPath , L " config " ) ;
SHCreateDirectoryEx ( 0 , userConfigDirPath , 0 ) ;
PathCombine ( userProfiledDirPath , userConfigDirPath , L " profile.d " ) ;
SHCreateDirectoryEx ( 0 , userProfiledDirPath , 0 ) ;
2018-11-09 10:25:42 +08:00
/*
Convert legacy user - profile . cmd to new name user_profile . cmd
*/
2018-09-01 06:02:56 +08:00
PathCombine ( legacyUserProfilePath , userConfigDirPath , L " user-profile.cmd " ) ;
2018-11-09 10:25:42 +08:00
if ( PathFileExists ( legacyUserProfilePath ) )
{
2018-09-01 06:02:56 +08:00
PathCombine ( userProfilePath , userConfigDirPath , L " user_profile.cmd " ) ;
char * lPr = ( char * ) malloc ( MAX_PATH ) ;
char * pR = ( char * ) malloc ( MAX_PATH ) ;
size_t i ;
wcstombs_s ( & i , lPr , ( size_t ) MAX_PATH ,
legacyUserProfilePath , ( size_t ) MAX_PATH ) ;
wcstombs_s ( & i , pR , ( size_t ) MAX_PATH ,
userProfilePath , ( size_t ) MAX_PATH ) ;
rename ( lPr , pR ) ;
}
2018-09-02 06:17:09 +08:00
2018-11-09 10:25:42 +08:00
/*
Convert legacy user - aliases . cmd to new name user_aliases . cmd
*/
2018-09-02 06:17:09 +08:00
PathCombine ( legacyUserAliasesPath , userConfigDirPath , L " user-aliases.cmd " ) ;
2018-11-09 10:25:42 +08:00
if ( PathFileExists ( legacyUserAliasesPath ) )
{
2018-09-02 06:17:09 +08:00
PathCombine ( userAliasesPath , userConfigDirPath , L " user_aliases.cmd " ) ;
char * lPr = ( char * ) malloc ( MAX_PATH ) ;
char * pR = ( char * ) malloc ( MAX_PATH ) ;
size_t i ;
wcstombs_s ( & i , lPr , ( size_t ) MAX_PATH ,
legacyUserAliasesPath , ( size_t ) MAX_PATH ) ;
wcstombs_s ( & i , pR , ( size_t ) MAX_PATH ,
userAliasesPath , ( size_t ) MAX_PATH ) ;
rename ( lPr , pR ) ;
}
2018-03-13 23:38:27 +08:00
}
// Set path to vendored ConEmu config file
PathCombine ( cfgPath , exeDir , L " vendor \\ conemu-maximus5 \\ ConEmu.xml " ) ;
// Set path to Cmder default ConEmu config file
2018-11-10 22:32:44 +08:00
PathCombine ( defaultCfgPath , exeDir , L " vendor \\ ConEmu.xml.default " ) ;
2018-03-13 23:38:27 +08:00
2016-10-03 10:50:56 +08:00
// Check for machine-specific then user config source file.
2018-03-13 23:38:27 +08:00
PathCombine ( cpuCfgPath , userConfigDirPath , L " ConEmu-%COMPUTERNAME%.xml " ) ;
2016-10-03 07:34:40 +08:00
ExpandEnvironmentStrings ( cpuCfgPath , cpuCfgPath , sizeof ( cpuCfgPath ) / sizeof ( cpuCfgPath [ 0 ] ) ) ;
2018-11-09 10:25:42 +08:00
// Set path to Cmder user ConEmu config file
2018-03-13 23:38:27 +08:00
PathCombine ( userCfgPath , userConfigDirPath , L " user-ConEmu.xml " ) ;
2018-11-09 10:25:42 +08:00
2018-11-12 20:56:55 +08:00
if ( PathFileExists ( cpuCfgPath ) | | use_user_cfg = = false ) // config/ConEmu-%COMPUTERNAME%.xml file exists or /m was specified on command line, use machine specific config.
2018-11-09 10:25:42 +08:00
{
2018-11-11 21:04:35 +08:00
if ( cfgRoot . length ( ) = = 0 ) // '/c [path]' was NOT specified
2018-11-09 10:25:42 +08:00
{
2018-11-11 06:25:17 +08:00
if ( PathFileExists ( cfgPath ) ) // vendor/conemu-maximus5/ConEmu.xml file exists, copy vendor/conemu-maximus5/ConEmu.xml to config/ConEmu-%COMPUTERNAME%.xml.
2018-03-13 23:38:27 +08:00
{
2018-11-11 06:25:17 +08:00
if ( ! CopyFile ( cfgPath , cpuCfgPath , FALSE ) )
{
MessageBox ( NULL ,
( GetLastError ( ) = = ERROR_ACCESS_DENIED )
? L " Failed to copy vendor/conemu-maximus5/ConEmu.xml file to config/ConEmu-%COMPUTERNAME%.xml! Access Denied. "
: L " Failed to copy vendor/conemu-maximus5/ConEmu.xml file to config/ConEmu-%COMPUTERNAME%.xml! " , MB_TITLE , MB_ICONSTOP ) ;
exit ( 1 ) ;
}
}
else // vendor/conemu-maximus5/ConEmu.xml config file does not exist, copy config/ConEmu-%COMPUTERNAME%.xml to vendor/conemu-maximus5/ConEmu.xml file
{
if ( ! CopyFile ( cpuCfgPath , cfgPath , FALSE ) )
{
MessageBox ( NULL ,
( GetLastError ( ) = = ERROR_ACCESS_DENIED )
2022-01-16 00:00:58 +08:00
? L " Failed to copy config/ConEmu-%COMPUTERNAME%.xml file to vendor/conemu-maximus5/ConEmu.xml! Access Denied. "
2018-11-11 06:25:17 +08:00
: L " Failed to copy config/ConEmu-%COMPUTERNAME%.xml file to vendor/conemu-maximus5/ConEmu.xml! " , MB_TITLE , MB_ICONSTOP ) ;
exit ( 1 ) ;
}
2018-03-13 23:38:27 +08:00
}
}
2018-11-11 21:04:35 +08:00
else // '/c [path]' was specified, don't copy anything and use existing conemu-%COMPUTERNAME%.xml to start comemu.
2018-03-13 23:38:27 +08:00
{
2018-11-12 21:30:44 +08:00
if ( use_user_cfg = = false & & PathFileExists ( cfgPath ) & & ! PathFileExists ( cpuCfgPath ) ) // vendor/conemu-maximus5/ConEmu.xml file exists, copy vendor/conemu-maximus5/ConEmu.xml to config/ConEmu-%COMPUTERNAME%.xml.
2018-03-13 23:38:27 +08:00
{
2018-11-12 21:30:44 +08:00
if ( ! CopyFile ( cfgPath , cpuCfgPath , FALSE ) )
{
MessageBox ( NULL ,
( GetLastError ( ) = = ERROR_ACCESS_DENIED )
? L " Failed to copy vendor/conemu-maximus5/ConEmu.xml file to config/ConEmu-%COMPUTERNAME%.xml! Access Denied. "
: L " Failed to copy vendor/conemu-maximus5/ConEmu.xml file to config/ConEmu-%COMPUTERNAME%.xml! " , MB_TITLE , MB_ICONSTOP ) ;
exit ( 1 ) ;
}
2018-03-13 23:38:27 +08:00
}
2018-11-12 21:30:44 +08:00
2018-11-11 06:25:17 +08:00
PathCombine ( userConEmuCfgPath , userConfigDirPath , L " ConEmu-%COMPUTERNAME%.xml " ) ;
ExpandEnvironmentStrings ( userConEmuCfgPath , userConEmuCfgPath , sizeof ( userConEmuCfgPath ) / sizeof ( userConEmuCfgPath [ 0 ] ) ) ;
2018-03-13 23:38:27 +08:00
}
2016-10-03 10:50:56 +08:00
}
2022-10-15 17:16:13 +08:00
else if ( PathFileExists ( userCfgPath ) ) // config/user_conemu.xml exists, use it.
2018-11-11 06:25:17 +08:00
{
2018-11-11 21:04:35 +08:00
if ( cfgRoot . length ( ) = = 0 ) // '/c [path]' was NOT specified
2018-11-11 06:25:17 +08:00
{
if ( PathFileExists ( cfgPath ) ) // vendor/conemu-maximus5/ConEmu.xml exists, copy vendor/conemu-maximus5/ConEmu.xml to config/user_conemu.xml.
2018-03-13 23:38:27 +08:00
{
2018-11-11 06:25:17 +08:00
if ( ! CopyFile ( cfgPath , userCfgPath , FALSE ) )
{
MessageBox ( NULL ,
( GetLastError ( ) = = ERROR_ACCESS_DENIED )
? L " Failed to copy vendor/conemu-maximus5/ConEmu.xml file to config/user-conemu.xml! Access Denied. "
: L " Failed to copy vendor/conemu-maximus5/ConEmu.xml file to config/user-conemu.xml! " , MB_TITLE , MB_ICONSTOP ) ;
exit ( 1 ) ;
}
}
else // vendor/conemu-maximus5/ConEmu.xml does not exist, copy config/user-conemu.xml to vendor/conemu-maximus5/ConEmu.xml
{
if ( ! CopyFile ( userCfgPath , cfgPath , FALSE ) )
{
MessageBox ( NULL ,
( GetLastError ( ) = = ERROR_ACCESS_DENIED )
? L " Failed to copy config/user-conemu.xml file to vendor/conemu-maximus5/ConEmu.xml! Access Denied. "
: L " Failed to copy config/user-conemu.xml file to vendor/conemu-maximus5/ConEmu.xml! " , MB_TITLE , MB_ICONSTOP ) ;
exit ( 1 ) ;
}
2018-03-13 23:38:27 +08:00
}
}
2018-11-11 21:04:35 +08:00
else // '/c [path]' was specified, don't copy anything and use existing user_conemu.xml to start comemu.
2018-11-11 06:25:17 +08:00
{
PathCombine ( userConEmuCfgPath , userConfigDirPath , L " user-ConEmu.xml " ) ;
}
2016-10-03 10:50:56 +08:00
}
2022-09-10 01:01:25 +08:00
else if ( cfgRoot . length ( ) = = 0 ) // '/c [path]' was NOT specified
2018-11-09 10:25:42 +08:00
{
2018-11-11 06:25:17 +08:00
if ( PathFileExists ( cfgPath ) ) // vendor/conemu-maximus5/ConEmu.xml exists, copy vendor/conemu-maximus5/ConEmu.xml to config/user_conemu.xml
2018-11-09 10:25:42 +08:00
{
2018-03-13 23:38:27 +08:00
if ( ! CopyFile ( cfgPath , userCfgPath , FALSE ) )
{
MessageBox ( NULL ,
( GetLastError ( ) = = ERROR_ACCESS_DENIED )
2018-11-10 22:32:44 +08:00
? L " Failed to copy vendor/conemu-maximus5/ConEmu.xml file to config/user-conemu.xml! Access Denied. "
: L " Failed to copy vendor/conemu-maximus5/ConEmu.xml file to config/user-conemu.xml! " , MB_TITLE , MB_ICONSTOP ) ;
2018-03-13 23:38:27 +08:00
exit ( 1 ) ;
}
2018-11-11 20:55:14 +08:00
else // vendor/ConEmu.xml.default config exists, copy Cmder vendor/ConEmu.xml.default file to vendor/conemu-maximus5/ConEmu.xml.
2018-03-13 23:38:27 +08:00
{
2018-11-11 06:25:17 +08:00
if ( ! CopyFile ( defaultCfgPath , cfgPath , FALSE ) )
{
MessageBox ( NULL ,
( GetLastError ( ) = = ERROR_ACCESS_DENIED )
? L " Failed to copy vendor/ConEmu.xml.default file to vendor/conemu-maximus5/ConEmu.xml! Access Denied. "
: L " Failed to copy vendor/ConEmu.xml.default file to vendor/conemu-maximus5/ConEmu.xml! " , MB_TITLE , MB_ICONSTOP ) ;
exit ( 1 ) ;
}
2018-03-13 23:38:27 +08:00
}
}
2018-12-01 03:56:30 +08:00
else {
if ( ! CopyFile ( defaultCfgPath , cfgPath , FALSE ) )
2018-03-13 23:38:27 +08:00
{
MessageBox ( NULL ,
( GetLastError ( ) = = ERROR_ACCESS_DENIED )
2018-12-01 03:56:30 +08:00
? L " Failed to copy vendor/ConEmu.xml.default file to vendor/conemu-maximus5/ConEmu.xml! Access Denied. "
: L " Failed to copy vendor/ConEmu.xml.default file to vendor/conemu-maximus5/ConEmu.xml! " , MB_TITLE , MB_ICONSTOP ) ;
2018-03-13 23:38:27 +08:00
exit ( 1 ) ;
}
}
}
2018-11-11 20:55:14 +08:00
else if ( PathFileExists ( cfgPath ) ) // vendor/conemu-maximus5/ConEmu.xml exists, copy vendor/conemu-maximus5/ConEmu.xml to config/user_conemu.xml
{
2018-03-13 23:38:27 +08:00
if ( ! CopyFile ( cfgPath , userCfgPath , FALSE ) )
{
MessageBox ( NULL ,
( GetLastError ( ) = = ERROR_ACCESS_DENIED )
2018-11-11 20:55:14 +08:00
? L " Failed to copy vendor/conemu-maximus5/ConEmu.xml file to config/user-conemu.xml! Access Denied. "
: L " Failed to copy vendor/conemu-maximus5/ConEmu.xml file to config/user-conemu.xml! " , MB_TITLE , MB_ICONSTOP ) ;
2018-03-13 23:38:27 +08:00
exit ( 1 ) ;
}
2018-11-11 20:55:14 +08:00
PathCombine ( userConEmuCfgPath , userConfigDirPath , L " user-ConEmu.xml " ) ;
2016-10-03 10:50:56 +08:00
}
2018-11-11 21:04:35 +08:00
else // '/c [path]' was specified and 'vendor/ConEmu.xml.default' config exists, copy Cmder 'vendor/ConEmu.xml.default' file to '[user specified path]/config/user_ConEmu.xml'.
2018-11-09 10:25:42 +08:00
{
2018-11-11 06:25:17 +08:00
if ( ! CopyFile ( defaultCfgPath , userCfgPath , FALSE ) )
2018-03-13 23:38:27 +08:00
{
MessageBox ( NULL ,
( GetLastError ( ) = = ERROR_ACCESS_DENIED )
2018-11-11 06:25:17 +08:00
? L " Failed to copy vendor/ConEmu.xml.default file to [user specified path]/config/user_ConEmu.xml! Access Denied. "
: L " Failed to copy vendor/ConEmu.xml.default file to [user specified path]/config/user_ConEmu.xml! " , MB_TITLE , MB_ICONSTOP ) ;
2018-03-13 23:38:27 +08:00
exit ( 1 ) ;
}
2018-11-11 06:25:17 +08:00
PathCombine ( userConEmuCfgPath , userConfigDirPath , L " user-ConEmu.xml " ) ;
2015-03-18 04:39:27 +08:00
}
2015-11-01 06:29:10 +08:00
2016-06-30 07:55:13 +08:00
SYSTEM_INFO sysInfo ;
GetNativeSystemInfo ( & sysInfo ) ;
2018-11-09 10:25:42 +08:00
if ( sysInfo . wProcessorArchitecture = = PROCESSOR_ARCHITECTURE_AMD64 )
{
2016-06-30 07:55:13 +08:00
PathCombine ( conEmuPath , exeDir , L " vendor \\ conemu-maximus5 \\ ConEmu64.exe " ) ;
}
2018-11-09 10:25:42 +08:00
else
{
2016-06-30 07:55:13 +08:00
PathCombine ( conEmuPath , exeDir , L " vendor \\ conemu-maximus5 \\ ConEmu.exe " ) ;
}
2013-11-30 22:15:42 +08:00
2020-06-24 13:17:48 +08:00
swprintf_s ( args , L " %s /Icon \" %s \" " , args , icoPath ) ;
2018-11-11 06:25:17 +08:00
if ( ! streqi ( cmderStart . c_str ( ) , L " " ) )
{
swprintf_s ( args , L " %s /dir \" %s \" " , args , cmderStart . c_str ( ) ) ;
}
2015-09-05 04:16:30 +08:00
if ( is_single_mode )
2014-11-20 23:59:17 +08:00
{
2018-11-11 06:25:17 +08:00
swprintf_s ( args , L " %s /single " , args ) ;
2014-11-20 23:59:17 +08:00
}
2018-11-11 06:25:17 +08:00
if ( ! streqi ( cmderTask . c_str ( ) , L " " ) )
2014-11-20 23:59:17 +08:00
{
2018-11-11 06:25:17 +08:00
swprintf_s ( args , L " %s /run {%s} " , args , cmderTask . c_str ( ) ) ;
}
2020-06-24 13:17:48 +08:00
if ( ! streqi ( cmderTitle . c_str ( ) , L " " ) )
{
swprintf_s ( args , L " %s /title \" %s \" " , args , cmderTitle . c_str ( ) ) ;
}
2018-11-11 06:25:17 +08:00
if ( cfgRoot . length ( ) ! = 0 )
{
swprintf_s ( args , L " %s -loadcfgfile \" %s \" " , args , userConEmuCfgPath ) ;
2014-11-20 23:59:17 +08:00
}
2013-11-30 22:15:42 +08:00
2019-05-20 04:54:47 +08:00
if ( ! streqi ( cmderConEmuArgs . c_str ( ) , L " " ) )
2019-05-12 21:18:15 +08:00
{
2019-05-20 04:54:47 +08:00
swprintf_s ( args , L " %s %s " , args , cmderConEmuArgs . c_str ( ) ) ;
2014-11-20 23:59:17 +08:00
}
2013-11-30 22:15:42 +08:00
2018-01-09 02:22:42 +08:00
SetEnvironmentVariable ( L " CMDER_ROOT " , exeDir ) ;
2018-03-13 23:38:27 +08:00
if ( wcscmp ( userConfigDirPath , configDirPath ) ! = 0 )
{
SetEnvironmentVariable ( L " CMDER_USER_CONFIG " , userConfigDirPath ) ;
SetEnvironmentVariable ( L " CMDER_USER_BIN " , userBinDirPath ) ;
}
2018-01-09 02:22:42 +08:00
2016-01-15 21:13:16 +08:00
// Ensure EnvironmentVariables are propagated.
2016-10-15 05:36:22 +08:00
2013-11-30 22:15:42 +08:00
STARTUPINFO si = { 0 } ;
2018-03-13 23:38:27 +08:00
2013-11-30 22:15:42 +08:00
si . cb = sizeof ( STARTUPINFO ) ;
# if USE_TASKBAR_API
si . lpTitle = appId ;
si . dwFlags = STARTF_TITLEISAPPID ;
# endif
PROCESS_INFORMATION pi ;
2016-02-01 05:35:57 +08:00
if ( ! CreateProcess ( conEmuPath , args , NULL , NULL , false , 0 , NULL , NULL , & si , & pi ) ) {
2018-01-09 02:22:42 +08:00
MessageBox ( NULL , _T ( " Unable to create the ConEmu process! " ) , _T ( " Error " ) , MB_OK ) ;
2016-02-01 05:35:57 +08:00
return ;
}
2016-10-15 05:36:22 +08:00
LRESULT lr = SendMessageTimeout ( HWND_BROADCAST , WM_SETTINGCHANGE , 0 , ( LPARAM ) " Environment " , SMTO_ABORTIFHUNG | SMTO_NOTIMEOUTIFNOTHUNG , 5000 , NULL ) ;
2016-04-14 02:16:58 +08:00
lr = SendMessageTimeout ( HWND_BROADCAST , WM_SETTINGCHANGE , 0 , ( LPARAM ) L " Environment " , SMTO_ABORTIFHUNG | SMTO_NOTIMEOUTIFNOTHUNG , 5000 , NULL ) ; // For Windows >= 8
2013-12-07 22:17:35 +08:00
}
bool IsUserOnly ( std : : wstring opt )
{
bool userOnly ;
if ( streqi ( opt . c_str ( ) , L " ALL " ) )
{
userOnly = false ;
}
else if ( streqi ( opt . c_str ( ) , L " USER " ) )
{
userOnly = true ;
}
else
{
MessageBox ( NULL , L " Unrecognized option for /REGISTER or /UNREGISTER. Must be either ALL or USER. " , MB_TITLE , MB_OK ) ;
exit ( 1 ) ;
}
return userOnly ;
}
HKEY GetRootKey ( std : : wstring opt )
{
HKEY root ;
if ( IsUserOnly ( opt ) )
{
2016-04-14 02:16:58 +08:00
FAIL_ON_ERROR ( RegCreateKeyEx ( HKEY_CURRENT_USER , L " Software \\ Classes " , 0 , NULL , REG_OPTION_NON_VOLATILE , KEY_ALL_ACCESS , NULL , & root , NULL ) ) ;
2013-12-07 22:17:35 +08:00
}
else
{
root = HKEY_CLASSES_ROOT ;
}
return root ;
}
2018-12-08 13:05:51 +08:00
void RegisterShellMenu ( std : : wstring opt , wchar_t * keyBaseName , std : : wstring cfgRoot , bool single )
2013-12-07 22:17:35 +08:00
{
2018-11-12 22:22:05 +08:00
wchar_t userConfigDirPath [ MAX_PATH ] = { 0 } ;
2014-02-28 07:34:37 +08:00
// First, get the paths we will use
wchar_t exePath [ MAX_PATH ] = { 0 } ;
wchar_t icoPath [ MAX_PATH ] = { 0 } ;
GetModuleFileName ( NULL , exePath , sizeof ( exePath ) ) ;
2018-03-14 06:40:07 +08:00
wchar_t commandStr [ MAX_PATH + 20 ] = { 0 } ;
2018-12-08 13:05:51 +08:00
wchar_t baseCommandStr [ MAX_PATH + 20 ] = { 0 } ;
if ( ! single ) {
swprintf_s ( baseCommandStr , L " \" %s \" " , exePath ) ;
}
else {
swprintf_s ( baseCommandStr , L " \" %s \" /single " , exePath ) ;
}
2018-11-12 22:22:05 +08:00
if ( cfgRoot . length ( ) = = 0 ) // '/c [path]' was NOT specified
{
2018-12-08 13:05:51 +08:00
swprintf_s ( commandStr , L " %s \" %%V \" " , baseCommandStr ) ;
2018-11-12 22:22:05 +08:00
}
else {
std : : copy ( cfgRoot . begin ( ) , cfgRoot . end ( ) , userConfigDirPath ) ;
userConfigDirPath [ cfgRoot . length ( ) ] = 0 ;
2018-12-08 13:05:51 +08:00
swprintf_s ( commandStr , L " %s /c \" %s \" \" %%V \" " , baseCommandStr , userConfigDirPath ) ;
2018-11-12 22:22:05 +08:00
}
2014-02-28 07:34:37 +08:00
2018-03-14 06:40:07 +08:00
// Now that we have `commandStr`, it's OK to change `exePath`...
PathRemoveFileSpec ( exePath ) ;
2014-02-28 07:34:37 +08:00
2018-03-14 06:40:07 +08:00
PathCombine ( icoPath , exePath , L " icons \\ cmder.ico " ) ;
2014-02-28 07:34:37 +08:00
2018-03-14 06:40:07 +08:00
// Now set the registry keys
HKEY root = GetRootKey ( opt ) ;
2013-12-07 22:17:35 +08:00
2018-03-14 06:40:07 +08:00
HKEY cmderKey ;
FAIL_ON_ERROR ( RegCreateKeyEx ( root , keyBaseName , 0 , NULL , REG_OPTION_NON_VOLATILE , KEY_ALL_ACCESS , NULL , & cmderKey , NULL ) ) ;
2013-12-07 22:17:35 +08:00
2018-03-14 06:40:07 +08:00
FAIL_ON_ERROR ( RegSetValue ( cmderKey , L " " , REG_SZ , L " Cmder Here " , NULL ) ) ;
FAIL_ON_ERROR ( RegSetValueEx ( cmderKey , L " NoWorkingDirectory " , 0 , REG_SZ , ( BYTE * ) L " " , 2 ) ) ;
2013-12-07 22:17:35 +08:00
2018-03-14 06:40:07 +08:00
FAIL_ON_ERROR ( RegSetValueEx ( cmderKey , L " Icon " , 0 , REG_SZ , ( BYTE * ) icoPath , wcslen ( icoPath ) * sizeof ( wchar_t ) ) ) ;
2014-02-28 07:34:37 +08:00
2018-03-14 06:40:07 +08:00
HKEY command ;
FAIL_ON_ERROR ( RegCreateKeyEx ( cmderKey , L " command " , 0 , NULL , REG_OPTION_NON_VOLATILE , KEY_ALL_ACCESS , NULL , & command , NULL ) ) ;
2013-12-07 22:17:35 +08:00
2018-03-14 06:40:07 +08:00
FAIL_ON_ERROR ( RegSetValue ( command , L " " , REG_SZ , commandStr , NULL ) ) ;
2013-12-07 22:17:35 +08:00
2018-03-14 06:40:07 +08:00
RegCloseKey ( command ) ;
RegCloseKey ( cmderKey ) ;
RegCloseKey ( root ) ;
2013-12-07 22:17:35 +08:00
}
2014-02-28 07:34:37 +08:00
void UnregisterShellMenu ( std : : wstring opt , wchar_t * keyBaseName )
2013-12-07 22:17:35 +08:00
{
HKEY root = GetRootKey ( opt ) ;
HKEY cmderKey ;
2016-04-14 02:16:58 +08:00
FAIL_ON_ERROR ( RegCreateKeyEx ( root , keyBaseName , 0 , NULL , REG_OPTION_NON_VOLATILE , KEY_ALL_ACCESS , NULL , & cmderKey , NULL ) ) ;
2014-08-27 06:52:49 +08:00
FAIL_ON_ERROR ( RegDeleteTree ( cmderKey , NULL ) ) ;
2018-04-13 09:41:42 +08:00
RegDeleteKeyEx ( root , keyBaseName , KEY_ALL_ACCESS , NULL ) ;
2013-12-07 22:17:35 +08:00
RegCloseKey ( cmderKey ) ;
RegCloseKey ( root ) ;
}
2018-03-13 23:38:27 +08:00
struct cmderOptions
{
std : : wstring cmderCfgRoot = L " " ;
std : : wstring cmderStart = L " " ;
std : : wstring cmderTask = L " " ;
2020-06-24 13:17:48 +08:00
std : : wstring cmderTitle = L " Cmder " ;
2020-06-24 08:50:15 +08:00
std : : wstring cmderIcon = L " " ;
2018-03-13 23:38:27 +08:00
std : : wstring cmderRegScope = L " USER " ;
2019-05-20 04:54:47 +08:00
std : : wstring cmderConEmuArgs = L " " ;
2018-03-13 23:38:27 +08:00
bool cmderSingle = false ;
2018-11-12 20:56:55 +08:00
bool cmderUserCfg = true ;
2018-03-13 23:38:27 +08:00
bool registerApp = false ;
bool unRegisterApp = false ;
bool error = false ;
} ;
cmderOptions GetOption ( )
{
cmderOptions cmderOptions ;
LPWSTR * szArgList ;
int argCount ;
szArgList = CommandLineToArgvW ( GetCommandLine ( ) , & argCount ) ;
for ( int i = 1 ; i < argCount ; i + + )
{
2018-09-04 00:06:39 +08:00
2018-03-13 23:38:27 +08:00
// MessageBox(NULL, szArgList[i], L"Arglist contents", MB_OK);
2018-11-12 21:30:44 +08:00
if ( cmderOptions . error = = false ) {
if ( _wcsicmp ( L " /c " , szArgList [ i ] ) = = 0 )
{
TCHAR userProfile [ MAX_PATH ] ;
const DWORD ret = GetEnvironmentVariable ( L " USERPROFILE " , userProfile , MAX_PATH ) ;
2018-03-13 23:38:27 +08:00
2018-11-12 21:30:44 +08:00
wchar_t cmderCfgRoot [ MAX_PATH ] = { 0 } ;
PathCombine ( cmderCfgRoot , userProfile , L " cmder_cfg " ) ;
2018-03-13 23:38:27 +08:00
2018-11-12 21:30:44 +08:00
cmderOptions . cmderCfgRoot = cmderCfgRoot ;
2018-03-13 23:38:27 +08:00
2018-11-12 21:30:44 +08:00
if ( szArgList [ i + 1 ] ! = NULL & & szArgList [ i + 1 ] [ 0 ] ! = ' / ' )
{
cmderOptions . cmderCfgRoot = szArgList [ i + 1 ] ;
i + + ;
}
2018-03-13 23:38:27 +08:00
}
2018-11-12 21:30:44 +08:00
else if ( _wcsicmp ( L " /start " , szArgList [ i ] ) = = 0 )
2018-09-04 00:06:39 +08:00
{
2018-11-12 21:30:44 +08:00
int len = wcslen ( szArgList [ i + 1 ] ) ;
if ( wcscmp ( & szArgList [ i + 1 ] [ len - 1 ] , L " \" " ) = = 0 )
{
szArgList [ i + 1 ] [ len - 1 ] = ' \0 ' ;
}
2018-03-13 23:38:27 +08:00
2018-11-12 21:30:44 +08:00
if ( PathFileExists ( szArgList [ i + 1 ] ) )
{
cmderOptions . cmderStart = szArgList [ i + 1 ] ;
i + + ;
}
else
{
MessageBox ( NULL , szArgList [ i + 1 ] , L " /START - Folder does not exist! " , MB_OK ) ;
}
}
else if ( _wcsicmp ( L " /task " , szArgList [ i ] ) = = 0 )
2018-03-13 23:38:27 +08:00
{
2018-11-12 21:30:44 +08:00
cmderOptions . cmderTask = szArgList [ i + 1 ] ;
2018-03-13 23:38:27 +08:00
i + + ;
}
2020-06-24 13:17:48 +08:00
else if ( _wcsicmp ( L " /title " , szArgList [ i ] ) = = 0 )
{
cmderOptions . cmderTitle = szArgList [ i + 1 ] ;
i + + ;
}
2020-06-24 08:50:15 +08:00
else if ( _wcsicmp ( L " /icon " , szArgList [ i ] ) = = 0 )
2018-03-13 23:38:27 +08:00
{
2020-06-24 08:50:15 +08:00
cmderOptions . cmderIcon = szArgList [ i + 1 ] ;
2018-03-13 23:38:27 +08:00
i + + ;
}
2018-11-12 21:30:44 +08:00
else if ( _wcsicmp ( L " /single " , szArgList [ i ] ) = = 0 )
2018-11-09 10:25:42 +08:00
{
2018-11-12 21:30:44 +08:00
cmderOptions . cmderSingle = true ;
2018-03-13 23:38:27 +08:00
}
2018-11-12 21:30:44 +08:00
else if ( _wcsicmp ( L " /m " , szArgList [ i ] ) = = 0 )
2018-03-14 06:40:07 +08:00
{
2018-11-12 21:30:44 +08:00
cmderOptions . cmderUserCfg = false ;
2018-03-13 23:38:27 +08:00
}
2018-11-12 21:30:44 +08:00
else if ( _wcsicmp ( L " /register " , szArgList [ i ] ) = = 0 )
2018-03-13 23:38:27 +08:00
{
2018-11-12 21:30:44 +08:00
cmderOptions . registerApp = true ;
cmderOptions . unRegisterApp = false ;
if ( szArgList [ i + 1 ] ! = NULL )
2018-03-13 23:38:27 +08:00
{
2018-11-12 21:30:44 +08:00
if ( _wcsicmp ( L " all " , szArgList [ i + 1 ] ) = = 0 | | _wcsicmp ( L " user " , szArgList [ i + 1 ] ) = = 0 )
{
cmderOptions . cmderRegScope = szArgList [ i + 1 ] ;
i + + ;
}
2018-03-13 23:38:27 +08:00
}
}
2018-11-12 21:30:44 +08:00
else if ( _wcsicmp ( L " /unregister " , szArgList [ i ] ) = = 0 )
2018-09-04 00:06:39 +08:00
{
2018-11-12 21:30:44 +08:00
cmderOptions . unRegisterApp = true ;
cmderOptions . registerApp = false ;
if ( szArgList [ i + 1 ] ! = NULL )
{
if ( _wcsicmp ( L " all " , szArgList [ i + 1 ] ) = = 0 | | _wcsicmp ( L " user " , szArgList [ i + 1 ] ) = = 0 )
{
cmderOptions . cmderRegScope = szArgList [ i + 1 ] ;
i + + ;
}
}
2018-09-04 00:06:39 +08:00
}
2019-05-20 04:54:47 +08:00
/* Used for passing arguments to conemu prog */
else if ( _wcsicmp ( L " /x " , szArgList [ i ] ) = = 0 )
2019-05-12 21:18:15 +08:00
{
2019-05-20 04:54:47 +08:00
cmderOptions . cmderConEmuArgs = szArgList [ i + 1 ] ;
2019-05-12 21:18:15 +08:00
i + + ;
}
2019-10-07 04:52:50 +08:00
/* Bare double dash, remaining commandline is for conemu */
else if ( _wcsicmp ( L " -- " , szArgList [ i ] ) = = 0 )
{
std : : wstring cmdline = std : : wstring ( GetCommandLineW ( ) ) ;
auto doubledash = cmdline . find ( L " -- " ) ;
if ( doubledash ! = std : : string : : npos )
{
cmderOptions . cmderConEmuArgs = cmdline . substr ( doubledash + 4 ) ;
}
break ;
}
2018-11-12 21:30:44 +08:00
else if ( cmderOptions . cmderStart = = L " " )
2018-03-13 23:38:27 +08:00
{
2018-11-12 21:30:44 +08:00
int len = wcslen ( szArgList [ i ] ) ;
if ( wcscmp ( & szArgList [ i ] [ len - 1 ] , L " \" " ) = = 0 )
{
szArgList [ i ] [ len - 1 ] = ' \0 ' ;
}
if ( PathFileExists ( szArgList [ i ] ) )
2018-03-13 23:38:27 +08:00
{
2018-11-12 21:30:44 +08:00
cmderOptions . cmderStart = szArgList [ i ] ;
2018-03-13 23:38:27 +08:00
i + + ;
}
2018-11-12 21:30:44 +08:00
else
{
cmderOptions . error = true ;
}
2018-09-04 00:06:39 +08:00
}
2018-11-09 10:25:42 +08:00
else
{
2018-11-12 21:30:44 +08:00
cmderOptions . error = true ;
2018-03-13 23:38:27 +08:00
}
}
2018-09-05 06:48:59 +08:00
2022-09-10 01:01:25 +08:00
}
if ( cmderOptions . error = = true )
{
wchar_t validOptions [ 512 ] ;
HMODULE hMod = GetModuleHandle ( NULL ) ;
LoadString ( hMod , IDS_SWITCHES , validOptions , 512 ) ;
// display list of valid options on unrecognized parameter
TaskDialogOpen ( L " Unrecognized parameter. " , validOptions ) ;
2018-03-13 23:38:27 +08:00
}
LocalFree ( szArgList ) ;
return cmderOptions ;
}
2018-03-23 22:20:07 +08:00
2013-12-07 22:17:35 +08:00
int APIENTRY _tWinMain ( _In_ HINSTANCE hInstance ,
_In_opt_ HINSTANCE hPrevInstance ,
_In_ LPTSTR lpCmdLine ,
_In_ int nCmdShow )
{
UNREFERENCED_PARAMETER ( hPrevInstance ) ;
UNREFERENCED_PARAMETER ( lpCmdLine ) ;
UNREFERENCED_PARAMETER ( nCmdShow ) ;
2018-03-13 23:38:27 +08:00
cmderOptions cmderOptions = GetOption ( ) ;
2013-12-07 22:17:35 +08:00
2018-11-09 10:25:42 +08:00
if ( cmderOptions . registerApp = = true )
{
2018-12-08 13:05:51 +08:00
RegisterShellMenu ( cmderOptions . cmderRegScope , SHELL_MENU_REGISTRY_PATH_BACKGROUND , cmderOptions . cmderCfgRoot , cmderOptions . cmderSingle ) ;
RegisterShellMenu ( cmderOptions . cmderRegScope , SHELL_MENU_REGISTRY_PATH_LISTITEM , cmderOptions . cmderCfgRoot , cmderOptions . cmderSingle ) ;
2019-03-17 07:15:36 +08:00
RegisterShellMenu ( cmderOptions . cmderRegScope , SHELL_MENU_REGISTRY_DRIVE_PATH_BACKGROUND , cmderOptions . cmderCfgRoot , cmderOptions . cmderSingle ) ;
RegisterShellMenu ( cmderOptions . cmderRegScope , SHELL_MENU_REGISTRY_DRIVE_PATH_LISTITEM , cmderOptions . cmderCfgRoot , cmderOptions . cmderSingle ) ;
2014-11-20 23:59:17 +08:00
}
2018-03-14 06:40:07 +08:00
else if ( cmderOptions . unRegisterApp = = true )
2014-11-20 23:59:17 +08:00
{
2018-03-13 23:38:27 +08:00
UnregisterShellMenu ( cmderOptions . cmderRegScope , SHELL_MENU_REGISTRY_PATH_BACKGROUND ) ;
UnregisterShellMenu ( cmderOptions . cmderRegScope , SHELL_MENU_REGISTRY_PATH_LISTITEM ) ;
2019-03-17 07:15:36 +08:00
UnregisterShellMenu ( cmderOptions . cmderRegScope , SHELL_MENU_REGISTRY_DRIVE_PATH_BACKGROUND ) ;
UnregisterShellMenu ( cmderOptions . cmderRegScope , SHELL_MENU_REGISTRY_DRIVE_PATH_LISTITEM ) ;
2013-12-07 22:17:35 +08:00
}
2018-03-13 23:38:27 +08:00
else if ( cmderOptions . error = = true )
2017-06-17 22:29:06 +08:00
{
2018-03-13 23:38:27 +08:00
return 1 ;
2013-12-07 22:17:35 +08:00
}
else
{
2020-06-24 13:23:28 +08:00
StartCmder ( cmderOptions . cmderStart , cmderOptions . cmderSingle , cmderOptions . cmderTask , cmderOptions . cmderTitle , cmderOptions . cmderIcon , cmderOptions . cmderCfgRoot , cmderOptions . cmderUserCfg , cmderOptions . cmderConEmuArgs ) ;
2013-12-07 22:17:35 +08:00
}
2018-03-14 06:40:07 +08:00
2013-11-30 22:15:42 +08:00
return 0 ;
2014-01-22 02:25:24 +08:00
}