char *
pyi_win32_wcs_to_mbs_sfn(const wchar_t *wstr)
{
    DWORD wsfnlen;
    wchar_t * wstr_sfn = NULL;
    char * str = NULL;
    DWORD ret;

    wsfnlen = GetShortPathNameW(wstr, NULL, 0);

    if (wsfnlen) {
        wstr_sfn = (wchar_t *)calloc(wsfnlen + 1, sizeof(wchar_t));
        ret = GetShortPathNameW(wstr, wstr_sfn, wsfnlen);

        if (ret) {
            str = pyi_win32_wcs_to_mbs(wstr_sfn);
        }
        free(wstr_sfn);
    }

    if (!str) {
        VS("Failed to get short path name for filename. GetShortPathNameW: \n%s\n",
           GetWinErrorString(0)
           );
        str = pyi_win32_wcs_to_mbs(wstr);
    }
    return str;
}
char * pyi_win32_wcs_to_mbs(const wchar_t *wstr) {
    DWORD len, ret;
    char * str;

    /* NOTE: setlocale hysterics are not needed on Windows - this function
       has an explicit codepage parameter. CP_ACP means "current ANSI codepage"
       which is set in the "Language for Non-Unicode Programs" control panel setting. */

    /* Get buffer size by passing NULL and 0 for output arguments */
    len = WideCharToMultiByte(CP_ACP,    // CodePage
                              0,         // dwFlags
                              wstr,      // lpWideCharStr
                              -1  ,      // cchWideChar - length in chars
                              NULL,      // lpMultiByteStr
                              0,         // cbMultiByte - length in bytes
                              NULL,      // lpDefaultChar
                              NULL       // lpUsedDefaultChar
                              );
    if(0 == len) {
        FATALERROR("Failed to get ANSI buffer size"
                   "(WideCharToMultiByte: %s)",
                   GetWinErrorString()
                   );
        return NULL;
    }

    str = (char *)malloc(sizeof(char) * wcslen(wstr) + 1);

    ret = WideCharToMultiByte(CP_ACP,    // CodePage
                              0,         // dwFlags
                              wstr,      // lpWideCharStr
                              -1,        // cchWideChar - length in chars
                              str,       // lpMultiByteStr
                              len,       // cbMultiByte - length in bytes
                              NULL,      // lpDefaultChar
                              NULL       // lpUsedDefaultChar
                              );

    if(0 == ret) {
        FATALERROR("Failed to encode filename as ANSI"
                   "(WideCharToMultiByte: %s)",
                   GetWinErrorString()
                   );
        return NULL;
    }
    return str;
}
/*
 * Encode wchar_t (UTF16) into char (UTF8).
 *
 * `wstr` must be null-terminated.
 *
 * If `str` is not NULL, copies the result into the given buffer, which must hold
 * at least `len` bytes. Returns the given buffer if successful. Returns NULL on
 * encoding failure, or if the UTF-8 encoding requires more than `len` bytes.
 *
 * If `str` is NULL, allocates and returns a new buffer to store the result. The
 * `len` argument is ignored. Returns NULL on encoding failure. The caller is
 * responsible for freeing the returned buffer using free().
 *
 */
char * pyi_win32_utils_to_utf8(char *str, const wchar_t *wstr, size_t len) {
    char * output;
    if(NULL == str) {
        /* Get buffer size by passing NULL and 0 for output arguments
         * -1 for cchWideChar means string is null-terminated
         */
        len = WideCharToMultiByte(CP_UTF8,              // CodePage
                                  0,                    // dwFlags
                                  wstr,                 // lpWideCharStr
                                  -1,                   // cchWideChar - length in chars
                                  NULL,                 // lpMultiByteStr
                                  0,                    // cbMultiByte - length in bytes
                                  NULL,                 // lpDefaultChar
                                  NULL                  // lpUsedDefaultChar
                                  );
        if(0 == len) {
            FATALERROR("Failed to get UTF-8 buffer size (WideCharToMultiByte: %s)",
                       GetWinErrorString()
                       );
            return NULL;
        }

        output = (char *)malloc(sizeof(char) * len + 1);
    } else {
        output = str;
    }

    len = WideCharToMultiByte(CP_UTF8,              // CodePage
                              0,                    // dwFlags
                              wstr,                 // lpWideCharStr
                              -1,                   // cchWideChar - length in chars
                              output,               // lpMultiByteStr
                              (DWORD)len,           // cbMultiByte - length in bytes
                              NULL,                 // lpDefaultChar
                              NULL                  // lpUsedDefaultChar
                              );
    if(len == 0) {
        FATALERROR("Failed to encode wchar_t as UTF-8 (WideCharToMultiByte: %s)",
                   GetWinErrorString()
                   );
        return NULL;
    }
    return output;
}
wchar_t * pyi_win32_utils_from_utf8(wchar_t *wstr, const char *str, size_t wlen) {
    wchar_t * output;
    if(NULL == wstr) {
        /* Get buffer size by passing NULL and 0 for output arguments
         * -1 for cbMultiByte means string is null-terminated.
         */
        wlen = MultiByteToWideChar(CP_UTF8,              // CodePage
                                   0,                   // dwFlags
                                   str,                  // lpMultiByteStr
                                   -1,                   // cbMultiByte - length in bytes
                                   NULL,                 // lpWideCharStr
                                   0                     // cchWideChar - length in chars
                                   );
        if(0 == wlen) {
            FATALERROR("Failed to get UTF-8 buffer size (WideCharToMultiByte: %s)",
                       GetWinErrorString()
                       );
            return NULL;
        }

        output = (wchar_t *)malloc(sizeof(wchar_t) * wlen + 1);
    } else {
        output = wstr;
    }

    wlen = MultiByteToWideChar(CP_UTF8,              // CodePage
                               0,                    // dwFlags
                               str,                  // lpMultiByteStr
                               -1,                   // cbMultiByte - length in bytes
                               output,               // lpWideCharStr
                               (DWORD)wlen           // cchWideChar - length in chars
                               );
    if(wlen == 0) {
        FATALERROR("Failed to encode wchar_t as UTF-8 (WideCharToMultiByte: %s)",
                   GetWinErrorString()
                   );
        return NULL;
    }
    return output;
}
int
CreateActContext(const char *manifestpath)
{
    wchar_t * manifestpath_w;
    ACTCTXW ctx;
    BOOL activated;
    HANDLE k32;

    HANDLE (WINAPI * CreateActCtx)(PACTCTXW pActCtx);
    BOOL (WINAPI * ActivateActCtx)(HANDLE hActCtx, ULONG_PTR * lpCookie);

    /* Setup activation context */
    VS("LOADER: manifestpath: %s\n", manifestpath);
    manifestpath_w = pyi_win32_utils_from_utf8(NULL, manifestpath, 0);

    k32 = LoadLibraryA("kernel32");
    CreateActCtx = (void*)GetProcAddress(k32, "CreateActCtxW");
    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_w;
    ctx.dwFlags = ACTCTX_FLAG_SET_PROCESS_DEFAULT;

    hCtx = CreateActCtx(&ctx);
    free(manifestpath_w);

    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: ActivateActCtx: \n%s\n", GetWinErrorString(0));
    return 0;
}
Example #6
0
/*
 * Return full path to the current executable.
 * Executable is the .exe created by pyinstaller: path/myappname.exe
 * Because the calling process can set argv[0] to whatever it wants,
 * we use a few alternate methods to get the executable path.
 *
 * 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];
    size_t result = -1;

#ifdef _WIN32
    wchar_t modulename_w[PATH_MAX];

    /* GetModuleFileNameW returns an absolute, fully qualified path
     */
    if (!GetModuleFileNameW(NULL, modulename_w, PATH_MAX)) {
        FATALERROR("Failed to get executable path. \nGetModuleFileNameW: %s",
                   GetWinErrorString());
        return -1;
    }

    if (!pyi_win32_utils_to_utf8(execfile, modulename_w, PATH_MAX)) {
        FATALERROR("Failed to convert executable path to UTF-8.",
                   GetWinErrorString());
        return -1;
    }

#elif __APPLE__
    uint32_t length = sizeof(buffer);

    /* Mac OS X has special function to obtain path to executable.
     * This may return a symlink.
     */
    if (_NSGetExecutablePath(buffer, &length) != 0) {
        FATALERROR("System error - unable to load!");
        return -1;
    }

    if (pyi_path_fullpath(execfile, PATH_MAX, buffer) == false) {
        VS("LOADER: Cannot get fullpath for %s\n", execfile);
        return -1;
    }

#else /* ifdef _WIN32 */
    result = -1;
    /* On Linux, FreeBSD, and Solaris, we try these /proc paths first
     */
    #if defined(__linux__)
    result = readlink("/proc/self/exe", execfile, PATH_MAX);  /* Linux */
    #elif defined(__FreeBSD__)
    result = readlink("/proc/curproc/file", execfile, PATH_MAX);  /* FreeBSD */
    #elif defined(__sun)
    result = readlink("/proc/self/path/a.out", execfile, PATH_MAX);  /* Solaris */
    #endif

    if (-1 != result) {
        /* execfile is not yet zero-terminated. result is the byte count. */
        *(execfile + result) = '\0';
    }
    else {
        /* No /proc path found or provided
         */
        if (appname[0] == PYI_SEP || strchr(appname, PYI_SEP)) {
            /* Absolute or relative path.
             * Convert to absolute and resolve symlinks.
             */
            if (pyi_path_fullpath(execfile, PATH_MAX, appname) == false) {
                VS("LOADER: Cannot get fullpath for %s\n", execfile);
                return -1;
            }
        }
        else {
            /* Not absolute or relative path, just program name. Search $PATH
             */
            result = pyi_search_path(buffer, appname);

            if (-1 == result) {
                /* Searching $PATH failed, user is crazy. */
                VS("LOADER: Searching $PATH failed for %s", appname);
                strcpy(buffer, appname);
            }

            if (pyi_path_fullpath(execfile, PATH_MAX, buffer) == false) {
                VS("LOADER: Cannot get fullpath for %s\n", execfile);
                return -1;
            }
        }
    }
#endif /* ifdef _WIN32 */
    VS("LOADER: executable is %s\n", execfile);
    return 0;
}