1. Eduard-Cristian Stefan
  2. exemaker

Commits

timeless  committed db95446

Rewrite code

  • Participants
  • Parent commits f53df11
  • Branches default

Comments (0)

Files changed (1)

File exemaker.c

View file
 }
 
 /* -------------------------------------------------------------------- */
+const char cannot_open[] = "Cannot open ";
+const char cannot_find[] = "Cannot find ";
+const char bang_python[] = "#!python.exe";
+const char lib_os_py[] = "\\lib\\os.py";
+const char cannot_find_dll_in[] = "Cannot find DLL in ";
 
 int __cdecl
 main(int ac, char **av)
 {
-    HINSTANCE dll;
-    HANDLE file;
+    HINSTANCE mainDll;
     DWORD n;
     char* argv[100];
     int (__cdecl * Py_Main)(int argc, char *argv[]);
     void (__cdecl * Py_SetPythonHome)(char* home);
-    char dllfile[256];
+    char fullfile[512];
+    char workingdir[512];
+    char requestedapplication[256];
     char exefile[256];
     char scriptfile[256];
     char message[512];
+    char* application;
+    DWORD isExe;
     DWORD i;
 
-    /* set script name */
+    /* calculate script name: our .exe name with .exe replaced by .py */
     GetModuleFileName(NULL, scriptfile, sizeof(scriptfile));
     i = rfindx(scriptfile, '.');
     scriptfile[i++] = '.';
     scriptfile[i++] = 'y';
     scriptfile[i] = '\0';
 
-    /* read first line from script */
-    file = CreateFile(scriptfile, GENERIC_READ, FILE_SHARE_READ, NULL,
-                      OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-    if (file == (HANDLE) -1) {
-        strcpy(message, "Cannot open "); strcat(message, scriptfile);
-        goto error;
+    n = finddir(scriptfile);
+    strncpy_s(workingdir, sizeof(workingdir), scriptfile, n);
+    workingdir[n] = 0;
+
+    {
+        /* read first line from script */
+        HANDLE script = CreateFile(scriptfile, GENERIC_READ, FILE_SHARE_READ, NULL,
+                            OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+        if (script == (HANDLE) -1) {
+            strncpy_s(message, sizeof message, cannot_open, sizeof cannot_open);
+            strcat_s(message, sizeof message, scriptfile);
+            goto error;
+        }
+        ReadFile(script, requestedapplication, sizeof(requestedapplication)-1, &n, NULL);
+        CloseHandle(script);
     }
-    ReadFile(file, dllfile, sizeof(dllfile)-1, &n, NULL);
-    CloseHandle(file);
 
     i = slashtobs(requestedapplication, n);
     requestedapplication[i] = '\0';
 
     /* look for #! header; if not present, assume #!python.exe */
-    if (dllfile[0] != '#' && dllfile[1] != '!') {
-        /* skip past the #! */
-        dllfile += 2;
+    if (requestedapplication[0] == '#' && requestedapplication[1] == '!') {
+        isExe = !memcmp(requestedapplication+i-4, ".exe", 4);
     } else {
-        strcpy(dllfile, "#!python.exe");
-        dllfile += 2;
-        i = strlen(dllfile);
+        strncpy_s(requestedapplication, sizeof requestedapplication, bang_python, sizeof bang_python);
+        isExe = 1;
+    }
+    /* skip past the #! */
+    application = requestedapplication + 2;
+
+    /* search the exe directory first */
+    if (requestedapplication[0] == '\\' || requestedapplication[1] == ':') {
+        /* absolute path, we can use LoadLibraryEx with LOAD_WITH_ALTERED_SEARCH_PATH */
+        application = requestedapplication;
+    } else {
+        DWORD slash = finddir(scriptfile) + 1;
+        strncpy_s(fullfile, sizeof(fullfile), scriptfile, slash);
+        fullfile[slash] = 0;
+        strcat_s(fullfile, sizeof(fullfile), application);
+        application = fullfile;
     }
 
-    /* search the exe directory first */
-    dll = LoadLibraryEx(dllfile, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
-    if (!dll) {
-        strcpy(message, "Cannot find "); strcat(message, dllfile);
+    mainDll = LoadLibraryEx(application, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
+    if (!mainDll) {
+        strncpy_s(message, sizeof message, cannot_find, sizeof cannot_find);
+        strcat_s(message, sizeof message, requestedapplication);
         goto error;
     }
 
-    if (!memcmp(dllfile+i-4, ".exe", 4)) {
+    if (isExe) {
+        HINSTANCE pythonDll;
         /* it's an EXE file; look for a Python DLL */
-        char* realdllfile = GetPythonImport(dll);
-        if (!realdllfile) {
-            strcpy(message, "Cannot find DLL in "); strcat(message, dllfile);
+        /* this finds the name of the python library that would be loaded by `application` if run */
+        const char *realpythondllfile = GetPythonImport(mainDll);
+        if (!realpythondllfile) {
+            strncpy_s(message, sizeof message, cannot_find_dll_in, sizeof cannot_find_dll_in);
+            strcat_s(message, sizeof message, requestedapplication);
             goto error;
         }
-        /* try loading the DLL file from the EXE file's directory */
-        i = finddir(dllfile);
-        dllfile[i++] = '\\';
-        strcpy(dllfile + i, realdllfile);
-        dll = LoadLibraryEx(
-            dllfile, NULL, LOAD_WITH_ALTERED_SEARCH_PATH
+        {
+            char loadPythonDll[512];
+            /* try loading the DLL file from the main EXE file's directory */
+            strncpy_s(loadPythonDll, sizeof loadPythonDll, workingdir, sizeof workingdir);
+            strcat_s(loadPythonDll, sizeof loadPythonDll, "\\");
+            strcat_s(loadPythonDll, sizeof loadPythonDll, realpythondllfile);
+            /*** try loading the python dll found near `application` using the path from `workingdir` */
+            pythonDll = LoadLibraryEx(
+                workingdir, NULL, LOAD_WITH_ALTERED_SEARCH_PATH
             );
-        if (!dll)
+        }
+        if (!pythonDll) {
+            DWORD pos;
+            char loadPythonDll[512];
             /* if that doesn't work, search for the DLL */
-            dll = LoadLibraryEx(
-                realdllfile, NULL, LOAD_WITH_ALTERED_SEARCH_PATH
+            pos = finddir(application);
+            strncpy_s(loadPythonDll, sizeof loadPythonDll, application, pos);
+            loadPythonDll[pos] = 0;
+            strcat_s(loadPythonDll, sizeof loadPythonDll, "\\");
+            strcat_s(loadPythonDll, sizeof loadPythonDll, realpythondllfile);
+            /*** try loading the python dll found near `application` using the path for `application` */
+            pythonDll = LoadLibraryEx(
+                loadPythonDll, NULL, LOAD_WITH_ALTERED_SEARCH_PATH
                 );
-        if (!dll) {
-            strcpy(message, "Cannot find "); strcat(message, realdllfile);
+        }
+        if (!pythonDll) {
+            strncpy_s(message, sizeof message, cannot_find, sizeof cannot_find);
+            strcat_s(message, sizeof message, realpythondllfile);
             goto error;
         }
+        FreeLibrary(mainDll);
+        mainDll = pythonDll;
     }
 
     /* get entry points */
-    Py_Main = (void*) GetProcAddress(dll, "Py_Main");
+    Py_Main = (void*) GetProcAddress(mainDll, "Py_Main");
     if (!Py_Main)
         ExitProcess(1);
 
     /* get paths */
-    GetModuleFileName(dll, dllfile, sizeof(dllfile));
-    GetModuleFileName(dll, exefile, sizeof(exefile));
+    GetModuleFileName(mainDll, requestedapplication, sizeof(requestedapplication));
+    GetModuleFileName(mainDll, exefile, sizeof(exefile));
 
     /* check if we have a Python library relative to the DLL home */
-    i = finddir(dllfile);
-    strcpy(dllfile + i, "\\lib\\os.py");
+    i = finddir(requestedapplication);
+    strncpy_s(requestedapplication + i, sizeof requestedapplication - i, lib_os_py, sizeof lib_os_py);
 
-    file = CreateFile(dllfile, GENERIC_READ, FILE_SHARE_READ, NULL,
-                      OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+    {
+        HANDLE ospy = CreateFile(requestedapplication, GENERIC_READ, FILE_SHARE_READ, NULL,
+                                 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
 
-    if (file != (HANDLE) -1) {
-        /* lib/os.py exists; set PYTHONHOME to the DLL directory */
-        Py_SetPythonHome = (void*) GetProcAddress(dll, "Py_SetPythonHome");
-        if (Py_SetPythonHome) {
-            dllfile[i] = '\0';
-            Py_SetPythonHome(dllfile); /* SetPythonHome keeps a reference! */
+        if (ospy != (HANDLE) -1) {
+            /* lib/os.py exists; set PYTHONHOME to the DLL directory */
+            Py_SetPythonHome = (void*) GetProcAddress(mainDll, "Py_SetPythonHome");
+            if (Py_SetPythonHome) {
+                requestedapplication[i] = '\0';
+                Py_SetPythonHome(requestedapplication); /* SetPythonHome keeps a reference! */
+            }
+            CloseHandle(ospy);
         }
-        CloseHandle(file);
     }
 
     /* zap environment variables (is this necessary?) */