Added PC folder with launcher sources.

master
Vinay Sajip 8 years ago
parent 8ee4035a29
commit b454a65a45
  1. 384
      PC/CLISimpleLauncher.vcproj
  2. 371
      PC/GUISimpleLauncher.vcproj
  3. 32
      PC/ReadMe.txt
  4. 36
      PC/SimpleLauncher.sln
  5. 468
      PC/launcher.c
  6. BIN
      PC/launcher.ico
  7. 4
      PC/launcher.rc

@ -0,0 +1,384 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="CLISimpleLauncher"
ProjectGUID="{A0AB4387-243A-48F7-881D-DE138DDE68BA}"
RootNamespace="SimpleLauncher"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="0"
StructMemberAlignment="0"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
GenerateMapFile="true"
MapFileName="$(OutDir)\$(ProjectName).map"
MapExports="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
GenerateMapFile="true"
MapFileName="$(OutDir)\$(ProjectName).map"
MapExports="true"
SubSystem="1"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="1"
EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="2"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="dist\t32.exe"
LinkIncremental="1"
GenerateDebugInformation="true"
GenerateMapFile="true"
MapFileName="$(OutDir)\$(ProjectName).map"
MapExports="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="1"
EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="2"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="dist\t64.exe"
LinkIncremental="1"
GenerateDebugInformation="true"
GenerateMapFile="true"
MapFileName="$(OutDir)\$(ProjectName).map"
MapExports="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\launcher.c"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\resource.h"
>
</File>
<File
RelativePath=".\stdafx.h"
>
</File>
<File
RelativePath=".\targetver.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
<File
RelativePath=".\launcher.ico"
>
</File>
<File
RelativePath=".\launcher.rc"
>
</File>
</Filter>
<File
RelativePath=".\ReadMe.txt"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

@ -0,0 +1,371 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="GUISimpleLauncher"
ProjectGUID="{6295B87B-6312-4D7D-BCE9-A3626FD25417}"
RootNamespace="GUISimpleLauncher"
Keyword="Win32Proj"
TargetFrameworkVersion="196613"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
GenerateMapFile="true"
MapFileName="$(OutDir)\$(ProjectName).map"
MapExports="true"
SubSystem="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
GenerateDebugInformation="true"
GenerateMapFile="true"
MapFileName="$(OutDir)\$(ProjectName).map"
MapExports="true"
SubSystem="2"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="1"
EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="2"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="dist\w32.exe"
LinkIncremental="1"
GenerateDebugInformation="true"
GenerateMapFile="true"
MapFileName="$(OutDir)\$(ProjectName).map"
MapExports="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="1"
EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="2"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="dist\w64.exe"
LinkIncremental="1"
GenerateDebugInformation="true"
GenerateMapFile="true"
MapFileName="$(OutDir)\$(ProjectName).map"
MapExports="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\launcher.c"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
<File
RelativePath=".\launcher.ico"
>
</File>
<File
RelativePath=".\launcher.rc"
>
</File>
</Filter>
<File
RelativePath=".\ReadMe.txt"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

@ -0,0 +1,32 @@
This is a simple launcher for Python files, which is functionally equivalent to
the launchers in setuptools but not based on setuptools code. There are two
versions of the launcher - console and GUI - built from the same source code.
The launcher has been written as part of the pythonv branch, and is intended
to facilitate location of the correct Python executable for a script in an
environment where there may be multiple versions of Python deployed.
The launcher is intended to facilitate script execution under Windows where a
PEP 397-compatible launcher is not available. The idea is that each Python
script has a copy of the launcher (symlinks not being generally available
under Windows). For scripts to work with the launcher, they have to have a name
ending in -script.py (for a console script) or -script.pyw (for a GUI script).
The deployment system (e.g. packaging) will ensure that for foo-script.py, a
console launcher opy named foo.exe is placed in the same directory; for
bar-script.pyw, a GUI launcher copy named bar.exe is placed in the same
directory.
Assuming that the relevant directories are on the path, the scripts can be
invoked using just "foo" or "bar". The foo.exe or bar.exe executable then
runs: it looks for a script with the appropriate suffix ("-script.py" or
"-script.pyw") in the same directory, and if found, opens that script to read a
shebang line indicating which Python executable to use for the script. That
executable, if found, is launched with the script and other arguments passed:
foo a b c -> c:\path\to\python.exe c:\other\path\to\foo-script.py a b c
bar d e f -> c:\path\to\pythonw.exe c:\other\path\to\bar-script.pyw d e f
Note: More recently, the launchers have been updated to find their script in an
archive appended to the executable, rather than a separate file. (This variant
is enabled when APPENDED_ARCHIVE is #defined). This allows the launchers to be
used to e.g. run .pyz archives as native Windows executables.

@ -0,0 +1,36 @@

Microsoft Visual Studio Solution File, Format Version 10.00
# Visual C++ Express 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CLISimpleLauncher", "CLISimpleLauncher.vcproj", "{A0AB4387-243A-48F7-881D-DE138DDE68BA}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GUISimpleLauncher", "GUISimpleLauncher.vcproj", "{6295B87B-6312-4D7D-BCE9-A3626FD25417}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|x64 = Debug|x64
Release|Win32 = Release|Win32
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A0AB4387-243A-48F7-881D-DE138DDE68BA}.Debug|Win32.ActiveCfg = Debug|Win32
{A0AB4387-243A-48F7-881D-DE138DDE68BA}.Debug|Win32.Build.0 = Debug|Win32
{A0AB4387-243A-48F7-881D-DE138DDE68BA}.Debug|x64.ActiveCfg = Debug|x64
{A0AB4387-243A-48F7-881D-DE138DDE68BA}.Debug|x64.Build.0 = Debug|x64
{A0AB4387-243A-48F7-881D-DE138DDE68BA}.Release|Win32.ActiveCfg = Release|Win32
{A0AB4387-243A-48F7-881D-DE138DDE68BA}.Release|Win32.Build.0 = Release|Win32
{A0AB4387-243A-48F7-881D-DE138DDE68BA}.Release|x64.ActiveCfg = Release|x64
{A0AB4387-243A-48F7-881D-DE138DDE68BA}.Release|x64.Build.0 = Release|x64
{6295B87B-6312-4D7D-BCE9-A3626FD25417}.Debug|Win32.ActiveCfg = Debug|Win32
{6295B87B-6312-4D7D-BCE9-A3626FD25417}.Debug|Win32.Build.0 = Debug|Win32
{6295B87B-6312-4D7D-BCE9-A3626FD25417}.Debug|x64.ActiveCfg = Debug|x64
{6295B87B-6312-4D7D-BCE9-A3626FD25417}.Debug|x64.Build.0 = Debug|x64
{6295B87B-6312-4D7D-BCE9-A3626FD25417}.Release|Win32.ActiveCfg = Release|Win32
{6295B87B-6312-4D7D-BCE9-A3626FD25417}.Release|Win32.Build.0 = Release|Win32
{6295B87B-6312-4D7D-BCE9-A3626FD25417}.Release|x64.ActiveCfg = Release|x64
{6295B87B-6312-4D7D-BCE9-A3626FD25417}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

@ -0,0 +1,468 @@
/*
* Copyright (C) 2011-2014 Vinay Sajip. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista.
#define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows.
#endif
#include <stdio.h>
#include <windows.h>
#define APPENDED_ARCHIVE
#define MSGSIZE 1024
#if !defined(APPENDED_ARCHIVE)
static char suffix[] = {
#if defined(_CONSOLE)
"-script.py"
#else
"-script.pyw"
#endif
};
#endif
static int pid = 0;
#if !defined(_CONSOLE)
typedef int (__stdcall *MSGBOXWAPI)(IN HWND hWnd,
IN LPCSTR lpText, IN LPCSTR lpCaption,
IN UINT uType, IN WORD wLanguageId, IN DWORD dwMilliseconds);
#define MB_TIMEDOUT 32000
int MessageBoxTimeoutA(HWND hWnd, LPCSTR lpText,
LPCSTR lpCaption, UINT uType, WORD wLanguageId, DWORD dwMilliseconds)
{
static MSGBOXWAPI MsgBoxTOA = NULL;
HMODULE hUser = LoadLibraryA("user32.dll");
if (!MsgBoxTOA) {
if (hUser)
MsgBoxTOA = (MSGBOXWAPI)GetProcAddress(hUser,
"MessageBoxTimeoutA");
else {
/*
* stuff happened, add code to handle it here
* (possibly just call MessageBox())
*/
}
}
if (MsgBoxTOA)
return MsgBoxTOA(hWnd, lpText, lpCaption, uType, wLanguageId,
dwMilliseconds);
if (hUser)
FreeLibrary(hUser);
return 0;
}
#endif
static void
assert(BOOL condition, char * format, ... )
{
if (!condition) {
va_list va;
char message[MSGSIZE];
int len;
va_start(va, format);
len = vsnprintf_s(message, MSGSIZE, MSGSIZE - 1, format, va);
#if defined(_CONSOLE)
fprintf(stderr, "Fatal error in launcher: %s\n", message);
#else
MessageBoxTimeoutA(NULL, message, "Fatal Error in Launcher",
MB_OK | MB_SETFOREGROUND | MB_ICONERROR,
0, 3000);
#endif
ExitProcess(1);
}
}
static char script_path[MAX_PATH];
#if defined(APPENDED_ARCHIVE)
#define LARGE_BUFSIZE (65 * 1024 * 1024)
typedef struct {
DWORD sig;
DWORD unused_disk_nos;
DWORD unused_numrecs;
DWORD cdsize;
DWORD cdoffset;
} ENDCDR;
/* We don't want to pick up this variable when scanning the executable.
* So we initialise it statically, but fill in the first byte later.
*/
static char
end_cdr_sig [4] = { 0x00, 0x4B, 0x05, 0x06 };
static char *
find_pattern(char *buffer, size_t bufsize, char * pattern, size_t patsize)
{
char * result = NULL;
char * p;
char * bp = buffer;
long n;
while ((n = bufsize - (bp - buffer) - patsize) >= 0) {
p = (char *) memchr(bp, pattern[0], n);
if (p == NULL)
break;
if (memcmp(pattern, p, patsize) == 0) {
result = p; /* keep trying - we want the last one */
}
bp = p + 1;
}
return result;
}
static char *
find_shebang(char * buffer, size_t bufsize)
{
FILE * fp = NULL;
errno_t rc;
char * result = NULL;
char * p;
size_t read;
long pos;
long file_size;
long end_cdr_offset = -1;
ENDCDR end_cdr;
rc = fopen_s(&fp, script_path, "rb");
assert(rc == 0, "Failed to open executable");
fseek(fp, 0, SEEK_END);
file_size = ftell(fp);
pos = file_size - bufsize;
if (pos < 0)
pos = 0;
fseek(fp, pos, SEEK_SET);
read = fread(buffer, sizeof(char), bufsize, fp);
p = find_pattern(buffer, read, end_cdr_sig, sizeof(end_cdr_sig));
if (p != NULL) {
end_cdr = *((ENDCDR *) p);
end_cdr_offset = pos + (p - buffer);
}
else {
/*
* Try a larger buffer. A comment can only be 64K long, so
* go for the largest size.
*/
char * big_buffer = malloc(LARGE_BUFSIZE);
int n = (int) LARGE_BUFSIZE;
pos = file_size - n;
if (pos < 0)
pos = 0;
fseek(fp, pos, SEEK_SET);
read = fread(big_buffer, sizeof(char), n, fp);
p = find_pattern(big_buffer, read, end_cdr_sig, sizeof(end_cdr_sig));
assert(p != NULL, "Unable to find an appended archive.");
end_cdr = *((ENDCDR *) p);
end_cdr_offset = pos + (p - big_buffer);
free(big_buffer);
}
end_cdr_offset -= end_cdr.cdsize + end_cdr.cdoffset;
/*
* end_cdr_offset should now be pointing to the start of the archive,
* i.e. just after the shebang. We'll assume the shebang line has no
* # or ! chars except at the beginning, and fits into bufsize (which
* should be MAX_PATH).
*/
pos = end_cdr_offset - bufsize;
if (pos < 0)
pos = 0;
fseek(fp, pos, SEEK_SET);
read = fread(buffer, sizeof(char), bufsize, fp);
assert(read > 0, "Unable to read from file");
p = &buffer[read - 1];
while (p >= buffer) {
if (memcmp(p, "#!", 2) == 0) {
result = p;
break;
}
--p;
}
fclose(fp);
return result;
}
#endif
#if 0
static COMMAND * find_on_path(wchar_t * name)
{
wchar_t * pathext;
size_t varsize;
wchar_t * context = NULL;
wchar_t * extension;
COMMAND * result = NULL;
DWORD len;
errno_t rc;
wcscpy_s(path_command.key, MAX_PATH, name);
if (wcschr(name, L'.') != NULL) {
/* assume it has an extension. */
len = SearchPathW(NULL, name, NULL, MSGSIZE, path_command.value, NULL);
if (len) {
result = &path_command;
}
}
else {
/* No extension - search using registered extensions. */
rc = _wdupenv_s(&pathext, &varsize, L"PATHEXT");
if (rc == 0) {
extension = wcstok_s(pathext, L";", &context);
while (extension) {
len = SearchPathW(NULL, name, extension, MSGSIZE, path_command.value, NULL);
if (len) {
result = &path_command;
break;
}
extension = wcstok_s(NULL, L";", &context);
}
free(pathext);
}
}
return result;
}
#endif
static char *
skip_ws(char *p)
{
while (*p && isspace(*p))
++p;
return p;
}
static char *
skip_me(char * p)
{
char * result;
char terminator;
if (*p != '\"')
terminator = ' ';
else {
terminator = *p++;
++p;
}
result = strchr(p, terminator);
if (result == NULL) /* perhaps nothing more on the command line */
result = "";
else
result = skip_ws(++result);
return result;
}
static char *
find_terminator(char *buffer, size_t size)
{
char c;
char * result = NULL;
char * end = buffer + size;
char * p;
for (p = buffer; p < end; p++) {
c = *p;
if (c == '\r') {
result = p;
break;
}
if (c == '\n') {
result = p;
break;
}
}
return result;
}
static BOOL
safe_duplicate_handle(HANDLE in, HANDLE * pout)
{
BOOL ok;
HANDLE process = GetCurrentProcess();
DWORD rc;
*pout = NULL;
ok = DuplicateHandle(process, in, process, pout, 0, TRUE,
DUPLICATE_SAME_ACCESS);
if (!ok) {
rc = GetLastError();
if (rc == ERROR_INVALID_HANDLE)
ok = TRUE;
}
return ok;
}
static BOOL
control_key_handler(DWORD type)
{
if ((type == CTRL_C_EVENT) && pid)
GenerateConsoleCtrlEvent(pid, 0);
return TRUE;
}
static void
run_child(char * cmdline)
{
HANDLE job;
JOBOBJECT_EXTENDED_LIMIT_INFORMATION info;
DWORD rc;
BOOL ok;
STARTUPINFO si;
PROCESS_INFORMATION pi;
job = CreateJobObject(NULL, NULL);
ok = QueryInformationJobObject(job, JobObjectExtendedLimitInformation,
&info, sizeof(info), &rc);
assert(ok && (rc == sizeof(info)), "Job information querying failed");
info.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE |
JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK;
ok = SetInformationJobObject(job, JobObjectExtendedLimitInformation, &info,
sizeof(info));
assert(ok, "Job information setting failed");
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
ok = safe_duplicate_handle(GetStdHandle(STD_INPUT_HANDLE), &si.hStdInput);
assert(ok, "stdin duplication failed");
ok = safe_duplicate_handle(GetStdHandle(STD_OUTPUT_HANDLE), &si.hStdOutput);
assert(ok, "stdout duplication failed");
ok = safe_duplicate_handle(GetStdHandle(STD_ERROR_HANDLE), &si.hStdError);
assert(ok, "stderr duplication failed");
si.dwFlags = STARTF_USESTDHANDLES;
SetConsoleCtrlHandler((PHANDLER_ROUTINE) control_key_handler, TRUE);
ok = CreateProcess(NULL, cmdline, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
assert(ok, "Unable to create process using '%s'", cmdline);
pid = pi.dwProcessId;
AssignProcessToJobObject(job, pi.hProcess);
CloseHandle(pi.hThread);
WaitForSingleObject(pi.hProcess, INFINITE);
ok = GetExitCodeProcess(pi.hProcess, &rc);
assert(ok, "Failed to get exit code of process");
ExitProcess(rc);
}
static int
process(int argc, char * argv[])
{
char * cmdline = skip_me(GetCommandLine());
char * psp;
size_t len = GetModuleFileName(NULL, script_path, MAX_PATH);
FILE *fp = NULL;
char buffer[MAX_PATH];
char *cp;
char * cmdp;
char * p;
#if !defined(APPENDED_ARCHIVE)
errno_t rc;
#endif
if (script_path[0] != '\"')
psp = script_path;
else {
psp = &script_path[1];
len -= 2;
}
psp[len] = '\0';
#if !defined(APPENDED_ARCHIVE)
/* Replace the .exe with -script.py(w) */
p = strstr(psp, ".exe");
assert(p != NULL, "Failed to find \".exe\" in executable name");
len = MAX_PATH - (p - script_path);
assert(len > sizeof(suffix), "Failed to append \"%s\" suffix", suffix);
strncpy_s(p, len, suffix, sizeof(suffix));
#endif
#if defined(APPENDED_ARCHIVE)
/* Initialise signature dynamically so that it doesn't appear in
* a stock executable.
*/
end_cdr_sig[0] = 0x50;
p = find_shebang(buffer, MAX_PATH);
assert(p != NULL, "Failed to find shebang");
#else
rc = fopen_s(&fp, psp, "rb");
assert(rc == 0, "Failed to open script file \"%s\"", psp);
fread(buffer, sizeof(char), MAX_PATH, fp);
fclose(fp);
p = buffer;
#endif
cp = find_terminator(p, MAX_PATH);
assert(cp != NULL, "Expected to find terminator in shebang line");
*cp = '\0';
cp = p;
while (*cp && isspace(*cp))
++cp;
assert(*cp == '#', "Expected to find \'#\' at start of shebang line");
++cp;
while (*cp && isspace(*cp))
++cp;
assert(*cp == '!', "Expected to find \'!\' following \'#\' in shebang line");
++cp;
while (*cp && isspace(*cp))
++cp;
if (*cp == '"') {
++cp;
p = strrchr(cp, '"');
assert(p != NULL, "Expected to find terminating quote in shebang line");
*p = '\0';
}
len = strlen(cp) + 7 + strlen(psp) + strlen(cmdline); /* 2 spaces + 4 quotes + NUL */
cmdp = calloc(len, sizeof(char));
assert(cmdp != NULL, "Expected to be able to allocate command line memory");
_snprintf_s(cmdp, len, len, "\"%s\" \"%s\" %s", cp, psp, cmdline);
run_child(cmdp); /* never actually returns */
free(cmdp);
return 0;
}
#if defined(_CONSOLE)
int main(int argc, char* argv[])
{
return process(argc, argv);
}
#else
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
return process(__argc, __argv);
}
#endif

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

@ -0,0 +1,4 @@
#define IDI_ICON 101
LANGUAGE 0, 0
IDI_ICON ICON ".\\launcher.ico"
Loading…
Cancel
Save