Пример #1
0
/*
 * Load the Python DLL, and get all of the necessary entry points
 */
int pyi_pylib_load(ARCHIVE_STATUS *status)
{
	dylib_t dll;
	char dllpath[PATH_MAX];
    char dllname[64];
    int pyvers = ntohl(status->cookie.pyvers);

    // Are we going to load the Python 2.x library?
    is_py2 = (pyvers / 10) == 2;

/*
 * On AIX Append the shared object member to the library path
 * to make it look like this:
 *   libpython2.6.a(libpython2.6.so)
 */
#ifdef AIX
    /*
     * On AIX 'ar' archives are used for both static and shared object.
     * To load a shared object from a library, it should be loaded like this:
     *   dlopen("libpython2.6.a(libpython2.6.so)", RTLD_MEMBER)
     */
    uint32_t pyvers_major;
    uint32_t pyvers_minor;

    pyvers_major = pyvers / 10;
    pyvers_minor = pyvers % 10;

    sprintf(dllname,
            "libpython%01d.%01d.a(libpython%01d.%01d.so)",
            pyvers_major, pyvers_minor, pyvers_major, pyvers_minor);
#else
    strcpy(dllname, status->cookie.pylibname);
#endif

    /*
     * Look for Python library in homepath or temppath.
     * It depends on the value of mainpath.
     */
    pyi_path_join(dllpath, status->mainpath, dllname);


    VS("LOADER: Python library: %s\n", dllpath);

	/* Load the DLL */
    dll = pyi_utils_dlopen(dllpath);

    /* Check success of loading Python library. */
	if (dll == 0) {
#ifdef _WIN32
		FATALERROR("Error loading Python DLL: %s (error code %d)\n",
			dllpath, GetLastError());
#else
		FATALERROR("Error loading Python lib '%s': %s\n",
			dllpath, dlerror());
#endif
		return -1;
	}

	return pyi_python_map_names(dll, pyvers);
}
Пример #2
0
/* Convert a UTF-8 string to an ANSI string, also attempting to get the MS-DOS
   ShortFileName if the string is a filename. ShortFileName allows Python 2.7 to
   accept filenames which cannot encode in the current ANSI codepage.

   Preserves the filename's original basename, since the bootloader code depends on
   the unmodified basename. Assumes that the basename can be encoded using the current
   ANSI codepage.

   This is a workaround for <https://github.com/pyinstaller/pyinstaller/issues/298>.

   Copies the converted string to `dest`, which must be a buffer
   of at least PATH_MAX characters. Returns 'dest' if successful.

   Returns NULL and logs error reason if encoding fails.
 */
char * pyi_win32_utf8_to_mbs_sfn_keep_basename(char * dest, const char * src) {
    char * mbs_buffer;
    char * mbs_sfn_buffer;
    char basename[PATH_MAX];
    char dirname[PATH_MAX];

    /* Convert path to mbs*/
    mbs_buffer = pyi_win32_utf8_to_mbs(NULL, src, 0);
    if(NULL == mbs_buffer) {
        return NULL;
    }

    /* Convert path again to mbs, this time with SFN */
    mbs_sfn_buffer = pyi_win32_utf8_to_mbs_sfn(NULL, src, 0);
    if(NULL == mbs_sfn_buffer) {
        free(mbs_buffer);
        return NULL;
    }

    pyi_path_basename(basename, mbs_buffer);
    pyi_path_dirname(dirname, mbs_sfn_buffer);
    pyi_path_join(dest, dirname, basename);
    free(mbs_buffer);
    free(mbs_sfn_buffer);
    return dest;
}
Пример #3
0
int CreateActContext(char *workpath, char *thisfile)
{
    char manifestpath[PATH_MAX];
    char basename[PATH_MAX];
    ACTCTX ctx;
    BOOL activated;
    HANDLE k32;
    HANDLE (WINAPI *CreateActCtx)(PACTCTX pActCtx);
    BOOL (WINAPI *ActivateActCtx)(HANDLE hActCtx, ULONG_PTR *lpCookie);

    // If not XP, nothing to do -- return OK
    if (!IsXPOrLater())
        return 1;
       
    /* Setup activation context */
    pyi_path_basename(basename, thisfile);
    pyi_path_join(manifestpath, workpath, basename);
    strcat(manifestpath, ".manifest");
    VS("LOADER: manifestpath: %s\n", manifestpath);
    
    k32 = LoadLibrary("kernel32");
    CreateActCtx = (void*)GetProcAddress(k32, "CreateActCtxA");
    ActivateActCtx = (void*)GetProcAddress(k32, "ActivateActCtx");
    
    if (!CreateActCtx || !ActivateActCtx)
    {
        VS("LOADER: Cannot find CreateActCtx/ActivateActCtx exports in kernel32.dll\n");
        return 0;
    }
    
    ZeroMemory(&ctx, sizeof(ctx));
    ctx.cbSize = sizeof(ACTCTX);
    ctx.lpSource = manifestpath;

    hCtx = CreateActCtx(&ctx);
    if (hCtx != INVALID_HANDLE_VALUE)
    {
        VS("LOADER: Activation context created\n");
        activated = ActivateActCtx(hCtx, &actToken);
        if (activated)
        {
            VS("LOADER: Activation context activated\n");
            return 1;
        }
    }

    hCtx = INVALID_HANDLE_VALUE;
    VS("LOADER: Error activating the context\n");
    return 0;
}
Пример #4
0
void
pyi_launch_initialize(ARCHIVE_STATUS * status)
{
#if defined(_WIN32)
    char * manifest;
    manifest = pyi_arch_get_option(status, "pyi-windows-manifest-filename");

    if (NULL != manifest) {
        manifest = pyi_path_join(NULL, status->mainpath, manifest);
        CreateActContext(manifest);
        free(manifest);
    }
#endif /* if defined(_WIN32) */
}
Пример #5
0
/* Search $PATH for the program named 'appname' and return its full path.
 * 'result' should be a buffer of at least PATH_MAX characters.
 */
int
pyi_search_path(char * result, const char * appname)
{
    char * path = getenv("PATH");
    char dirname[PATH_MAX + 1];
    char filename[PATH_MAX + 1];

    if (NULL == path) {
        return -1;
    }

    while (1) {
        char *delim = strchr(path, PYI_PATHSEP);

        if (delim) {
            size_t len = delim - path;

            if (len > PATH_MAX) {
                len = PATH_MAX;
            }
            strncpy(dirname, path, len);
            *(dirname + len) = '\0';
        }
        else {  /* last $PATH element */
            strncpy(dirname, path, PATH_MAX);
        }
        pyi_path_join(filename, dirname, appname);

        if (pyi_path_exists(filename)) {
            strncpy(result, filename, PATH_MAX);
            return 0;
        }

        if (!delim) {
            break;
        }
        path = delim + 1;
    }
    return -1;
}
Пример #6
0
/*
 * Return full path to the current executable.
 * Executable is the .exe created by pyinstaller: path/myappname.exe
 *
 * execfile - buffer where to put path to executable.
 * appname - usually the item argv[0].
 */
int pyi_path_executable(char *execfile, const char *appname)
{
    char buffer[PATH_MAX];

#ifdef WIN32
    char dos83_buffer[PATH_MAX];
    stb__wchar wchar_buffer[PATH_MAX];
    stb__wchar wchar_dos83_buffer[PATH_MAX];
    char basename[PATH_MAX];
    char dirname[PATH_MAX];

    /* Windows has special function to obtain path to executable.
     * We EXPLICTLY use wide-string API in the bootloader because
     * otherwise it is impossible to represent non-ASCII character
     * from a different character set. For instance, let's say I have
     * a Latin-1 (Europe Windows), and I want to run a PyInstaller
     * program in a path with japanese character; there is no way to
     * represent that path with ANSI API in Windows, because ANSI API
     * would only support the local charset (Latin-1).
     */
	if (!GetModuleFileNameW(NULL, wchar_buffer, PATH_MAX)) {
		FATALERROR("System error - unable to load!");
		return -1;
	}
    /* Convert wchar_t to utf8. Just use type char as usual. */
    stb_to_utf8(buffer, wchar_buffer, PATH_MAX);

    /*
     * Use 8.3 filename (dos 8.3 or short filename)
     * to overcome the Python and PyInstaller limitation
     * to run with foreign characters in directory names.
     *
     * If 8.3 filename does not exist, original vaule is just copied
     * to the supplied buffer. 8.3 filename might not be available
     * for some networking file systems.
     *
     * This is workaround for <http://www.pyinstaller.org/ticket/298>.
     */
    GetShortPathNameW(wchar_buffer, wchar_dos83_buffer, PATH_MAX);
    /* Convert wchar_t to utf8 just use char as usual. */
    stb_to_utf8(dos83_buffer, wchar_dos83_buffer, PATH_MAX);

    /*
     * Construct proper execfile -  83_DIRNAME + full_basename.
     * GetShortPathName() makes also the basename (appname.exe) shorter.
     *
     * However, bootloader code depends on unmodified basename.
     * Using basename from original path should fix this.
     * It is supposed that basename does not contain any foreign characters.
     *
     * Reuse 'buffer' variable.
     */
    pyi_path_basename(basename, buffer);
    pyi_path_dirname(dirname, dos83_buffer);
    pyi_path_join(buffer, dirname, basename);

#elif __APPLE__
    uint32_t length = sizeof(buffer);

    /* Mac OS X has special function to obtain path to executable. */
    if (_NSGetExecutablePath(buffer, &length) != 0) {
        FATALERROR("System error - unable to load!");
		return -1;
    }
#else
    /* Fill in thisfile. */
    #ifdef __CYGWIN__
    if (strncasecmp(&appname[strlen(appname)-4], ".exe", 4)) {
        strcpy(execfile, appname);
        strcat(execfile, ".exe");
        PI_SetProgramName(execfile);
    }
    else
    #endif /* __CYGWIN__ */
    PI_SetProgramName(appname);
    strcpy(buffer, PI_GetProgramFullPath());
#endif
    /*
     * Ensure path to executable is absolute.
     * 'execfile' starting with ./ might break some modules when changing
     * the CWD.From 'execfile' is constructed 'homepath' and homepath is used
     * for LD_LIBRARY_PATH variavle. Relative LD_LIBRARY_PATH is a security
     * problem.
     */
    if(stb_fullpath(execfile, PATH_MAX, buffer) == false) {
        VS("LOADER: executable is %s\n", execfile);
        return -1;
    }
 
    VS("LOADER: executable is %s\n", execfile);

	return 0;
}