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; }
/* * 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; }