@ -6,6 +6,9 @@
# define WIN32_LEAN_AND_MEAN
# include <Windows.h>
# include <shellapi.h>
# include <shlobj.h>
# include <string>
# include <winrt\Windows.ApplicationModel.h>
# include <winrt\Windows.Storage.h>
@ -24,192 +27,219 @@ const wchar_t *PROGNAME = L"python.exe";
# endif
# endif
static void
s et_user_base( )
static std : : wstring
g et_user_base( )
{
wchar_t envBuffer [ 2048 ] ;
try {
const auto appData = winrt : : Windows : : Storage : : ApplicationData : : Current ( ) ;
if ( appData ) {
const auto localCache = appData . LocalCacheFolder ( ) ;
if ( localCache ) {
auto path = localCache . Path ( ) ;
if ( ! path . empty ( ) & &
! wcscpy_s ( envBuffer , path . c_str ( ) ) & &
! wcscat_s ( envBuffer , L " \\ local-packages " )
) {
_wputenv_s ( L " PYTHONUSERBASE " , envBuffer ) ;
if ( ! path . empty ( ) ) {
return std : : wstring ( path ) + L " \\ local-packages " ;
}
}
}
} catch ( . . . ) {
}
return std : : wstring ( ) ;
}
static const wchar_t *
get_argv0 ( const wchar_t * argv0 )
static std : : wstring
get_package_family ( )
{
winrt : : hstring installPath ;
const wchar_t * launcherPath ;
wchar_t * buffer ;
size_t len ;
launcherPath = _wgetenv ( L " __PYVENV_LAUNCHER__ " ) ;
if ( launcherPath & & launcherPath [ 0 ] ) {
len = wcslen ( launcherPath ) + 1 ;
buffer = ( wchar_t * ) malloc ( sizeof ( wchar_t ) * len ) ;
if ( ! buffer ) {
Py_FatalError ( " out of memory " ) ;
return NULL ;
}
if ( wcscpy_s ( buffer , len , launcherPath ) ) {
Py_FatalError ( " failed to copy to buffer " ) ;
return NULL ;
try {
const auto package = winrt : : Windows : : ApplicationModel : : Package : : Current ( ) ;
if ( package ) {
const auto id = package . Id ( ) ;
if ( id ) {
return std : : wstring ( id . FamilyName ( ) ) ;
}
}
return buffer ;
}
catch ( . . . ) {
}
return std : : wstring ( ) ;
}
static std : : wstring
get_package_home ( )
{
try {
const auto package = winrt : : Windows : : ApplicationModel : : Package : : Current ( ) ;
if ( package ) {
const auto install = package . InstalledLocation ( ) ;
if ( install ) {
installPath = install . Path ( ) ;
const auto path = package . InstalledLocation ( ) ;
if ( path ) {
return std : : wstring ( path . Path ( ) ) ;
}
}
}
catch ( . . . ) {
}
if ( ! installPath . empty ( ) ) {
len = installPath . size ( ) + wcslen ( PROGNAME ) + 2 ;
} else {
len = wcslen ( argv0 ) + wcslen ( PROGNAME ) + 1 ;
}
return std : : wstring ( ) ;
}
buffer = ( wchar_t * ) malloc ( sizeof ( wchar_t ) * len ) ;
if ( ! buffer ) {
Py_FatalError ( " out of memory " ) ;
return NULL ;
}
static PyStatus
set_process_name ( PyConfig * config )
{
PyStatus status = PyStatus_Ok ( ) ;
std : : wstring executable ;
if ( ! installPath . empty ( ) ) {
if ( wcscpy_s ( buffer , len , installPath . c_str ( ) ) ) {
Py_FatalError ( " failed to copy to buffer " ) ;
return NULL ;
}
if ( wcscat_s ( buffer , len , L " \\ " ) ) {
Py_FatalError ( " failed to concatenate backslash " ) ;
return NULL ;
}
} else {
if ( wcscpy_s ( buffer , len , argv0 ) ) {
Py_FatalError ( " failed to copy argv[0] " ) ;
return NULL ;
}
const auto home = get_package_home ( ) ;
const auto family = get_package_family ( ) ;
wchar_t * name = wcsrchr ( buffer , L ' \\ ' ) ;
if ( name ) {
name [ 1 ] = L ' \0 ' ;
} else {
buffer [ 0 ] = L ' \0 ' ;
if ( ! family . empty ( ) ) {
PWSTR localAppData ;
if ( SUCCEEDED ( SHGetKnownFolderPath ( FOLDERID_LocalAppData , 0 ,
NULL , & localAppData ) ) ) {
executable = std : : wstring ( localAppData )
+ L " \\ Microsoft \\ WindowsApps \\ "
+ family
+ L " \\ "
+ PROGNAME ;
CoTaskMemFree ( localAppData ) ;
}
}
if ( wcscat_s ( buffer , len , PROGNAME ) ) {
Py_FatalError ( " failed to concatenate program name " ) ;
return NULL ;
/* Only use module filename if we don't have a home */
if ( home . empty ( ) & & executable . empty ( ) ) {
executable . resize ( MAX_PATH ) ;
while ( true ) {
DWORD len = GetModuleFileNameW (
NULL , executable . data ( ) , ( DWORD ) executable . size ( ) ) ;
if ( len = = 0 ) {
executable . clear ( ) ;
break ;
} else if ( len = = executable . size ( ) & &
GetLastError ( ) = = ERROR_INSUFFICIENT_BUFFER ) {
executable . resize ( len * 2 ) ;
} else {
executable . resize ( len ) ;
break ;
}
}
}
return buffer ;
}
static wchar_t *
get_process_name ( )
{
DWORD bufferLen = MAX_PATH ;
DWORD len = bufferLen ;
wchar_t * r = NULL ;
while ( ! r ) {
r = ( wchar_t * ) malloc ( bufferLen * sizeof ( wchar_t ) ) ;
if ( ! r ) {
Py_FatalError ( " out of memory " ) ;
return NULL ;
if ( ! home . empty ( ) ) {
status = PyConfig_SetString ( config , & config - > home , home . c_str ( ) ) ;
if ( PyStatus_Exception ( status ) ) {
return status ;
}
len = GetModuleFileNameW ( NULL , r , bufferLen ) ;
if ( len = = 0 ) {
free ( ( void * ) r ) ;
return NULL ;
} else if ( len = = bufferLen & &
GetLastError ( ) = = ERROR_INSUFFICIENT_BUFFER ) {
free ( r ) ;
r = NULL ;
bufferLen * = 2 ;
}
const wchar_t * launcherPath = _wgetenv ( L " __PYVENV_LAUNCHER__ " ) ;
if ( launcherPath ) {
if ( ! executable . empty ( ) ) {
status = PyConfig_SetString ( config , & config - > base_executable ,
executable . c_str ( ) ) ;
if ( PyStatus_Exception ( status ) ) {
return status ;
}
}
status = PyConfig_SetString (
config , & config - > executable , launcherPath ) ;
/* bpo-35873: Clear the environment variable to avoid it being
* inherited by child processes . */
_wputenv_s ( L " __PYVENV_LAUNCHER__ " , L " " ) ;
} else if ( ! executable . empty ( ) ) {
status = PyConfig_SetString (
config , & config - > executable , executable . c_str ( ) ) ;
}
return r ;
return status ;
}
int
wmain ( int argc , wchar_t * * argv )
{
const wchar_t * * new_argv ;
int new_argc ;
const wchar_t * exeName ;
PyStatus status ;
new_argc = argc ;
new_argv = ( const wchar_t * * ) malloc ( sizeof ( wchar_t * ) * ( argc + 2 ) ) ;
if ( new_argv = = NULL ) {
Py_FatalError ( " out of memory " ) ;
return - 1 ;
PyPreConfig preconfig ;
PyConfig config ;
PyPreConfig_InitPythonConfig ( & preconfig ) ;
status = Py_PreInitializeFromArgs ( & preconfig , argc , argv ) ;
if ( PyStatus_Exception ( status ) ) {
goto fail ;
}
exeName = get_process_name ( ) ;
status = PyConfig_InitPythonConfig ( & config ) ;
if ( PyStatus_Exception ( status ) ) {
goto fail ;
}
new_argv [ 0 ] = get_argv0 ( exeName ? exeName : argv [ 0 ] ) ;
for ( int i = 1 ; i < argc ; + + i ) {
new_argv [ i ] = argv [ i ] ;
status = PyConfig_SetArgv ( & config , argc , argv ) ;
if ( PyStatus_Exception ( status ) ) {
goto fail ;
}
set_user_base ( ) ;
status = set_process_name ( & config ) ;
if ( PyStatus_Exception ( status ) ) {
goto fail ;
}
if ( exeName ) {
const wchar_t * p = wcsrchr ( exeName , L ' \\ ' ) ;
if ( p ) {
const wchar_t * moduleName = NULL ;
if ( * p + + = = L ' \\ ' ) {
if ( wcsnicmp ( p , L " pip " , 3 ) = = 0 ) {
moduleName = L " pip " ;
/* No longer required when pip 19.1 is added */
_wputenv_s ( L " PIP_USER " , L " true " ) ;
} else if ( wcsnicmp ( p , L " idle " , 4 ) = = 0 ) {
moduleName = L " idlelib " ;
}
}
const wchar_t * p = _wgetenv ( L " PYTHONUSERBASE " ) ;
if ( ! p | | ! * p ) {
_wputenv_s ( L " PYTHONUSERBASE " , get_user_base ( ) . c_str ( ) ) ;
}
if ( moduleName ) {
new_argc + = 2 ;
for ( int i = argc ; i > = 1 ; - - i ) {
new_argv [ i + 2 ] = new_argv [ i ] ;
}
new_argv [ 1 ] = L " -m " ;
new_argv [ 2 ] = moduleName ;
p = wcsrchr ( argv [ 0 ] , L ' \\ ' ) ;
if ( ! p ) {
p = argv [ 0 ] ;
}
if ( p ) {
if ( * p = = L ' \\ ' ) {
p + + ;
}
const wchar_t * moduleName = NULL ;
if ( wcsnicmp ( p , L " pip " , 3 ) = = 0 ) {
moduleName = L " pip " ;
/* No longer required when pip 19.1 is added */
_wputenv_s ( L " PIP_USER " , L " true " ) ;
} else if ( wcsnicmp ( p , L " idle " , 4 ) = = 0 ) {
moduleName = L " idlelib " ;
}
if ( moduleName ) {
status = PyConfig_SetString ( & config , & config . run_module , moduleName ) ;
if ( PyStatus_Exception ( status ) ) {
goto fail ;
}
status = PyConfig_SetString ( & config , & config . run_filename , NULL ) ;
if ( PyStatus_Exception ( status ) ) {
goto fail ;
}
status = PyConfig_SetString ( & config , & config . run_command , NULL ) ;
if ( PyStatus_Exception ( status ) ) {
goto fail ;
}
}
}
/* Override program_full_path from here so that
sys . executable is set correctly . */
_Py_SetProgramFullPath ( new_argv [ 0 ] ) ;
int result = Py_Main ( new_argc , ( wchar_t * * ) new_argv ) ;
status = Py_InitializeFromConfig ( & config ) ;
if ( PyStatus_Exception ( status ) ) {
goto fail ;
}
PyConfig_Clear ( & config ) ;
free ( ( void * ) exeName ) ;
free ( ( void * ) new_argv ) ;
return Py_RunMain ( ) ;
return result ;
fail :
PyConfig_Clear ( & config ) ;
if ( PyStatus_IsExit ( status ) ) {
return status . exitcode ;
}
assert ( PyStatus_Exception ( status ) ) ;
Py_ExitStatusException ( status ) ;
/* Unreachable code */
return 0 ;
}
# ifdef PYTHONW