chore: initial commit (extracted from Launchers monorepo)

Plugin: nsShellExecAsUser v1.0.0
Architectures: x86-ansi, x86-unicode, amd64-unicode
License: zlib
This commit is contained in:
Simone
2026-04-29 14:04:59 +02:00
commit c98a0d37d9
30 changed files with 3109 additions and 0 deletions
+272
View File
@@ -0,0 +1,272 @@
// ShellExecAsUser.cpp : Defines the entry point for the DLL application.
//
#include <windows.h>
#include <shlDisp.h>
#include <atlbase.h>
#include <Exdisp.h>
#include <shobjidl.h>
#include <shlguid.h>
//#include <process.h>
#include "pluginapi.h" // nsis plugin
#include <shellApi.h>
//#pragma comment(linker,"/merge:.rdata=.text")
//VistaTools
#define NO_DLL_IMPORTS 1
#define DONTWANT_RunNonElevated 1
#define IMPLEMENT_VISTA_TOOLS
#include "VistaTools.cxx"
//////////////////////////////////////
//missing in old sdk, had to replace shlwapi.lib as well
//LWSTDAPI IUnknown_QueryService(__in IUnknown* punk, __in REFGUID guidService, __in REFIID riid, __deref_out void ** ppvOut);
HINSTANCE g_hInstance;
HWND g_hwndParent;
HWND g_hwnd;
HANDLE g_hThread;
typedef struct _ExecShellParams {
TCHAR action[50];
TCHAR command[_MAX_PATH];
TCHAR params[1024];
TCHAR directory[_MAX_PATH];
int iShow;
} ExecShellParams;
UINT_PTR NSISPluginCallback(enum NSPIM Event)
{
switch(Event)
{
case NSPIM_UNLOAD:
if (g_hThread) {
//OutputDebugString("ExecShellAsUser: NSPIM_UNLOAD wait...");
::PostMessage(g_hwnd, WM_USER+11, 0, 0);
::WaitForSingleObject(g_hThread, INFINITE);
::CloseHandle(g_hThread);
//OutputDebugString("ExecShellAsUser: NSPIM_UNLOAD");
}
break;
}
return NULL;
}
//http://brandonlive.com/2008/04/27/getting-the-shell-to-run-an-application-for-you-part-2-how/
static CComQIPtr<IShellDispatch2> retrieveDesktop()
{
CComPtr<IShellWindows> psw;
HRESULT hr = psw.CoCreateInstance(CLSID_ShellWindows, NULL, CLSCTX_LOCAL_SERVER);
if (SUCCEEDED(hr))
{
HWND hwnd;
CComPtr<IDispatch> pdisp;
VARIANT vEmpty;
vEmpty.vt = VT_EMPTY;
if (S_OK == (hr = psw->FindWindowSW(&vEmpty, &vEmpty, 0x8/*SWC_DESKTOP*/, (long*)&hwnd, SWFO_NEEDDISPATCH, &pdisp)))
{
CComPtr<IShellBrowser> psb;
hr = IUnknown_QueryService(pdisp, SID_STopLevelBrowser, __uuidof(IShellBrowser), (void**) &psb); //IID_PPV_ARGS(&psb)
if (SUCCEEDED(hr))
{
CComPtr<IShellView> psv;
hr = psb->QueryActiveShellView(&psv);
CComPtr<IDispatch> pdispBackground;
HRESULT hr = psv->GetItemObject(SVGIO_BACKGROUND, __uuidof(IDispatch), (void**) &pdispBackground);
if (SUCCEEDED(hr))
{
if (CComQIPtr<IShellFolderViewDual> psfvd = pdispBackground)
{
CComPtr<IDispatch> pdisp;
hr = psfvd->get_Application(&pdisp);
if (SUCCEEDED(hr))
{
return CComQIPtr<IShellDispatch2>(pdisp);
}
}
}
}
} else {
TCHAR buf[100];
wsprintf(buf, _T("ShellExecAsUser: FindWindowSW failed: %x"), hr);
OutputDebugString(buf);
}
}
return CComQIPtr<IShellDispatch2>();
}
static int getShowMode(const TCHAR* s)
{
if (s[0] == 0) return SW_SHOWNORMAL;
const TCHAR* strModes[] = { _T("SW_SHOWDEFAULT"), _T("SW_SHOWNORMAL"), _T("SW_SHOWMAXIMIZED"), _T("SW_SHOWMINIMIZED"), _T("SW_HIDE") };
int modes[] = { SW_SHOWDEFAULT, SW_SHOWNORMAL, SW_SHOWMAXIMIZED, SW_SHOWMINIMIZED, SW_HIDE };
for (int i=0; i<sizeof(strModes)/sizeof(TCHAR*); ++i) {
if (lstrcmp(s, strModes[i]) == 0)
return modes[i];
}
return SW_SHOWNORMAL;
}
static bool runCommand(IShellDispatch2* psd, ExecShellParams* params)
{
if (!psd) return false;
CComBSTR command(params->command);
CComVariant vAction, vParams, vDir;
if (params->action[0] != 0) vAction = params->action;
if (params->params[0] != 0) vParams = params->params;
if (params->directory[0] != 0) vDir = params->directory;
CComVariant vShow;
if (params->iShow != -1) vShow = params->iShow;
//#pragma push_macro("ShellExecute")
//#undef ShellExecute
HRESULT hr = psd->ShellExecute(command, vParams, vDir, vAction, vShow);
//#pragma pop_macro("ShellExecute")
return hr == S_OK;
}
static LRESULT WndProc(HWND hWnd, UINT uMsg,WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_CREATE:
{
void* param = ((LPCREATESTRUCT)lParam)->lpCreateParams;
::SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)param);
break;
}
case WM_USER+10:
{
ExecShellParams* p = (ExecShellParams*)lParam;
IShellDispatch2* pSD = (IShellDispatch2*)::GetWindowLongPtr(hWnd, GWLP_USERDATA);
runCommand(pSD, p);
delete p;
break;
}
case WM_USER+11:
DestroyWindow(hWnd);
break;
case WM_DESTROY:
{
PostQuitMessage(0);
break;
}
default:
return ::DefWindowProc(hWnd,uMsg,wParam,lParam);
};
return 0;
}
HWND CreateMessageWindow(void* data)
{
WNDCLASSEX wincl;
ZeroMemory(&wincl, sizeof(WNDCLASSEX));
wincl.hInstance = g_hInstance;
wincl.lpszClassName = _T("NSIS_DESKTOP_LAUNCH_CLASS");
wincl.lpfnWndProc = (WNDPROC)WndProc;
wincl.cbSize = sizeof (WNDCLASSEX);
ATOM atom = RegisterClassEx (&wincl);
return CreateWindowEx(
0,
MAKEINTATOM(atom),
_T(""),
0,
0,
0,
0,
0,
HWND_MESSAGE,
NULL,
wincl.hInstance,
data);
}
static unsigned __stdcall WorkerThreadProc(void* pParam)
{
HANDLE hRunEvent = (HANDLE) pParam;
::CoInitialize(NULL);
{
CComPtr<IShellDispatch2> pSD = retrieveDesktop();
OutputDebugString(pSD.p ? _T("ExecShellAsUser: got desktop") : _T("ExecShellAsUser: failed to retrieve desktop!"));
if (pSD.p) g_hwnd = CreateMessageWindow(pSD.p);
SetEvent(hRunEvent);
if (g_hwnd) {
MSG msg;
while ( GetMessage(&msg, NULL, 0, 0) > 0 )
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
::CoUninitialize();
OutputDebugString(_T("ExecShellAsUser: thread finished"));
return 0;
}
#define EMPTY_TO_NULL(s) (s[0] == 0 ? NULL : s)
extern "C"
void __declspec(dllexport) ShellExecAsUser(HWND hwndParent, int string_size,
TCHAR *variables, stack_t **stacktop,
extra_parameters *extra)
{
static int initDone=0;
g_hwndParent=hwndParent;
EXDLL_INIT();
if (initDone == 0) {
initDone=1;
extra->RegisterPluginCallback(g_hInstance, NSISPluginCallback);
if (IsVista() && IsElevated(NULL) == S_OK) {
//note: COM calls to shell interfaces have to be executed on another thread,
//otherwise I got RPC_E_CANTCALLOUT_ININPUTSYNCCALL error.
HANDLE hRunEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL); //manual reset
g_hThread = (HANDLE)_beginthreadex( NULL, 0, WorkerThreadProc, hRunEvent, 0, NULL);
if (g_hThread) ::WaitForSingleObject(hRunEvent, INFINITE);
CloseHandle(hRunEvent);
OutputDebugString(_T("ExecShellAsUser: elevated process detected"));
} else {
OutputDebugString(_T("ExecShellAsUser: process is not elevated, will fallback to ShellExecute"));
}
}
// action command [parameters] [SW_SHOWDEFAULT | SW_SHOWNORMAL | SW_SHOWMAXIMIZED | SW_SHOWMINIMIZED | SW_HIDE]
ExecShellParams execShellParams;
ExecShellParams* params = g_hwnd ? new ExecShellParams : &execShellParams;
TCHAR show[50];
popstring(params->action);
popstring(params->command);
popstring(params->params);
popstring(show);
params->iShow = getShowMode(show);
TCHAR* dir = getuservariable(INST_OUTDIR);
if (g_hwnd) {
if (dir) lstrcpyn(params->directory, dir, sizeof(params->directory)/sizeof(params->directory[0]));
::PostMessage(g_hwnd, WM_USER+10, 0, (LPARAM)params);
} else {
::ShellExecute(NULL, EMPTY_TO_NULL(params->action), params->command, EMPTY_TO_NULL(params->params), dir, params->iShow);
}
}
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
if(ul_reason_for_call==DLL_PROCESS_ATTACH)
{
g_hInstance = (HINSTANCE) hModule;
} else if (ul_reason_for_call==DLL_PROCESS_DETACH) {
OutputDebugString(_T("ExecShellAsUser: DLL_PROCESS_DETACH"));
}
return TRUE;
}
+32
View File
@@ -0,0 +1,32 @@
Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ShellExecAsUser", "ShellExecAsUser.vcxproj", "{8384A5B1-BFFE-254C-4F8D-3C865339D9ED}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
ReleaseUnicode|Win32 = ReleaseUnicode|Win32
ReleaseUnicode|x64 = ReleaseUnicode|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8384A5B1-BFFE-254C-4F8D-3C865339D9ED}.Debug|Win32.ActiveCfg = Debug|Win32
{8384A5B1-BFFE-254C-4F8D-3C865339D9ED}.Debug|Win32.Build.0 = Debug|Win32
{8384A5B1-BFFE-254C-4F8D-3C865339D9ED}.Debug|x64.ActiveCfg = Debug|x64
{8384A5B1-BFFE-254C-4F8D-3C865339D9ED}.Debug|x64.Build.0 = Debug|x64
{8384A5B1-BFFE-254C-4F8D-3C865339D9ED}.Release|Win32.ActiveCfg = Release|Win32
{8384A5B1-BFFE-254C-4F8D-3C865339D9ED}.Release|Win32.Build.0 = Release|Win32
{8384A5B1-BFFE-254C-4F8D-3C865339D9ED}.Release|x64.ActiveCfg = Release|x64
{8384A5B1-BFFE-254C-4F8D-3C865339D9ED}.Release|x64.Build.0 = Release|x64
{8384A5B1-BFFE-254C-4F8D-3C865339D9ED}.ReleaseUnicode|Win32.ActiveCfg = ReleaseUnicode|Win32
{8384A5B1-BFFE-254C-4F8D-3C865339D9ED}.ReleaseUnicode|Win32.Build.0 = ReleaseUnicode|Win32
{8384A5B1-BFFE-254C-4F8D-3C865339D9ED}.ReleaseUnicode|x64.ActiveCfg = ReleaseUnicode|x64
{8384A5B1-BFFE-254C-4F8D-3C865339D9ED}.ReleaseUnicode|x64.Build.0 = ReleaseUnicode|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
+394
View File
@@ -0,0 +1,394 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="ReleaseUnicode|Win32">
<Configuration>ReleaseUnicode</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="ReleaseUnicode|x64">
<Configuration>ReleaseUnicode</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<SccProjectName />
<SccLocalPath />
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseUnicode|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseUnicode|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfMfc>false</UseOfMfc>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseUnicode|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseUnicode|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>$(SolutionDir)..\..\Plugins\x86-ansi\</OutDir>
<IntDir>$(SolutionDir)Intermediate\$(Configuration)\$(PlatformShortName)\</IntDir>
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>$(SolutionDir)..\..\Plugins\amd64-ansi\</OutDir>
<IntDir>$(SolutionDir)Intermediate\$(Configuration)\$(PlatformShortName)\</IntDir>
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseUnicode|Win32'">
<LinkIncremental>false</LinkIncremental>
<IntDir>$(SolutionDir)Intermediate\$(Configuration)\$(PlatformShortName)\</IntDir>
<OutDir>$(SolutionDir)..\..\Plugins\x86-unicode\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseUnicode|x64'">
<LinkIncremental>false</LinkIncremental>
<IntDir>$(SolutionDir)Intermediate\$(Configuration)\$(PlatformShortName)\</IntDir>
<OutDir>$(SolutionDir)..\..\Plugins\amd64-unicode\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>$(SolutionDir)..\..\Plugins\x86-ansi-debug\</OutDir>
<IntDir>$(SolutionDir)Intermediate\$(Configuration)\$(PlatformShortName)\</IntDir>
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>$(SolutionDir)..\..\Plugins\amd64-ansi-debug\</OutDir>
<IntDir>$(SolutionDir)Intermediate\$(Configuration)\$(PlatformShortName)\</IntDir>
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<StringPooling>true</StringPooling>
<Optimization>MinSpace</Optimization>
<SuppressStartupBanner>true</SuppressStartupBanner>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;SHELLEXECASUSER_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>
</PrecompiledHeader>
<AdditionalIncludeDirectories>nsis</AdditionalIncludeDirectories>
<WholeProgramOptimization>true</WholeProgramOptimization>
<ExceptionHandling>false</ExceptionHandling>
<PrecompiledHeaderOutputFile>$(IntDir)\$(TargetName).pch</PrecompiledHeaderOutputFile>
</ClCompile>
<Midl>
<SuppressStartupBanner>true</SuppressStartupBanner>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<TypeLibraryName>.\Release\ShellExecAsUser.tlb</TypeLibraryName>
<MkTypLibCompatible>true</MkTypLibCompatible>
<TargetEnvironment>Win32</TargetEnvironment>
</Midl>
<ResourceCompile>
<Culture>0x0409</Culture>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Bscmake>
<SuppressStartupBanner>true</SuppressStartupBanner>
<OutputFile>.\Release\ShellExecAsUser.bsc</OutputFile>
</Bscmake>
<Link>
<SuppressStartupBanner>true</SuppressStartupBanner>
<LinkDLL>true</LinkDLL>
<SubSystem>Windows</SubSystem>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<ImportLibrary>
</ImportLibrary>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>
</AdditionalLibraryDirectories>
<IgnoreSpecificDefaultLibraries>libc.lib</IgnoreSpecificDefaultLibraries>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<StringPooling>true</StringPooling>
<Optimization>MinSpace</Optimization>
<SuppressStartupBanner>true</SuppressStartupBanner>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;SHELLEXECASUSER_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>
</PrecompiledHeader>
<AdditionalIncludeDirectories>nsis</AdditionalIncludeDirectories>
<WholeProgramOptimization>true</WholeProgramOptimization>
<ExceptionHandling>false</ExceptionHandling>
<PrecompiledHeaderOutputFile>$(IntDir)\$(TargetName).pch</PrecompiledHeaderOutputFile>
</ClCompile>
<Midl>
<SuppressStartupBanner>true</SuppressStartupBanner>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<TypeLibraryName>.\Release\ShellExecAsUser.tlb</TypeLibraryName>
<MkTypLibCompatible>true</MkTypLibCompatible>
</Midl>
<ResourceCompile>
<Culture>0x0409</Culture>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Bscmake>
<SuppressStartupBanner>true</SuppressStartupBanner>
<OutputFile>.\Release\ShellExecAsUser.bsc</OutputFile>
</Bscmake>
<Link>
<SuppressStartupBanner>true</SuppressStartupBanner>
<LinkDLL>true</LinkDLL>
<SubSystem>Windows</SubSystem>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<ImportLibrary>
</ImportLibrary>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>
</AdditionalLibraryDirectories>
<IgnoreSpecificDefaultLibraries>libc.lib</IgnoreSpecificDefaultLibraries>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseUnicode|Win32'">
<ClCompile>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<StringPooling>true</StringPooling>
<Optimization>MinSpace</Optimization>
<SuppressStartupBanner>true</SuppressStartupBanner>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;SHELLEXECASUSER_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>
</PrecompiledHeader>
<AdditionalIncludeDirectories>nsis</AdditionalIncludeDirectories>
<WholeProgramOptimization>true</WholeProgramOptimization>
<ExceptionHandling>false</ExceptionHandling>
<PrecompiledHeaderOutputFile>$(IntDir)\$(TargetName).pch</PrecompiledHeaderOutputFile>
</ClCompile>
<Midl>
<SuppressStartupBanner>true</SuppressStartupBanner>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<TypeLibraryName>.\Release\ShellExecAsUser.tlb</TypeLibraryName>
<MkTypLibCompatible>true</MkTypLibCompatible>
<TargetEnvironment>Win32</TargetEnvironment>
</Midl>
<ResourceCompile>
<Culture>0x0409</Culture>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Bscmake>
<SuppressStartupBanner>true</SuppressStartupBanner>
<OutputFile>.\Release\ShellExecAsUser.bsc</OutputFile>
</Bscmake>
<Link>
<SuppressStartupBanner>true</SuppressStartupBanner>
<LinkDLL>true</LinkDLL>
<SubSystem>Windows</SubSystem>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>
</AdditionalLibraryDirectories>
<IgnoreSpecificDefaultLibraries>libc.lib</IgnoreSpecificDefaultLibraries>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseUnicode|x64'">
<ClCompile>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<StringPooling>true</StringPooling>
<Optimization>MinSpace</Optimization>
<SuppressStartupBanner>true</SuppressStartupBanner>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;SHELLEXECASUSER_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>
</PrecompiledHeader>
<AdditionalIncludeDirectories>nsis</AdditionalIncludeDirectories>
<WholeProgramOptimization>true</WholeProgramOptimization>
<ExceptionHandling>false</ExceptionHandling>
<PrecompiledHeaderOutputFile>$(IntDir)\$(TargetName).pch</PrecompiledHeaderOutputFile>
</ClCompile>
<Midl>
<SuppressStartupBanner>true</SuppressStartupBanner>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<TypeLibraryName>.\Release\ShellExecAsUser.tlb</TypeLibraryName>
<MkTypLibCompatible>true</MkTypLibCompatible>
</Midl>
<ResourceCompile>
<Culture>0x0409</Culture>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Bscmake>
<SuppressStartupBanner>true</SuppressStartupBanner>
<OutputFile>.\Release\ShellExecAsUser.bsc</OutputFile>
</Bscmake>
<Link>
<SuppressStartupBanner>true</SuppressStartupBanner>
<LinkDLL>true</LinkDLL>
<SubSystem>Windows</SubSystem>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>
</AdditionalLibraryDirectories>
<IgnoreSpecificDefaultLibraries>libc.lib</IgnoreSpecificDefaultLibraries>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<InlineFunctionExpansion>Default</InlineFunctionExpansion>
<FunctionLevelLinking>false</FunctionLevelLinking>
<Optimization>Disabled</Optimization>
<SuppressStartupBanner>true</SuppressStartupBanner>
<WarningLevel>Level3</WarningLevel>
<MinimalRebuild>true</MinimalRebuild>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;SHELLEXECASUSER_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>
</PrecompiledHeader>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<PrecompiledHeaderOutputFile>$(IntDir)\$(TargetName).pch</PrecompiledHeaderOutputFile>
</ClCompile>
<Midl>
<SuppressStartupBanner>true</SuppressStartupBanner>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<TypeLibraryName>.\Debug\ShellExecAsUser.tlb</TypeLibraryName>
<MkTypLibCompatible>true</MkTypLibCompatible>
<TargetEnvironment>Win32</TargetEnvironment>
</Midl>
<ResourceCompile>
<Culture>0x0409</Culture>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Bscmake>
<SuppressStartupBanner>true</SuppressStartupBanner>
<OutputFile>.\Debug\ShellExecAsUser.bsc</OutputFile>
</Bscmake>
<Link>
<SuppressStartupBanner>true</SuppressStartupBanner>
<LinkDLL>true</LinkDLL>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<ImportLibrary>
</ImportLibrary>
<AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<InlineFunctionExpansion>Default</InlineFunctionExpansion>
<FunctionLevelLinking>false</FunctionLevelLinking>
<Optimization>Disabled</Optimization>
<SuppressStartupBanner>true</SuppressStartupBanner>
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;SHELLEXECASUSER_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>
</PrecompiledHeader>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<PrecompiledHeaderOutputFile>$(IntDir)\$(TargetName).pch</PrecompiledHeaderOutputFile>
</ClCompile>
<Midl>
<SuppressStartupBanner>true</SuppressStartupBanner>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<TypeLibraryName>.\Debug\ShellExecAsUser.tlb</TypeLibraryName>
<MkTypLibCompatible>true</MkTypLibCompatible>
</Midl>
<ResourceCompile>
<Culture>0x0409</Culture>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ResourceCompile>
<Bscmake>
<SuppressStartupBanner>true</SuppressStartupBanner>
<OutputFile>.\Debug\ShellExecAsUser.bsc</OutputFile>
</Bscmake>
<Link>
<SuppressStartupBanner>true</SuppressStartupBanner>
<LinkDLL>true</LinkDLL>
<GenerateDebugInformation>true</GenerateDebugInformation>
<SubSystem>Windows</SubSystem>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
<ImportLibrary>
</ImportLibrary>
<AdditionalDependencies>shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="pluginapi.cpp" />
<ClCompile Include="ShellExecAsUser.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="api.h" />
<ClInclude Include="nsis_tchar.h" />
<ClInclude Include="pluginapi.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
+12
View File
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="ShellExecAsUser.cpp" />
<ClCompile Include="pluginapi.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="api.h" />
<ClInclude Include="nsis_tchar.h" />
<ClInclude Include="pluginapi.h" />
</ItemGroup>
</Project>
+713
View File
@@ -0,0 +1,713 @@
///////////////////////////////
/* VistaTools.cxx - version 2.1
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright (C) 2008. WinAbility Software Corporation. All rights reserved.
Author: Andrei Belogortseff [ http://www.softblog.com ]
TERMS OF USE: You are free to use this file in any way you like,
for both the commercial and non-commercial purposes, royalty-free,
AS LONG AS you agree with the warranty disclaimer above,
EXCEPT that you may not remove or modify this or any of the
preceeding paragraphs. If you make any changes, please document
them in the MODIFICATIONS section below. If the changes are of general
interest, please let us know and we will consider incorporating them in
this file, as well.
If you use this file in your own project, an acknowledgment will be appreciated,
although it's not required.
SUMMARY:
This file contains several Vista-specific functions helpful when dealing with the
"elevation" features of Windows Vista. See the descriptions of the functions below
for information on what each function does and how to use it.
This file contains the Win32 stuff only, it can be used with or without other frameworks,
such as MFC, ATL, etc.
HOW TO USE THIS FILE:
Make sure you have the latest Windows SDK (see msdn.microsoft.com for more information)
or this file may not compile!
This is a "combo" file that contains both the declarations (usually placed in the .h files)
as well as the definitions (usually placed in the .cpp files) of the functions.
To get the declarations only, include it as you would any .h file, for example:
#include "VistaTools.cxx"
To get both the declarations and definitions, define IMPLEMENT_VISTA_TOOLS before including the file:
#define IMPLEMENT_VISTA_TOOLS
#include "VistaTools.cxx"
(The above should be done once and only once per project).
To use the function RunNonElevated, this file must be compiled into a DLL.
In such a case, define DLL_EXPORTS when compiling the DLL,
and do not define DLL_EXPORTS when compiling the projects linking to the DLL.
If you don't need to use RunNonElevated, then this file may be a part of an EXE
project. In such a case, define DONTWANT_RunNonElevated and NO_DLL_IMPORTS to make
this file compile properly.
NOTE: The file VistaTools.cxx can be included in the VisualStudio projects, but it should be
excluded from the build process (because its contents is compiled when it is included
in another .cpp file with IMPLEMENT_VISTA_TOOLS defined, as shown above.)
MODIFICATIONS:
v.1.0 (2006-Dec-16) created by Andrei Belogortseff.
v.2.0 (2007-Feb-20) deprecated RunAsStdUser();
implemented RunNonElevated() to replace RunAsStdUser();
added function declarations for use in a DLL project
v.2.1 (2008-Feb-24) removed RunAsStdUser();
*/
#if ( NTDDI_VERSION < NTDDI_LONGHORN )
# error NTDDI_VERSION must be defined as NTDDI_LONGHORN or later
#endif
#if !defined(NTDDI_VISTA) || defined(BUILD_OLDSDK)
typedef enum _TOKEN_ELEVATION_TYPE {
TokenElevationTypeDefault = 1,
TokenElevationTypeFull,
TokenElevationTypeLimited,
} TOKEN_ELEVATION_TYPE, *PTOKEN_ELEVATION_TYPE;
typedef struct _TOKEN_ELEVATION {
DWORD TokenIsElevated;
} TOKEN_ELEVATION, *PTOKEN_ELEVATION;
enum _TOKEN_INFORMATION_CLASS___VISTA {
TokenElevationType = (TokenOrigin+1),
TokenLinkedToken,
TokenElevation,
TokenHasRestrictions,
TokenAccessInformation,
TokenVirtualizationAllowed,
TokenVirtualizationEnabled,
TokenIntegrityLevel,
TokenUIAccess,
TokenMandatoryPolicy,
TokenLogonSid,
};
#endif
//////////////////////////////////////////////////////////////////
// if ASSERT was not defined already, let's define our own version,
// to use the CRT assert()
#ifndef ASSERT
# ifdef _DEBUG
# include <assert.h>
# define ASSERT(x) assert( x )
# define ASSERT_HERE assert( FALSE )
# else// _DEBUG
# define ASSERT(x)
# define ASSERT_HERE
# endif//_DEBUG
#endif//ASSERT
///////////////////////////////////////////////////////////////////
// a handy macro to get the number of characters (not bytes!)
// a string buffer can hold
#ifndef _tsizeof
# define _tsizeof( s ) (sizeof(s)/sizeof(s[0]))
#endif//_tsizeof
///////////////////////////////////////////////////////////////
// macros to handle the functions implemented in a DLL properly
#ifdef DLL_EXPORTS
# define DLL_API __declspec(dllexport)
#else
# ifndef NO_DLL_IMPORTS
# define DLL_API __declspec(dllimport)
# else
# define DLL_API
# endif
#endif
BOOL DLL_API
IsVista();
/*
Use IsVista() to determine whether the current process is running under Windows Vista or
(or a later version of Windows, whatever it will be)
Return Values:
If the function succeeds, and the current version of Windows is Vista or later,
the return value is TRUE.
If the function fails, or if the current version of Windows is older than Vista
(that is, if it is Windows XP, Windows 2000, Windows Server 2003, Windows 98, etc.)
the return value is FALSE.
*/
#ifndef WIN64
BOOL DLL_API
IsWow64();
/*
Use IsWow64() to determine whether the current 32-bit process is running under 64-bit Windows
(Vista or XP)
Return Values:
If the function succeeds, and the current version of Windows is x64,
the return value is TRUE.
If the function fails, or if the current version of Windows is 32-bit,
the return value is FALSE.
While this function is not Vista specific (it works under XP as well),
we include it here to be able to prevent execution of the 32-bit code under 64-bit Windows,
when required.
*/
#endif//WIN64
HRESULT DLL_API
GetElevationType( __out TOKEN_ELEVATION_TYPE * ptet );
/*
Use GetElevationType() to determine the elevation type of the current process.
Parameters:
ptet
[out] Pointer to a variable that receives the elevation type of the current process.
The possible values are:
TokenElevationTypeDefault - User is not using a "split" token.
This value indicates that either UAC is disabled, or the process is started
by a standard user (not a member of the Administrators group).
The following two values can be returned only if both the UAC is enabled and
the user is a member of the Administrator's group (that is, the user has a "split" token):
TokenElevationTypeFull - the process is running elevated.
TokenElevationTypeLimited - the process is not running elevated.
Return Values:
If the function succeeds, the return value is S_OK.
If the function fails, the return value is E_FAIL. To get extended error information,
call GetLastError().
*/
HRESULT DLL_API
IsElevated( __out_opt BOOL * pbElevated = NULL );
/*
Use IsElevated() to determine whether the current process is elevated or not.
Parameters:
pbElevated
[out] [optional] Pointer to a BOOL variable that, if non-NULL, receives the result.
The possible values are:
TRUE - the current process is elevated.
This value indicates that either UAC is enabled, and the process was elevated by
the administrator, or that UAC is disabled and the process was started by a user
who is a member of the Administrators group.
FALSE - the current process is not elevated (limited).
This value indicates that either UAC is enabled, and the process was started normally,
without the elevation, or that UAC is disabled and the process was started by a standard user.
Return Values
If the function succeeds, and the current process is elevated, the return value is S_OK.
If the function succeeds, and the current process is not elevated, the return value is S_FALSE.
If the function fails, the return value is E_FAIL. To get extended error information,
call GetLastError().
*/
BOOL DLL_API
RunElevated(
__in HWND hwnd,
__in LPCTSTR pszPath,
__in_opt LPCTSTR pszParameters = NULL,
__in_opt LPCTSTR pszDirectory = NULL );
/*
Use RunElevated() to start an elevated process. This function calls ShellExecEx() with the verb "runas"
to start the elevated process.
Parameters:
hwnd
[in] Window handle to any message boxes that the system might produce while executing this function.
pszPath
[in] Address of a null-terminated string that specifies the name of the executable file that
should be used to start the process.
pszParameters
[in] [optional] Address of a null-terminated string that contains the command-line parameters for the process.
If NULL, no parameters are passed to the process.
pszDirectory
[in] [optional] Address of a null-terminated string that specifies the name of the working directory.
If NULL, the current directory is used as the working directory. .
Return Values
If the function succeeds, the return value is TRUE.
If the function fails, the return value is FALSE. To get extended error information,
call GetLastError().
NOTE: This function will start a process elevated no matter which attribute (asInvoker,
highestAvailable, or requireAdministrator) is specified in its manifest, and even if
there is no such attribute at all.
*/
#ifndef DONTWANT_RunNonElevated
#ifdef NO_DLL_IMPORTS
# error RunNonElevated must be used in a DLL project!
#endif//NO_DLL_IMPORTS
BOOL DLL_API
RunNonElevated(
__in HWND hwnd,
__in LPCTSTR pszPath,
__in_opt LPCTSTR pszParameters = NULL,
__in_opt LPCTSTR pszDirectory = NULL );
/*
Use RunNonElevated() to start a non-elevated process. If the current process is not elevated,
it calls ShellExecuteEx() to start the new process. If the current process is elevated,
it injects itself into the (non-elevated) shell process, and starts a non-elevated process from there.
Parameters:
hwnd
[in] Window handle to any message boxes that the system might produce while executing this function.
pszPath
[in] Address of a null-terminated string that specifies the executable file that
should be used to start the process.
pszParameters
[in] [optional] Address of a null-terminated string that contains the command-line parameters for
the process. If NULL, no parameters are passed to the process.
pszDirectory
[in] [optional] Address of a null-terminated string that specifies the name of the working directory.
If NULL, the current directory is used as the working directory. .
Return Values
If the function succeeds, the return value is TRUE.
If the function fails, the return value is FALSE. To get extended error information,
call GetLastError().
NOTE: For this function to work, the application must be marked with the asInvoker or
highestAvailable attributes in its manifest. If the executable to be started is marked
as requireAdministrator, it will be started elevated!
*/
#endif //DONTWANT_RunNonElevated
//////////////////////////////////////////////////////////
// MyShellExec is just a wrapper around a call to ShellExecuteEx,
// to be able to specify the verb easily.
BOOL DLL_API
MyShellExec( HWND hwnd,
LPCTSTR pszVerb,
LPCTSTR pszPath,
LPCTSTR pszParameters = NULL,
int nShow = SW_SHOWNORMAL);
#ifdef IMPLEMENT_VISTA_TOOLS
//////////////////////////////////////////////////////////
// MyShellExec is just a wrapper around a call to ShellExecuteEx,
// to be able to specify the verb easily.
/*
BOOL
MyShellExec( HWND hwnd,
LPCTSTR pszVerb,
LPCTSTR pszPath,
LPCTSTR pszParameters, // = NULL,
int nShow)
{
SHELLEXECUTEINFO shex;
memset( &shex, 0, sizeof( shex) );
shex.cbSize = sizeof( SHELLEXECUTEINFO );
shex.fMask = 0;
shex.hwnd = hwnd;
shex.lpVerb = pszVerb;
shex.lpFile = pszPath;
shex.lpParameters = pszParameters;
shex.lpDirectory = NULL;
shex.nShow = nShow;
return ::ShellExecuteEx( &shex );
}
*/
BOOL IsVista()
{
OSVERSIONINFOEX osver;
DWORDLONG dwlConditionMask = 0;
int op = VER_GREATER_EQUAL;
ZeroMemory(&osver, sizeof(OSVERSIONINFOEX));
osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
osver.dwMajorVersion = 6;
osver.dwMinorVersion = 0;
osver.dwPlatformId = VER_PLATFORM_WIN32_NT;
VER_SET_CONDITION(dwlConditionMask, VER_MAJORVERSION, op);
VER_SET_CONDITION(dwlConditionMask, VER_MINORVERSION, op);
VER_SET_CONDITION(dwlConditionMask, VER_PLATFORMID, VER_EQUAL);
return VerifyVersionInfo(&osver, VER_MAJORVERSION | VER_MINORVERSION | VER_PLATFORMID, dwlConditionMask);
}
#ifndef WIN64 // we need this when compiling 32-bit code only
typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE hProcess,PBOOL Wow64Process);
LPFN_ISWOW64PROCESS fnIsWow64Process =
(LPFN_ISWOW64PROCESS)::GetProcAddress( ::GetModuleHandle(_T("kernel32")),"IsWow64Process");
BOOL
IsWow64()
{
BOOL bIsWow64 = FALSE;
if (NULL != fnIsWow64Process)
{
if ( !fnIsWow64Process( ::GetCurrentProcess(),&bIsWow64) )
{
ASSERT_HERE;
}
}
return bIsWow64;
}
#endif//WIN64
HRESULT
GetElevationType( __out TOKEN_ELEVATION_TYPE * ptet )
{
ASSERT( IsVista() );
ASSERT( ptet );
HRESULT hResult = E_FAIL; // assume an error occured
HANDLE hToken = NULL;
if ( !::OpenProcessToken(
::GetCurrentProcess(),
TOKEN_QUERY,
&hToken ) )
{
ASSERT_HERE;
return hResult;
}
DWORD dwReturnLength = 0;
if ( !::GetTokenInformation(
hToken,
(_TOKEN_INFORMATION_CLASS)TokenElevationType,
ptet,
sizeof( *ptet ),
&dwReturnLength ) )
{
ASSERT_HERE;
}
else
{
ASSERT( dwReturnLength == sizeof( *ptet ) );
hResult = S_OK;
}
::CloseHandle( hToken );
return hResult;
}
HRESULT
IsElevated( __out_opt BOOL * pbElevated ) //= NULL )
{
ASSERT( IsVista() );
HRESULT hResult = E_FAIL; // assume an error occured
HANDLE hToken = NULL;
if ( !::OpenProcessToken(
::GetCurrentProcess(),
TOKEN_QUERY,
&hToken ) )
{
ASSERT_HERE;
return hResult;
}
TOKEN_ELEVATION te = { 0 };
DWORD dwReturnLength = 0;
if ( !::GetTokenInformation(
hToken,
(_TOKEN_INFORMATION_CLASS)TokenElevation,
&te,
sizeof( te ),
&dwReturnLength ) )
{
ASSERT_HERE;
}
else
{
ASSERT( dwReturnLength == sizeof( te ) );
hResult = te.TokenIsElevated ? S_OK : S_FALSE;
if ( pbElevated)
*pbElevated = (te.TokenIsElevated != 0);
}
::CloseHandle( hToken );
return hResult;
}
////////////////////////////////
// RunElevated simply calls ShellExecuteEx with the verb "runas" to start the elevated process.
// I wish there was a just as easy way to start a non-elevated process, as well.
/*
BOOL
RunElevated(
__in HWND hwnd,
__in LPCTSTR pszPath,
__in_opt LPCTSTR pszParameters, // = NULL,
__in_opt LPCTSTR pszDirectory ) // = NULL );
{
return MyShellExec( hwnd, _T("runas"), pszPath, pszParameters );
}
*/
#ifndef DONTWANT_RunNonElevated
///////////////////////////////////////
// RunNonElevated() implementation
///////////////////////////////////////////////////
// The shared data, to be able to share
// data between ours and the shell proceses
#pragma section( "ve_shared", read, write, shared )
__declspec(allocate("ve_shared"))
HHOOK hHook = NULL;
__declspec(allocate("ve_shared"))
UINT uVistaElevatorMsg = 0;
__declspec(allocate("ve_shared"))
BOOL bSuccess = FALSE;
__declspec(allocate("ve_shared"))
TCHAR szVE_Path[ MAX_PATH ] = _T("");
__declspec(allocate("ve_shared"))
TCHAR szVE_Parameters[ MAX_PATH ] = _T("");
__declspec(allocate("ve_shared"))
TCHAR szVE_Directory[ MAX_PATH ] = _T("");
//////////////////////////////////e
// the hook callback procedure, it is called in the context of th shell proces
LRESULT CALLBACK
VistaEelevator_HookProc_MsgRet( int code, WPARAM wParam, LPARAM lParam )
{
if ( code >= 0 && lParam )
{
CWPRETSTRUCT * pwrs = (CWPRETSTRUCT *)lParam;
if (pwrs->message == uVistaElevatorMsg )
{
bSuccess = ::MyShellExec(
pwrs->hwnd,
NULL,
szVE_Path,
szVE_Parameters,
szVE_Directory );
}
}
return ::CallNextHookEx( hHook, code, wParam, lParam );
}
BOOL
RunNonElevated(
__in HWND hwnd,
__in LPCTSTR pszPath,
__in_opt LPCTSTR pszParameters, // = NULL,
__in_opt LPCTSTR pszDirectory ) // = NULL );
{
ASSERT( pszPath && *pszPath ); // other args are optional
ASSERT( IsVista() );
ASSERT( pszPath );
if ( S_FALSE == IsElevated() )
{
// if the current process is not elevated, we can use ShellExecuteAs directly!
return MyShellExec( hwnd,
NULL,
pszPath,
pszParameters,
pszDirectory );
}
#ifndef WIN64
// If 32-bit code is executing under x64 version of Windows, it will not work, because
// the shell is a 64-bit process, and to hook it successfully this code needs to be 64-bit as well
if ( IsWow64() )
{
ASSERT_HERE;
return FALSE;
}
#endif//WIN64
//////////////////////////////////////////////
//
// How this code works:
//
// To start a non-elevated process, we need to inject our code into a non-elevated
// process already running on the target computer. Since Windows shell is non-elevated,
// and we can safely assume it to always run, (when was the last time you saw Windows
// running without its shell?), we will try to inject our code into the shell process.
//
// To inject the code, we will install a global hook, and send a message to
// a window created by the shell. This will cause our hook callback procedure to be executed
// in the context of the shell proces.
//
// Because this trick uses a global hook, the hook procedure must be in a DLL.
//
/////////////////////
// First, register a private message, to communicate with the (hooked) shell process
if ( !uVistaElevatorMsg )
uVistaElevatorMsg = ::RegisterWindowMessage( _T("VistaElevatorMsg") );
//////////////////////////////////////
// Find the shell window (the desktop)
HWND hwndShell = ::FindWindow( _T("Progman"), NULL);
if ( !hwndShell )
{
ASSERT_HERE;
return FALSE;
}
/////////////////////////////////////////
// Install a global hook, to inject our code into the shell proces
HMODULE hModule = NULL; // we need to know hModule of the DLL to install a global hook
if ( !::GetModuleHandleEx(
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
(LPCTSTR)VistaEelevator_HookProc_MsgRet,
&hModule ) )
{
ASSERT_HERE;
return FALSE;
}
ASSERT( hModule );
hHook = ::SetWindowsHookEx( WH_CALLWNDPROCRET, // hook called after SendMessage() !!!
(HOOKPROC)VistaEelevator_HookProc_MsgRet, hModule, 0);
if ( !hHook )
{
ASSERT_HERE;
return FALSE;
}
//////////////////////////////////
// Prepare the parameters for launching the non-elevated process
// from the hook callback procedure (they are placed into the shared data section)
if ( FAILED( StringCchCopy(
szVE_Path,
_tsizeof(szVE_Path),
pszPath ) ) )
{
ASSERT_HERE;
return FALSE;
}
if ( FAILED( StringCchCopy(
szVE_Parameters,
_tsizeof(szVE_Parameters),
pszParameters ? pszParameters : _T("") ) ) )
{
ASSERT_HERE;
return FALSE;
}
if ( FAILED( StringCchCopy(
szVE_Directory,
_tsizeof(szVE_Directory),
pszDirectory ? pszDirectory : _T("") ) ) )
{
ASSERT_HERE;
return FALSE;
}
/////////////////////////////////////////
// Activate our hook callback procedure:
bSuccess = FALSE; // assume failure
::SendMessage( hwndShell, uVistaElevatorMsg, 0, 0 );
////////////////////////////////////////////////////////
// At this point our hook procedure has been executed!
/////////////////////////////////////
// The hook is no longer needed, remove it:
::UnhookWindowsHookEx( hHook );
hHook = NULL;
//////////////////////
// All done!
return bSuccess;
}
#endif //DONTWANT_RunNonElevated
#endif// IMPLEMENT_VISTA_TOOLS
+83
View File
@@ -0,0 +1,83 @@
/*
* apih
*
* This file is a part of NSIS.
*
* Copyright (C) 1999-2013 Nullsoft and Contributors
*
* 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.
*/
#ifndef _NSIS_EXEHEAD_API_H_
#define _NSIS_EXEHEAD_API_H_
// Starting with NSIS 2.42, you can check the version of the plugin API in exec_flags->plugin_api_version
// The format is 0xXXXXYYYY where X is the major version and Y is the minor version (MAKELONG(y,x))
// When doing version checks, always remember to use >=, ex: if (pX->exec_flags->plugin_api_version >= NSISPIAPIVER_1_0) {}
#define NSISPIAPIVER_1_0 0x00010000
#define NSISPIAPIVER_CURR NSISPIAPIVER_1_0
// NSIS Plug-In Callback Messages
enum NSPIM
{
NSPIM_UNLOAD, // This is the last message a plugin gets, do final cleanup
NSPIM_GUIUNLOAD, // Called after .onGUIEnd
};
// Prototype for callbacks registered with extra_parameters->RegisterPluginCallback()
// Return NULL for unknown messages
// Should always be __cdecl for future expansion possibilities
typedef UINT_PTR (*NSISPLUGINCALLBACK)(enum NSPIM);
// extra_parameters data structures containing other interesting stuff
// but the stack, variables and HWND passed on to plug-ins.
typedef struct
{
int autoclose;
int all_user_var;
int exec_error;
int abort;
int exec_reboot; // NSIS_SUPPORT_REBOOT
int reboot_called; // NSIS_SUPPORT_REBOOT
int XXX_cur_insttype; // depreacted
int plugin_api_version; // see NSISPIAPIVER_CURR
// used to be XXX_insttype_changed
int silent; // NSIS_CONFIG_SILENT_SUPPORT
int instdir_error;
int rtl;
int errlvl;
int alter_reg_view;
int status_update;
} exec_flags_t;
#ifndef NSISCALL
# define NSISCALL __stdcall
#endif
typedef struct {
exec_flags_t *exec_flags;
int (NSISCALL *ExecuteCodeSegment)(int, HWND);
void (NSISCALL *validate_filename)(TCHAR *);
int (NSISCALL *RegisterPluginCallback)(HMODULE, NSISPLUGINCALLBACK); // returns 0 on success, 1 if already registered and < 0 on errors
} extra_parameters;
// Definitions for page showing plug-ins
// See Ui.c to understand better how they're used
// sent to the outer window to tell it to go to the next inner window
#define WM_NOTIFY_OUTER_NEXT (WM_USER+0x8)
// custom pages should send this message to let NSIS know they're ready
#define WM_NOTIFY_CUSTOM_READY (WM_USER+0xd)
// sent as wParam with WM_NOTIFY_OUTER_NEXT when user cancels - heed its warning
#define NOTIFY_BYE_BYE 'x'
#endif /* _PLUGIN_H_ */
+229
View File
@@ -0,0 +1,229 @@
/*
* nsis_tchar.h
*
* This file is a part of NSIS.
*
* Copyright (C) 1999-2013 Nullsoft and Contributors
*
* This software is provided 'as-is', without any express or implied
* warranty.
*
* For Unicode support by Jim Park -- 08/30/2007
*/
// Jim Park: Only those we use are listed here.
#pragma once
#ifdef _UNICODE
#ifndef _T
#define __T(x) L ## x
#define _T(x) __T(x)
#define _TEXT(x) __T(x)
#endif
#ifndef _TCHAR_DEFINED
#define _TCHAR_DEFINED
#if !defined(_NATIVE_WCHAR_T_DEFINED) && !defined(_WCHAR_T_DEFINED)
typedef unsigned short TCHAR;
#else
typedef wchar_t TCHAR;
#endif
#endif
// program
#define _tenviron _wenviron
#define __targv __wargv
// printfs
#define _ftprintf fwprintf
#define _sntprintf _snwprintf
#if (defined(_MSC_VER) && (_MSC_VER<=1310)) || defined(__MINGW32__)
# define _stprintf swprintf
#else
# define _stprintf _swprintf
#endif
#define _tprintf wprintf
#define _vftprintf vfwprintf
#define _vsntprintf _vsnwprintf
#if defined(_MSC_VER) && (_MSC_VER<=1310)
# define _vstprintf vswprintf
#else
# define _vstprintf _vswprintf
#endif
// scanfs
#define _tscanf wscanf
#define _stscanf swscanf
// string manipulations
#define _tcscat wcscat
#define _tcschr wcschr
#define _tcsclen wcslen
#define _tcscpy wcscpy
#define _tcsdup _wcsdup
#define _tcslen wcslen
#define _tcsnccpy wcsncpy
#define _tcsncpy wcsncpy
#define _tcsrchr wcsrchr
#define _tcsstr wcsstr
#define _tcstok wcstok
// string comparisons
#define _tcscmp wcscmp
#define _tcsicmp _wcsicmp
#define _tcsncicmp _wcsnicmp
#define _tcsncmp wcsncmp
#define _tcsnicmp _wcsnicmp
// upper / lower
#define _tcslwr _wcslwr
#define _tcsupr _wcsupr
#define _totlower towlower
#define _totupper towupper
// conversions to numbers
#define _tcstoi64 _wcstoi64
#define _tcstol wcstol
#define _tcstoul wcstoul
#define _tstof _wtof
#define _tstoi _wtoi
#define _tstoi64 _wtoi64
#define _ttoi _wtoi
#define _ttoi64 _wtoi64
#define _ttol _wtol
// conversion from numbers to strings
#define _itot _itow
#define _ltot _ltow
#define _i64tot _i64tow
#define _ui64tot _ui64tow
// file manipulations
#define _tfopen _wfopen
#define _topen _wopen
#define _tremove _wremove
#define _tunlink _wunlink
// reading and writing to i/o
#define _fgettc fgetwc
#define _fgetts fgetws
#define _fputts fputws
#define _gettchar getwchar
// directory
#define _tchdir _wchdir
// environment
#define _tgetenv _wgetenv
#define _tsystem _wsystem
// time
#define _tcsftime wcsftime
#else // ANSI
#ifndef _T
#define _T(x) x
#define _TEXT(x) x
#endif
#ifndef _TCHAR_DEFINED
#define _TCHAR_DEFINED
typedef char TCHAR;
#endif
// program
#define _tenviron environ
#define __targv __argv
// printfs
#define _ftprintf fprintf
#define _sntprintf _snprintf
#define _stprintf sprintf
#define _tprintf printf
#define _vftprintf vfprintf
#define _vsntprintf _vsnprintf
#define _vstprintf vsprintf
// scanfs
#define _tscanf scanf
#define _stscanf sscanf
// string manipulations
#define _tcscat strcat
#define _tcschr strchr
#define _tcsclen strlen
#define _tcscnlen strnlen
#define _tcscpy strcpy
#define _tcsdup _strdup
#define _tcslen strlen
#define _tcsnccpy strncpy
#define _tcsrchr strrchr
#define _tcsstr strstr
#define _tcstok strtok
// string comparisons
#define _tcscmp strcmp
#define _tcsicmp _stricmp
#define _tcsncmp strncmp
#define _tcsncicmp _strnicmp
#define _tcsnicmp _strnicmp
// upper / lower
#define _tcslwr _strlwr
#define _tcsupr _strupr
#define _totupper toupper
#define _totlower tolower
// conversions to numbers
#define _tcstol strtol
#define _tcstoul strtoul
#define _tstof atof
#define _tstoi atoi
#define _tstoi64 _atoi64
#define _tstoi64 _atoi64
#define _ttoi atoi
#define _ttoi64 _atoi64
#define _ttol atol
// conversion from numbers to strings
#define _i64tot _i64toa
#define _itot _itoa
#define _ltot _ltoa
#define _ui64tot _ui64toa
// file manipulations
#define _tfopen fopen
#define _topen _open
#define _tremove remove
#define _tunlink _unlink
// reading and writing to i/o
#define _fgettc fgetc
#define _fgetts fgets
#define _fputts fputs
#define _gettchar getchar
// directory
#define _tchdir _chdir
// environment
#define _tgetenv getenv
#define _tsystem system
// time
#define _tcsftime strftime
#endif
// is functions (the same in Unicode / ANSI)
#define _istgraph isgraph
#define _istascii __isascii
#define __TFILE__ _T(__FILE__)
#define __TDATE__ _T(__DATE__)
#define __TTIME__ _T(__TIME__)
+296
View File
@@ -0,0 +1,296 @@
//#include "StdAfx.h"
#include <windows.h>
#include <commctrl.h>
#include "pluginapi.h"
#ifdef _countof
#define COUNTOF _countof
#else
#define COUNTOF(a) (sizeof(a)/sizeof(a[0]))
#endif
unsigned int g_stringsize;
stack_t **g_stacktop;
TCHAR *g_variables;
// utility functions (not required but often useful)
int NSISCALL popstring(TCHAR *str)
{
stack_t *th;
if (!g_stacktop || !*g_stacktop) return 1;
th=(*g_stacktop);
if (str) lstrcpy(str,th->text);
*g_stacktop = th->next;
GlobalFree((HGLOBAL)th);
return 0;
}
int NSISCALL popstringn(TCHAR *str, int maxlen)
{
stack_t *th;
if (!g_stacktop || !*g_stacktop) return 1;
th=(*g_stacktop);
if (str) lstrcpyn(str,th->text,maxlen?maxlen:g_stringsize);
*g_stacktop = th->next;
GlobalFree((HGLOBAL)th);
return 0;
}
void NSISCALL pushstring(const TCHAR *str)
{
stack_t *th;
if (!g_stacktop) return;
th=(stack_t*)GlobalAlloc(GPTR,(sizeof(stack_t)+(g_stringsize)*sizeof(TCHAR)));
lstrcpyn(th->text,str,g_stringsize);
th->next=*g_stacktop;
*g_stacktop=th;
}
TCHAR* NSISCALL getuservariable(const int varnum)
{
if (varnum < 0 || varnum >= __INST_LAST) return NULL;
return g_variables+varnum*g_stringsize;
}
void NSISCALL setuservariable(const int varnum, const TCHAR *var)
{
if (var != NULL && varnum >= 0 && varnum < __INST_LAST)
lstrcpy(g_variables + varnum*g_stringsize, var);
}
#ifdef _UNICODE
int NSISCALL PopStringA(char* ansiStr)
{
wchar_t* wideStr = (wchar_t*) GlobalAlloc(GPTR, g_stringsize*sizeof(wchar_t));
int rval = popstring(wideStr);
WideCharToMultiByte(CP_ACP, 0, wideStr, -1, ansiStr, g_stringsize, NULL, NULL);
GlobalFree((HGLOBAL)wideStr);
return rval;
}
int NSISCALL PopStringNA(char* ansiStr, int maxlen)
{
int realLen = maxlen ? maxlen : g_stringsize;
wchar_t* wideStr = (wchar_t*) GlobalAlloc(GPTR, realLen*sizeof(wchar_t));
int rval = popstringn(wideStr, realLen);
WideCharToMultiByte(CP_ACP, 0, wideStr, -1, ansiStr, realLen, NULL, NULL);
GlobalFree((HGLOBAL)wideStr);
return rval;
}
void NSISCALL PushStringA(const char* ansiStr)
{
wchar_t* wideStr = (wchar_t*) GlobalAlloc(GPTR, g_stringsize*sizeof(wchar_t));
MultiByteToWideChar(CP_ACP, 0, ansiStr, -1, wideStr, g_stringsize);
pushstring(wideStr);
GlobalFree((HGLOBAL)wideStr);
return;
}
void NSISCALL GetUserVariableW(const int varnum, wchar_t* wideStr)
{
lstrcpyW(wideStr, getuservariable(varnum));
}
void NSISCALL GetUserVariableA(const int varnum, char* ansiStr)
{
wchar_t* wideStr = getuservariable(varnum);
WideCharToMultiByte(CP_ACP, 0, wideStr, -1, ansiStr, g_stringsize, NULL, NULL);
}
void NSISCALL SetUserVariableA(const int varnum, const char* ansiStr)
{
if (ansiStr != NULL && varnum >= 0 && varnum < __INST_LAST)
{
wchar_t* wideStr = g_variables + varnum * g_stringsize;
MultiByteToWideChar(CP_ACP, 0, ansiStr, -1, wideStr, g_stringsize);
}
}
#else
// ANSI defs
int NSISCALL PopStringW(wchar_t* wideStr)
{
char* ansiStr = (char*) GlobalAlloc(GPTR, g_stringsize);
int rval = popstring(ansiStr);
MultiByteToWideChar(CP_ACP, 0, ansiStr, -1, wideStr, g_stringsize);
GlobalFree((HGLOBAL)ansiStr);
return rval;
}
int NSISCALL PopStringNW(wchar_t* wideStr, int maxlen)
{
int realLen = maxlen ? maxlen : g_stringsize;
char* ansiStr = (char*) GlobalAlloc(GPTR, realLen);
int rval = popstringn(ansiStr, realLen);
MultiByteToWideChar(CP_ACP, 0, ansiStr, -1, wideStr, realLen);
GlobalFree((HGLOBAL)ansiStr);
return rval;
}
void NSISCALL PushStringW(wchar_t* wideStr)
{
char* ansiStr = (char*) GlobalAlloc(GPTR, g_stringsize);
WideCharToMultiByte(CP_ACP, 0, wideStr, -1, ansiStr, g_stringsize, NULL, NULL);
pushstring(ansiStr);
GlobalFree((HGLOBAL)ansiStr);
}
void NSISCALL GetUserVariableW(const int varnum, wchar_t* wideStr)
{
char* ansiStr = getuservariable(varnum);
MultiByteToWideChar(CP_ACP, 0, ansiStr, -1, wideStr, g_stringsize);
}
void NSISCALL GetUserVariableA(const int varnum, char* ansiStr)
{
lstrcpyA(ansiStr, getuservariable(varnum));
}
void NSISCALL SetUserVariableW(const int varnum, const wchar_t* wideStr)
{
if (wideStr != NULL && varnum >= 0 && varnum < __INST_LAST)
{
char* ansiStr = g_variables + varnum * g_stringsize;
WideCharToMultiByte(CP_ACP, 0, wideStr, -1, ansiStr, g_stringsize, NULL, NULL);
}
}
#endif
// playing with integers
INT_PTR NSISCALL nsishelper_str_to_ptr(const TCHAR *s)
{
INT_PTR v=0;
if (*s == _T('0') && (s[1] == _T('x') || s[1] == _T('X')))
{
s++;
for (;;)
{
int c=*(++s);
if (c >= _T('0') && c <= _T('9')) c-=_T('0');
else if (c >= _T('a') && c <= _T('f')) c-=_T('a')-10;
else if (c >= _T('A') && c <= _T('F')) c-=_T('A')-10;
else break;
v<<=4;
v+=c;
}
}
else if (*s == _T('0') && s[1] <= _T('7') && s[1] >= _T('0'))
{
for (;;)
{
int c=*(++s);
if (c >= _T('0') && c <= _T('7')) c-=_T('0');
else break;
v<<=3;
v+=c;
}
}
else
{
int sign=0;
if (*s == _T('-')) sign++; else s--;
for (;;)
{
int c=*(++s) - _T('0');
if (c < 0 || c > 9) break;
v*=10;
v+=c;
}
if (sign) v = -v;
}
return v;
}
unsigned int NSISCALL myatou(const TCHAR *s)
{
unsigned int v=0;
for (;;)
{
unsigned int c=*s++;
if (c >= _T('0') && c <= _T('9')) c-=_T('0');
else break;
v*=10;
v+=c;
}
return v;
}
int NSISCALL myatoi_or(const TCHAR *s)
{
int v=0;
if (*s == _T('0') && (s[1] == _T('x') || s[1] == _T('X')))
{
s++;
for (;;)
{
int c=*(++s);
if (c >= _T('0') && c <= _T('9')) c-=_T('0');
else if (c >= _T('a') && c <= _T('f')) c-=_T('a')-10;
else if (c >= _T('A') && c <= _T('F')) c-=_T('A')-10;
else break;
v<<=4;
v+=c;
}
}
else if (*s == _T('0') && s[1] <= _T('7') && s[1] >= _T('0'))
{
for (;;)
{
int c=*(++s);
if (c >= _T('0') && c <= _T('7')) c-=_T('0');
else break;
v<<=3;
v+=c;
}
}
else
{
int sign=0;
if (*s == _T('-')) sign++; else s--;
for (;;)
{
int c=*(++s) - _T('0');
if (c < 0 || c > 9) break;
v*=10;
v+=c;
}
if (sign) v = -v;
}
// Support for simple ORed expressions
if (*s == _T('|'))
{
v |= myatoi_or(s+1);
}
return v;
}
INT_PTR NSISCALL popintptr()
{
TCHAR buf[128];
if (popstringn(buf,COUNTOF(buf)))
return 0;
return nsishelper_str_to_ptr(buf);
}
int NSISCALL popint_or()
{
TCHAR buf[128];
if (popstringn(buf,COUNTOF(buf)))
return 0;
return myatoi_or(buf);
}
void NSISCALL pushintptr(INT_PTR value)
{
TCHAR buffer[30];
wsprintf(buffer, sizeof(void*) > 4 ? _T("%Id") : _T("%d"), value);
pushstring(buffer);
}
+115
View File
@@ -0,0 +1,115 @@
#ifndef ___NSIS_PLUGIN__H___
#define ___NSIS_PLUGIN__H___
#ifdef __cplusplus
extern "C" {
#endif
#include "api.h"
#ifdef _UNICODE
#ifndef _T
#define __T(x) L ## x
#define _T(x) __T(x)
#define _TEXT(x) __T(x)
#endif
#else
#ifndef _T
#define _T(x) x
#define _TEXT(x) x
#endif
#endif
#ifndef NSISCALL
# define NSISCALL __stdcall
#endif
#define EXDLL_INIT() { \
g_stringsize=string_size; \
g_stacktop=stacktop; \
g_variables=variables; }
typedef struct _stack_t {
struct _stack_t *next;
TCHAR text[1]; // this should be the length of string_size
} stack_t;
enum
{
INST_0, // $0
INST_1, // $1
INST_2, // $2
INST_3, // $3
INST_4, // $4
INST_5, // $5
INST_6, // $6
INST_7, // $7
INST_8, // $8
INST_9, // $9
INST_R0, // $R0
INST_R1, // $R1
INST_R2, // $R2
INST_R3, // $R3
INST_R4, // $R4
INST_R5, // $R5
INST_R6, // $R6
INST_R7, // $R7
INST_R8, // $R8
INST_R9, // $R9
INST_CMDLINE, // $CMDLINE
INST_INSTDIR, // $INSTDIR
INST_OUTDIR, // $OUTDIR
INST_EXEDIR, // $EXEDIR
INST_LANG, // $LANGUAGE
__INST_LAST
};
extern unsigned int g_stringsize;
extern stack_t **g_stacktop;
extern TCHAR *g_variables;
void NSISCALL pushstring(const TCHAR *str);
void NSISCALL pushintptr(INT_PTR value);
#define pushint(v) pushintptr((INT_PTR)(v))
int NSISCALL popstring(TCHAR *str); // 0 on success, 1 on empty stack
int NSISCALL popstringn(TCHAR *str, int maxlen); // with length limit, pass 0 for g_stringsize
INT_PTR NSISCALL popintptr();
#define popint() ( (int) popintptr() )
int NSISCALL popint_or(); // with support for or'ing (2|4|8)
INT_PTR NSISCALL nsishelper_str_to_ptr(const TCHAR *s);
#define myatoi(s) ( (int) nsishelper_str_to_ptr(s) ) // converts a string to an integer
unsigned int NSISCALL myatou(const TCHAR *s); // converts a string to an unsigned integer, decimal only
int NSISCALL myatoi_or(const TCHAR *s); // with support for or'ing (2|4|8)
TCHAR* NSISCALL getuservariable(const int varnum);
void NSISCALL setuservariable(const int varnum, const TCHAR *var);
#ifdef _UNICODE
#define PopStringW(x) popstring(x)
#define PushStringW(x) pushstring(x)
#define SetUserVariableW(x,y) setuservariable(x,y)
int NSISCALL PopStringA(char* ansiStr);
void NSISCALL PushStringA(const char* ansiStr);
void NSISCALL GetUserVariableW(const int varnum, wchar_t* wideStr);
void NSISCALL GetUserVariableA(const int varnum, char* ansiStr);
void NSISCALL SetUserVariableA(const int varnum, const char* ansiStr);
#else
// ANSI defs
#define PopStringA(x) popstring(x)
#define PushStringA(x) pushstring(x)
#define SetUserVariableA(x,y) setuservariable(x,y)
int NSISCALL PopStringW(wchar_t* wideStr);
void NSISCALL PushStringW(wchar_t* wideStr);
void NSISCALL GetUserVariableW(const int varnum, wchar_t* wideStr);
void NSISCALL GetUserVariableA(const int varnum, char* ansiStr);
void NSISCALL SetUserVariableW(const int varnum, const wchar_t* wideStr);
#endif
#ifdef __cplusplus
}
#endif
#endif//!___NSIS_PLUGIN__H___