sdl

FORK: Simple Directmedia Layer
git clone https://git.neptards.moe/neptards/sdl.git
Log | Files | Refs

windows_process.c (6631B)


      1 /* See COPYING.txt for the full license governing this code. */
      2 /**
      3  * \file windows_process.c 
      4  *
      5  * Source file for the process API on windows.
      6  */
      7 
      8 
      9 #include <SDL.h>
     10 #include <SDL_test.h>
     11 #include <string.h>
     12 #include <stdlib.h>
     13 
     14 #include "SDL_visualtest_process.h"
     15 
     16 #if defined(__WIN32__)
     17 
     18 void
     19 LogLastError(char* str)
     20 {
     21     LPVOID buffer;
     22     DWORD dw = GetLastError();
     23     FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|
     24                     FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dw,
     25                     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&buffer,
     26                     0, NULL);
     27     SDLTest_LogError("%s: %s", str, (char*)buffer);
     28     LocalFree(buffer);
     29 }
     30 
     31 int
     32 SDL_LaunchProcess(char* file, char* args, SDL_ProcessInfo* pinfo)
     33 {
     34     BOOL success;
     35     char* working_directory;
     36     char* command_line;
     37     int path_length, args_length;
     38     STARTUPINFO sui = {0};
     39     sui.cb = sizeof(sui);
     40 
     41     if(!file)
     42     {
     43         SDLTest_LogError("Path to executable to launched cannot be NULL.");
     44         return 0;
     45     }
     46     if(!pinfo)
     47     {
     48         SDLTest_LogError("pinfo cannot be NULL.");
     49         return 0;
     50     }
     51 
     52     /* get the working directory of the process being launched, so that
     53         the process can load any resources it has in it's working directory */
     54     path_length = SDL_strlen(file);
     55     if(path_length == 0)
     56     {
     57         SDLTest_LogError("Length of the file parameter is zero.");
     58         return 0;
     59     }
     60 
     61     working_directory = (char*)SDL_malloc(path_length + 1);
     62     if(!working_directory)
     63     {
     64         SDLTest_LogError("Could not allocate working_directory - malloc() failed.");
     65         return 0;
     66     }
     67 
     68     SDL_memcpy(working_directory, file, path_length + 1);
     69     PathRemoveFileSpec(working_directory);
     70     if(SDL_strlen(working_directory) == 0)
     71     {
     72         SDL_free(working_directory);
     73         working_directory = NULL;
     74     }
     75 
     76     /* join the file path and the args string together */
     77     if(!args)
     78         args = "";
     79     args_length = SDL_strlen(args);
     80     command_line = (char*)SDL_malloc(path_length + args_length + 2);
     81     if(!command_line)
     82     {
     83         SDLTest_LogError("Could not allocate command_line - malloc() failed.");
     84         return 0;
     85     }
     86     SDL_memcpy(command_line, file, path_length);
     87     command_line[path_length] = ' ';
     88     SDL_memcpy(command_line + path_length + 1, args, args_length + 1);
     89 
     90     /* create the process */
     91     success = CreateProcess(NULL, command_line, NULL, NULL, FALSE,
     92                             NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW,
     93                             NULL, working_directory, &sui, &pinfo->pi);
     94     if(working_directory)
     95     {
     96         SDL_free(working_directory);
     97         working_directory = NULL;
     98     }
     99     SDL_free(command_line);
    100     if(!success)
    101     {
    102         LogLastError("CreateProcess() failed");
    103         return 0;
    104     }
    105 
    106     return 1;
    107 }
    108 
    109 int
    110 SDL_GetProcessExitStatus(SDL_ProcessInfo* pinfo, SDL_ProcessExitStatus* ps)
    111 {
    112     DWORD exit_status;
    113     BOOL success;
    114 
    115     if(!pinfo)
    116     {
    117         SDLTest_LogError("pinfo cannot be NULL");
    118         return 0;
    119     }
    120     if(!ps)
    121     {
    122         SDLTest_LogError("ps cannot be NULL");
    123         return 0;
    124     }
    125 
    126     /* get the exit code */
    127     success = GetExitCodeProcess(pinfo->pi.hProcess, &exit_status);
    128     if(!success)
    129     {
    130         LogLastError("GetExitCodeProcess() failed");
    131         return 0;
    132     }
    133 
    134     if(exit_status == STILL_ACTIVE)
    135         ps->exit_status = -1;
    136     else
    137         ps->exit_status = exit_status;
    138     ps->exit_success = 1;
    139     return 1;
    140 }
    141 
    142 
    143 int
    144 SDL_IsProcessRunning(SDL_ProcessInfo* pinfo)
    145 {
    146     DWORD exit_status;
    147     BOOL success;
    148 
    149     if(!pinfo)
    150     {
    151         SDLTest_LogError("pinfo cannot be NULL");
    152         return -1;
    153     }
    154 
    155     success = GetExitCodeProcess(pinfo->pi.hProcess, &exit_status);
    156     if(!success)
    157     {
    158         LogLastError("GetExitCodeProcess() failed");
    159         return -1;
    160     }
    161     
    162     if(exit_status == STILL_ACTIVE)
    163         return 1;
    164     return 0;
    165 }
    166 
    167 static BOOL CALLBACK
    168 CloseWindowCallback(HWND hwnd, LPARAM lparam)
    169 {
    170     DWORD pid;
    171     SDL_ProcessInfo* pinfo;
    172 
    173     pinfo = (SDL_ProcessInfo*)lparam;
    174 
    175     GetWindowThreadProcessId(hwnd, &pid);
    176     if(pid == pinfo->pi.dwProcessId)
    177     {
    178         DWORD result;
    179         if(!SendMessageTimeout(hwnd, WM_CLOSE, 0, 0, SMTO_BLOCK,
    180                                1000, &result))
    181         {
    182             if(GetLastError() != ERROR_TIMEOUT)
    183             {
    184                 LogLastError("SendMessageTimeout() failed");
    185                 return FALSE;
    186             }
    187         }
    188     }
    189     return TRUE;
    190 }
    191 
    192 int
    193 SDL_QuitProcess(SDL_ProcessInfo* pinfo, SDL_ProcessExitStatus* ps)
    194 {
    195     DWORD wait_result;
    196     if(!pinfo)
    197     {
    198         SDLTest_LogError("pinfo argument cannot be NULL");
    199         return 0;
    200     }
    201     if(!ps)
    202     {
    203         SDLTest_LogError("ps argument cannot be NULL");
    204         return 0;
    205     }
    206 
    207     /* enumerate through all the windows, trying to close each one */
    208     if(!EnumWindows(CloseWindowCallback, (LPARAM)pinfo))
    209     {
    210         SDLTest_LogError("EnumWindows() failed");
    211         return 0;
    212     }
    213 
    214     /* wait until the process terminates */
    215     wait_result = WaitForSingleObject(pinfo->pi.hProcess, 1000);
    216     if(wait_result == WAIT_FAILED)
    217     {
    218         LogLastError("WaitForSingleObject() failed");
    219         return 0;
    220     }
    221     if(wait_result != WAIT_OBJECT_0)
    222     {
    223         SDLTest_LogError("Process did not quit.");
    224         return 0;
    225     }
    226 
    227     /* get the exit code */
    228     if(!SDL_GetProcessExitStatus(pinfo, ps))
    229     {
    230         SDLTest_LogError("SDL_GetProcessExitStatus() failed");
    231         return 0;
    232     }
    233 
    234     return 1;
    235 }
    236 
    237 int
    238 SDL_KillProcess(SDL_ProcessInfo* pinfo, SDL_ProcessExitStatus* ps)
    239 {
    240     BOOL success;
    241     DWORD exit_status, wait_result;
    242 
    243     if(!pinfo)
    244     {
    245         SDLTest_LogError("pinfo argument cannot be NULL");
    246         return 0;
    247     }
    248     if(!ps)
    249     {
    250         SDLTest_LogError("ps argument cannot be NULL");
    251         return 0;
    252     }
    253 
    254     /* initiate termination of the process */
    255     success = TerminateProcess(pinfo->pi.hProcess, 0);
    256     if(!success)
    257     {
    258         LogLastError("TerminateProcess() failed");
    259         return 0;
    260     }
    261 
    262     /* wait until the process terminates */
    263     wait_result = WaitForSingleObject(pinfo->pi.hProcess, INFINITE);
    264     if(wait_result == WAIT_FAILED)
    265     {
    266         LogLastError("WaitForSingleObject() failed");
    267         return 0;
    268     }
    269 
    270     /* get the exit code */
    271     success = GetExitCodeProcess(pinfo->pi.hProcess, &exit_status);
    272     if(!success)
    273     {
    274         LogLastError("GetExitCodeProcess() failed");
    275         return 0;
    276     }
    277 
    278     ps->exit_status = exit_status;
    279     ps->exit_success = 1;
    280 
    281     return 1;
    282 }
    283 
    284 #endif