ProcessWin32.c 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407
  1. /*=========================================================================
  2. Program: KWSys - Kitware System Library
  3. Module: $RCSfile$
  4. Language: C++
  5. Date: $Date$
  6. Version: $Revision$
  7. Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
  8. See http://www.cmake.org/HTML/Copyright.html for details.
  9. This software is distributed WITHOUT ANY WARRANTY; without even
  10. the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  11. PURPOSE. See the above copyright notices for more information.
  12. =========================================================================*/
  13. #define KWSYS_IN_PROCESS_C
  14. #include <Process.h>
  15. /*
  16. Implementation for Windows
  17. On windows, a thread is created to wait for data on each pipe. The
  18. threads are synchronized with the main thread to simulate the use of
  19. a UNIX-style select system call.
  20. On Windows9x platforms, a small WIN32 console application is spawned
  21. in-between the calling process and the actual child to be executed.
  22. This is to work-around a problem with connecting pipes from WIN16
  23. console applications to WIN32 applications.
  24. For more information, please check Microsoft Knowledge Base Articles
  25. Q190351 and Q150956.
  26. */
  27. #ifdef _MSC_VER
  28. #pragma warning (push, 1)
  29. #endif
  30. #include <windows.h> /* Windows API */
  31. #include <string.h> /* strlen, strdup */
  32. #include <stdio.h> /* sprintf */
  33. #include <io.h> /* _unlink */
  34. #ifdef _MSC_VER
  35. #pragma warning (pop)
  36. #pragma warning (disable: 4514)
  37. #pragma warning (disable: 4706)
  38. #endif
  39. /* The number of pipes for the child's output. The standard stdout
  40. and stderr pipes are the first two. One more pipe is used on Win9x
  41. for the forwarding executable to use in reporting problems. */
  42. #define CMPE_PIPE_COUNT 3
  43. #define CMPE_PIPE_STDOUT 0
  44. #define CMPE_PIPE_STDERR 1
  45. #define CMPE_PIPE_ERROR 2
  46. /* The maximum amount to read from a pipe at a time. */
  47. #define CMPE_PIPE_BUFFER_SIZE 1024
  48. #define kwsysEncodedWriteArrayProcessFwd9x kwsys(EncodedWriteArrayProcessFwd9x)
  49. typedef LARGE_INTEGER kwsysProcessTime;
  50. /*--------------------------------------------------------------------------*/
  51. typedef struct kwsysProcessPipeData_s kwsysProcessPipeData;
  52. static DWORD WINAPI kwsysProcessPipeThread(LPVOID ptd);
  53. static void kwsysProcessPipeThreadReadPipe(kwsysProcess* cp, kwsysProcessPipeData* td);
  54. static void kwsysProcessCleanupHandle(PHANDLE h);
  55. static void kwsysProcessCleanup(kwsysProcess* cp, int error);
  56. static int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout,
  57. kwsysProcessTime* timeoutTime);
  58. static int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime,
  59. kwsysProcessTime* timeoutLength);
  60. static kwsysProcessTime kwsysProcessTimeGetCurrent();
  61. static DWORD kwsysProcessTimeToDWORD(kwsysProcessTime t);
  62. static double kwsysProcessTimeToDouble(kwsysProcessTime t);
  63. static kwsysProcessTime kwsysProcessTimeFromDouble(double d);
  64. static int kwsysProcessTimeLess(kwsysProcessTime in1, kwsysProcessTime in2);
  65. static kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1, kwsysProcessTime in2);
  66. static kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProcessTime in2);
  67. extern kwsysEXPORT int kwsysEncodedWriteArrayProcessFwd9x(const char* fname);
  68. /*--------------------------------------------------------------------------*/
  69. /* A structure containing data for each pipe's thread. */
  70. struct kwsysProcessPipeData_s
  71. {
  72. /* ------------- Data managed per instance of kwsysProcess ------------- */
  73. /* Handle for the thread for this pipe. */
  74. HANDLE Thread;
  75. /* Semaphore indicating a process and pipe are available. */
  76. HANDLE Ready;
  77. /* Semaphore indicating when this thread's buffer is empty. */
  78. HANDLE Empty;
  79. /* Semaphore indicating a pipe thread has reset for another process. */
  80. HANDLE Reset;
  81. /* Index of this pipe. */
  82. int Index;
  83. /* The kwsysProcess instance owning this pipe. */
  84. kwsysProcess* Process;
  85. /* ------------- Data managed per call to Execute ------------- */
  86. /* Buffer for data read in this pipe's thread. */
  87. char DataBuffer[CMPE_PIPE_BUFFER_SIZE];
  88. /* The length of the data stored in the buffer. */
  89. DWORD DataLength;
  90. /* Whether the pipe has been closed. */
  91. int Closed;
  92. /* Handle for the read end of this pipe. */
  93. HANDLE Read;
  94. /* Handle for the write end of this pipe. */
  95. HANDLE Write;
  96. };
  97. /*--------------------------------------------------------------------------*/
  98. /* Structure containing data used to implement the child's execution. */
  99. struct kwsysProcess_s
  100. {
  101. /* ------------- Data managed per instance of kwsysProcess ------------- */
  102. /* The status of the process. */
  103. int State;
  104. /* The command line to execute. */
  105. char* Command;
  106. /* The working directory for the child process. */
  107. char* WorkingDirectory;
  108. /* On Win9x platforms, the path to the forwarding executable. */
  109. char* Win9x;
  110. /* On Win9x platforms, the kill event for the forwarding executable. */
  111. HANDLE Win9xKillEvent;
  112. /* Mutex to protect the shared index used by threads to report data. */
  113. HANDLE SharedIndexMutex;
  114. /* Semaphore used by threads to signal data ready. */
  115. HANDLE Full;
  116. /* The number of pipes needed to implement the child's execution.
  117. This is 3 on Win9x and 2 otherwise. */
  118. int PipeCount;
  119. /* Whether we are currently deleting this kwsysProcess instance. */
  120. int Deleting;
  121. /* Data specific to each pipe and its thread. */
  122. kwsysProcessPipeData Pipe[CMPE_PIPE_COUNT];
  123. /* ------------- Data managed per call to Execute ------------- */
  124. /* The exceptional behavior that terminated the process, if any. */
  125. int ExitException;
  126. /* The process exit code. */
  127. DWORD ExitCode;
  128. /* The process return code, if any. */
  129. int ExitValue;
  130. /* Index of last pipe to report data, if any. */
  131. int CurrentIndex;
  132. /* Index shared by threads to report data. */
  133. int SharedIndex;
  134. /* The timeout length. */
  135. double Timeout;
  136. /* Time at which the child started. */
  137. kwsysProcessTime StartTime;
  138. /* Time at which the child will timeout. Negative for no timeout. */
  139. kwsysProcessTime TimeoutTime;
  140. /* Flag for whether the process was killed. */
  141. int Killed;
  142. /* Flag for whether the timeout expired. */
  143. int TimeoutExpired;
  144. /* Flag for whether the process has terminated. */
  145. int Terminated;
  146. /* The number of pipes still open during execution and while waiting
  147. for pipes to close after process termination. */
  148. int PipesLeft;
  149. /* Buffer for error messages (possibly from Win9x child). */
  150. char ErrorMessage[CMPE_PIPE_BUFFER_SIZE+1];
  151. int ErrorMessageLength;
  152. /* The actual command line that will be used to create the process. */
  153. char* RealCommand;
  154. /* Windows process information data. */
  155. PROCESS_INFORMATION ProcessInformation;
  156. };
  157. /*--------------------------------------------------------------------------*/
  158. kwsysProcess* kwsysProcess_New()
  159. {
  160. int i;
  161. /* Process control structure. */
  162. kwsysProcess* cp;
  163. /* Path to Win9x forwarding executable. */
  164. char* win9x = 0;
  165. /* Windows version number data. */
  166. OSVERSIONINFO osv;
  167. /* Allocate a process control structure. */
  168. cp = (kwsysProcess*)malloc(sizeof(kwsysProcess));
  169. if(!cp)
  170. {
  171. /* Could not allocate memory for the control structure. */
  172. return 0;
  173. }
  174. ZeroMemory(cp, sizeof(*cp));
  175. /* Set initial status. */
  176. cp->State = kwsysProcess_State_Starting;
  177. /* Choose a method of running the child based on version of
  178. windows. */
  179. ZeroMemory(&osv, sizeof(osv));
  180. osv.dwOSVersionInfoSize = sizeof(osv);
  181. GetVersionEx(&osv);
  182. if(osv.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
  183. {
  184. /* This is Win9x. We need the console forwarding executable to
  185. work-around a Windows 9x bug. */
  186. char fwdName[_MAX_FNAME+1] = "";
  187. char tempDir[_MAX_PATH+1] = "";
  188. /* We will try putting the executable in the system temp
  189. directory. Note that the returned path already has a trailing
  190. slash. */
  191. DWORD length = GetTempPath(_MAX_PATH+1, tempDir);
  192. /* Construct the executable name from the process id and kwsysProcess
  193. instance. This should be unique. */
  194. sprintf(fwdName, "cmw9xfwd_%u_%p.exe", GetCurrentProcessId(), cp);
  195. /* If we have a temp directory, use it. */
  196. if(length > 0 && length <= _MAX_PATH)
  197. {
  198. /* Allocate a buffer to hold the forwarding executable path. */
  199. size_t tdlen = strlen(tempDir);
  200. win9x = (char*)malloc(tdlen + strlen(fwdName) + 2);
  201. if(!win9x)
  202. {
  203. kwsysProcess_Delete(cp);
  204. return 0;
  205. }
  206. /* Construct the full path to the forwarding executable. */
  207. sprintf(win9x, "%s%s", tempDir, fwdName);
  208. }
  209. /* If we found a place to put the forwarding executable, try to
  210. write it. */
  211. if(win9x)
  212. {
  213. if(!kwsysEncodedWriteArrayProcessFwd9x(win9x))
  214. {
  215. /* Failed to create forwarding executable. Give up. */
  216. free(win9x);
  217. kwsysProcess_Delete(cp);
  218. return 0;
  219. }
  220. }
  221. else
  222. {
  223. /* Failed to find a place to put forwarding executable. */
  224. kwsysProcess_Delete(cp);
  225. return 0;
  226. }
  227. }
  228. /* We need the extra error pipe on Win9x. */
  229. cp->Win9x = win9x;
  230. cp->PipeCount = cp->Win9x? 3:2;
  231. /* Initially no thread owns the mutex. Initialize semaphore to 1. */
  232. if(!(cp->SharedIndexMutex = CreateSemaphore(0, 1, 1, 0)))
  233. {
  234. kwsysProcess_Delete(cp);
  235. return 0;
  236. }
  237. /* Initially no data are available. Initialize semaphore to 0. */
  238. if(!(cp->Full = CreateSemaphore(0, 0, 1, 0)))
  239. {
  240. kwsysProcess_Delete(cp);
  241. return 0;
  242. }
  243. if(cp->Win9x)
  244. {
  245. /* Create an event to tell the forwarding executable to kill the
  246. child. */
  247. SECURITY_ATTRIBUTES sa;
  248. ZeroMemory(&sa, sizeof(sa));
  249. sa.nLength = sizeof(sa);
  250. sa.bInheritHandle = TRUE;
  251. if(!(cp->Win9xKillEvent = CreateEvent(&sa, TRUE, 0, 0)))
  252. {
  253. kwsysProcess_Delete(cp);
  254. return 0;
  255. }
  256. }
  257. /* Create the thread to read each pipe. */
  258. for(i=0; i < cp->PipeCount; ++i)
  259. {
  260. DWORD dummy=0;
  261. /* Assign the thread its index. */
  262. cp->Pipe[i].Index = i;
  263. /* Give the thread a pointer back to the kwsysProcess instance. */
  264. cp->Pipe[i].Process = cp;
  265. /* The pipe is not yet ready to read. Initialize semaphore to 0. */
  266. if(!(cp->Pipe[i].Ready = CreateSemaphore(0, 0, 1, 0)))
  267. {
  268. kwsysProcess_Delete(cp);
  269. return 0;
  270. }
  271. /* The pipe is not yet reset. Initialize semaphore to 0. */
  272. if(!(cp->Pipe[i].Reset = CreateSemaphore(0, 0, 1, 0)))
  273. {
  274. kwsysProcess_Delete(cp);
  275. return 0;
  276. }
  277. /* The thread's buffer is initially empty. Initialize semaphore to 1. */
  278. if(!(cp->Pipe[i].Empty = CreateSemaphore(0, 1, 1, 0)))
  279. {
  280. kwsysProcess_Delete(cp);
  281. return 0;
  282. }
  283. /* Create the thread. It will block immediately. The thread will
  284. not make deeply nested calls, so we need only a small
  285. stack. */
  286. if(!(cp->Pipe[i].Thread = CreateThread(0, 1024, kwsysProcessPipeThread,
  287. &cp->Pipe[i], 0, &dummy)))
  288. {
  289. kwsysProcess_Delete(cp);
  290. return 0;
  291. }
  292. }
  293. return cp;
  294. }
  295. /*--------------------------------------------------------------------------*/
  296. void kwsysProcess_Delete(kwsysProcess* cp)
  297. {
  298. int i;
  299. /* If the process is executing, wait for it to finish. */
  300. if(cp->State == kwsysProcess_State_Executing)
  301. {
  302. kwsysProcess_WaitForExit(cp, 0);
  303. }
  304. /* We are deleting the kwsysProcess instance. */
  305. cp->Deleting = 1;
  306. /* Terminate each of the threads. */
  307. for(i=0; i < cp->PipeCount; ++i)
  308. {
  309. if(cp->Pipe[i].Thread)
  310. {
  311. /* Signal the thread we are ready for it. It will terminate
  312. immediately since Deleting is set. */
  313. ReleaseSemaphore(cp->Pipe[i].Ready, 1, 0);
  314. /* Wait for the thread to exit. */
  315. WaitForSingleObject(cp->Pipe[i].Thread, INFINITE);
  316. /* Close the handle to the thread. */
  317. kwsysProcessCleanupHandle(&cp->Pipe[i].Thread);
  318. }
  319. /* Cleanup the pipe's semaphores. */
  320. kwsysProcessCleanupHandle(&cp->Pipe[i].Ready);
  321. kwsysProcessCleanupHandle(&cp->Pipe[i].Empty);
  322. }
  323. /* Close the shared semaphores. */
  324. kwsysProcessCleanupHandle(&cp->SharedIndexMutex);
  325. kwsysProcessCleanupHandle(&cp->Full);
  326. /* Close the Win9x kill event handle. */
  327. if(cp->Win9x)
  328. {
  329. kwsysProcessCleanupHandle(&cp->Win9xKillEvent);
  330. }
  331. /* Free memory. */
  332. kwsysProcess_SetCommand(cp, 0);
  333. kwsysProcess_SetWorkingDirectory(cp, 0);
  334. if(cp->Win9x)
  335. {
  336. _unlink(cp->Win9x);
  337. free(cp->Win9x);
  338. }
  339. free(cp);
  340. }
  341. /*--------------------------------------------------------------------------*/
  342. void kwsysProcess_SetCommand(kwsysProcess* cp, char const* const* command)
  343. {
  344. if(cp->Command)
  345. {
  346. free(cp->Command);
  347. cp->Command = 0;
  348. }
  349. if(command)
  350. {
  351. /* We need to construct a single string representing the command
  352. and its arguments. We will surround each argument containing
  353. spaces with double-quotes. Inside a double-quoted argument, we
  354. need to escape double-quotes and all backslashes before them.
  355. We also need to escape backslashes at the end of an argument
  356. because they come before the closing double-quote for the
  357. argument. */
  358. char* cmd;
  359. char const* const* arg;
  360. int length = 0;
  361. /* First determine the length of the final string. */
  362. for(arg = command; *arg; ++arg)
  363. {
  364. /* Keep track of how many backslashes have been encountered in a
  365. row in this argument. */
  366. int backslashes = 0;
  367. int spaces = 0;
  368. const char* c;
  369. /* Scan the string for spaces. If there are no spaces, we can
  370. pass the argument verbatim. */
  371. for(c=*arg; *c; ++c)
  372. {
  373. if(*c == ' ' || *c == '\t')
  374. {
  375. spaces = 1;
  376. break;
  377. }
  378. }
  379. /* Add the length of the argument, plus 1 for the space
  380. separating the arguments. */
  381. length += (int)strlen(*arg) + 1;
  382. if(spaces)
  383. {
  384. /* Add 2 for double quotes since spaces are present. */
  385. length += 2;
  386. /* Scan the string to find characters that need escaping. */
  387. for(c=*arg; *c; ++c)
  388. {
  389. if(*c == '\\')
  390. {
  391. /* Found a backslash. It may need to be escaped later. */
  392. ++backslashes;
  393. }
  394. else if(*c == '"')
  395. {
  396. /* Found a double-quote. We need to escape it and all
  397. immediately preceding backslashes. */
  398. length += backslashes + 1;
  399. backslashes = 0;
  400. }
  401. else
  402. {
  403. /* Found another character. This eliminates the possibility
  404. that any immediately preceding backslashes will be
  405. escaped. */
  406. backslashes = 0;
  407. }
  408. }
  409. /* We need to escape all ending backslashes. */
  410. length += backslashes;
  411. }
  412. }
  413. /* Allocate enough space for the command. We do not need an extra
  414. byte for the terminating null because we allocated a space for
  415. the first argument that we will not use. */
  416. cp->Command = (char*)malloc(length);
  417. /* Construct the command line in the allocated buffer. */
  418. cmd = cp->Command;
  419. for(arg = command; *arg; ++arg)
  420. {
  421. /* Keep track of how many backslashes have been encountered in a
  422. row in an argument. */
  423. int backslashes = 0;
  424. int spaces = 0;
  425. const char* c;
  426. /* Scan the string for spaces. If there are no spaces, we can
  427. pass the argument verbatim. */
  428. for(c=*arg; *c; ++c)
  429. {
  430. if(*c == ' ' || *c == '\t')
  431. {
  432. spaces = 1;
  433. break;
  434. }
  435. }
  436. /* Add the separating space if this is not the first argument. */
  437. if(arg != command)
  438. {
  439. *cmd++ = ' ';
  440. }
  441. if(spaces)
  442. {
  443. /* Add the opening double-quote for this argument. */
  444. *cmd++ = '"';
  445. /* Add the characters of the argument, possibly escaping them. */
  446. for(c=*arg; *c; ++c)
  447. {
  448. if(*c == '\\')
  449. {
  450. /* Found a backslash. It may need to be escaped later. */
  451. ++backslashes;
  452. *cmd++ = '\\';
  453. }
  454. else if(*c == '"')
  455. {
  456. /* Add enough backslashes to escape any that preceded the
  457. double-quote. */
  458. while(backslashes > 0)
  459. {
  460. --backslashes;
  461. *cmd++ = '\\';
  462. }
  463. /* Add the backslash to escape the double-quote. */
  464. *cmd++ = '\\';
  465. /* Add the double-quote itself. */
  466. *cmd++ = '"';
  467. }
  468. else
  469. {
  470. /* We encountered a normal character. This eliminates any
  471. escaping needed for preceding backslashes. Add the
  472. character. */
  473. backslashes = 0;
  474. *cmd++ = *c;
  475. }
  476. }
  477. /* Add enough backslashes to escape any trailing ones. */
  478. while(backslashes > 0)
  479. {
  480. --backslashes;
  481. *cmd++ = '\\';
  482. }
  483. /* Add the closing double-quote for this argument. */
  484. *cmd++ = '"';
  485. }
  486. else
  487. {
  488. /* No spaces. Add the argument verbatim. */
  489. for(c=*arg; *c; ++c)
  490. {
  491. *cmd++ = *c;
  492. }
  493. }
  494. }
  495. /* Add the terminating null character to the command line. */
  496. *cmd = 0;
  497. }
  498. }
  499. /*--------------------------------------------------------------------------*/
  500. void kwsysProcess_SetTimeout(kwsysProcess* cp, double timeout)
  501. {
  502. cp->Timeout = timeout;
  503. }
  504. /*--------------------------------------------------------------------------*/
  505. void kwsysProcess_SetWorkingDirectory(kwsysProcess* cp, const char* dir)
  506. {
  507. if(cp->WorkingDirectory)
  508. {
  509. free(cp->WorkingDirectory);
  510. cp->WorkingDirectory = 0;
  511. }
  512. if(dir && dir[0])
  513. {
  514. /* We must convert the working directory to a full path. */
  515. DWORD length = GetFullPathName(dir, 0, 0, 0);
  516. if(length > 0)
  517. {
  518. cp->WorkingDirectory = (char*)malloc(length);
  519. if(!GetFullPathName(dir, length, cp->WorkingDirectory, 0))
  520. {
  521. free(cp->WorkingDirectory);
  522. cp->WorkingDirectory = 0;
  523. }
  524. }
  525. }
  526. }
  527. /*--------------------------------------------------------------------------*/
  528. int kwsysProcess_GetState(kwsysProcess* cp)
  529. {
  530. return cp->State;
  531. }
  532. /*--------------------------------------------------------------------------*/
  533. int kwsysProcess_GetExitException(kwsysProcess* cp)
  534. {
  535. return cp->ExitException;
  536. }
  537. /*--------------------------------------------------------------------------*/
  538. int kwsysProcess_GetExitValue(kwsysProcess* cp)
  539. {
  540. return cp->ExitValue;
  541. }
  542. /*--------------------------------------------------------------------------*/
  543. int kwsysProcess_GetExitCode(kwsysProcess* cp)
  544. {
  545. return cp->ExitCode;
  546. }
  547. /*--------------------------------------------------------------------------*/
  548. const char* kwsysProcess_GetErrorString(kwsysProcess* cp)
  549. {
  550. if(cp->State == kwsysProcess_State_Error)
  551. {
  552. return cp->ErrorMessage;
  553. }
  554. return 0;
  555. }
  556. /*--------------------------------------------------------------------------*/
  557. void kwsysProcess_Execute(kwsysProcess* cp)
  558. {
  559. int i=0;
  560. /* Windows child startup control data. */
  561. STARTUPINFO si;
  562. /* Do not execute a second time. */
  563. if(cp->State == kwsysProcess_State_Executing)
  564. {
  565. return;
  566. }
  567. /* Initialize startup info data. */
  568. ZeroMemory(&si, sizeof(si));
  569. si.cb = sizeof(si);
  570. /* Reset internal status flags. */
  571. cp->TimeoutExpired = 0;
  572. cp->Terminated = 0;
  573. cp->Killed = 0;
  574. cp->ExitException = kwsysProcess_Exception_None;
  575. cp->ExitCode = 1;
  576. cp->ExitValue = 1;
  577. /* Reset error data. */
  578. cp->ErrorMessage[0] = 0;
  579. cp->ErrorMessageLength = 0;
  580. /* Reset the Win9x kill event. */
  581. if(cp->Win9x)
  582. {
  583. if(!ResetEvent(cp->Win9xKillEvent))
  584. {
  585. kwsysProcessCleanup(cp, 1);
  586. return;
  587. }
  588. }
  589. /* Create a pipe for each child output. */
  590. for(i=0; i < cp->PipeCount; ++i)
  591. {
  592. HANDLE writeEnd;
  593. /* The pipe is not closed. */
  594. cp->Pipe[i].Closed = 0;
  595. /* Create the pipe. Neither end is directly inherited. */
  596. if(!CreatePipe(&cp->Pipe[i].Read, &writeEnd, 0, 0))
  597. {
  598. kwsysProcessCleanup(cp, 1);
  599. return;
  600. }
  601. /* Create an inherited duplicate of the write end. This also closes
  602. the non-inherited version. */
  603. if(!DuplicateHandle(GetCurrentProcess(), writeEnd,
  604. GetCurrentProcess(), &cp->Pipe[i].Write,
  605. 0, TRUE, (DUPLICATE_CLOSE_SOURCE |
  606. DUPLICATE_SAME_ACCESS)))
  607. {
  608. kwsysProcessCleanup(cp, 1);
  609. CloseHandle(writeEnd);
  610. return;
  611. }
  612. }
  613. /* Construct the real command line. */
  614. if(cp->Win9x)
  615. {
  616. /* Windows 9x */
  617. /* The forwarding executable is given a handle to the error pipe
  618. and a handle to the kill event. */
  619. cp->RealCommand = malloc(strlen(cp->Win9x)+strlen(cp->Command)+100);
  620. sprintf(cp->RealCommand, "%s %p %p %s", cp->Win9x,
  621. cp->Pipe[CMPE_PIPE_ERROR].Write,
  622. cp->Win9xKillEvent, cp->Command);
  623. }
  624. else
  625. {
  626. /* Not Windows 9x */
  627. cp->RealCommand = strdup(cp->Command);
  628. }
  629. /* Connect the child's output pipes to the threads. */
  630. si.dwFlags = STARTF_USESTDHANDLES;
  631. si.hStdOutput = cp->Pipe[CMPE_PIPE_STDOUT].Write;
  632. si.hStdError = cp->Pipe[CMPE_PIPE_STDERR].Write;
  633. /* Hide the forwarding executable console on Windows 9x. */
  634. si.dwFlags |= STARTF_USESHOWWINDOW;
  635. if(cp->Win9x)
  636. {
  637. si.wShowWindow = SW_HIDE;
  638. }
  639. else
  640. {
  641. si.wShowWindow = SW_SHOWDEFAULT;
  642. }
  643. /* The timeout period starts now. */
  644. cp->StartTime = kwsysProcessTimeGetCurrent();
  645. cp->TimeoutTime = kwsysProcessTimeFromDouble(-1);
  646. /* CREATE THE CHILD PROCESS */
  647. if(!CreateProcess(0, cp->RealCommand, 0, 0, TRUE,
  648. cp->Win9x? CREATE_NEW_CONSOLE:DETACHED_PROCESS, 0,
  649. cp->WorkingDirectory, &si, &cp->ProcessInformation))
  650. {
  651. kwsysProcessCleanup(cp, 1);
  652. return;
  653. }
  654. /* ---- It is no longer safe to call kwsysProcessCleanup. ----- */
  655. /* Tell the pipe threads that a process has started. */
  656. for(i=0; i < cp->PipeCount; ++i)
  657. {
  658. ReleaseSemaphore(cp->Pipe[i].Ready, 1, 0);
  659. }
  660. /* We don't care about the child's main thread. */
  661. kwsysProcessCleanupHandle(&cp->ProcessInformation.hThread);
  662. /* No pipe has reported data. */
  663. cp->CurrentIndex = CMPE_PIPE_COUNT;
  664. cp->PipesLeft = cp->PipeCount;
  665. /* The process has now started. */
  666. cp->State = kwsysProcess_State_Executing;
  667. }
  668. /*--------------------------------------------------------------------------*/
  669. int kwsysProcess_WaitForData(kwsysProcess* cp, int pipes, char** data, int* length,
  670. double* userTimeout)
  671. {
  672. kwsysProcessTime userStartTime;
  673. kwsysProcessTime timeoutLength;
  674. kwsysProcessTime timeoutTime;
  675. DWORD timeout;
  676. int user;
  677. int done = 0;
  678. int expired = 0;
  679. int pipeId = 0;
  680. DWORD w;
  681. HANDLE events[2];
  682. /* Make sure we are executing a process. */
  683. if(cp->State != kwsysProcess_State_Executing || cp->Killed ||
  684. cp->TimeoutExpired)
  685. {
  686. return 0;
  687. }
  688. /* We will wait for data until the process termiantes or data are
  689. available. */
  690. events[0] = cp->Full;
  691. events[1] = cp->ProcessInformation.hProcess;
  692. /* Record the time at which user timeout period starts. */
  693. userStartTime = kwsysProcessTimeGetCurrent();
  694. /* Calculate the time at which a timeout will expire, and whether it
  695. is the user or process timeout. */
  696. user = kwsysProcessGetTimeoutTime(cp, userTimeout, &timeoutTime);
  697. /* Loop until we have a reason to return. */
  698. while(!done && cp->PipesLeft > 0)
  699. {
  700. /* If we previously got data from a thread, let it know we are
  701. done with the data. */
  702. if(cp->CurrentIndex < CMPE_PIPE_COUNT)
  703. {
  704. ReleaseSemaphore(cp->Pipe[cp->CurrentIndex].Empty, 1, 0);
  705. cp->CurrentIndex = CMPE_PIPE_COUNT;
  706. }
  707. /* Setup a timeout if required. */
  708. if(kwsysProcessGetTimeoutLeft(&timeoutTime, &timeoutLength))
  709. {
  710. /* Timeout has already expired. */
  711. expired = 1;
  712. done = 1;
  713. break;
  714. }
  715. if(timeoutTime.QuadPart < 0)
  716. {
  717. timeout = INFINITE;
  718. }
  719. else
  720. {
  721. timeout = kwsysProcessTimeToDWORD(timeoutLength);
  722. }
  723. /* Wait for a pipe's thread to signal or the application to
  724. terminate. */
  725. w = WaitForMultipleObjects(cp->Terminated?1:2, events, 0, timeout);
  726. if(w == WAIT_TIMEOUT)
  727. {
  728. /* Timeout has expired. */
  729. expired = 1;
  730. done = 1;
  731. }
  732. else if(w == WAIT_OBJECT_0)
  733. {
  734. /* Save the index of the reporting thread and release the mutex.
  735. The thread will block until we signal its Empty mutex. */
  736. cp->CurrentIndex = cp->SharedIndex;
  737. ReleaseSemaphore(cp->SharedIndexMutex, 1, 0);
  738. /* Data are available or a pipe closed. */
  739. if(cp->Pipe[cp->CurrentIndex].Closed)
  740. {
  741. /* The pipe closed. */
  742. --cp->PipesLeft;
  743. }
  744. else if(cp->CurrentIndex == CMPE_PIPE_ERROR)
  745. {
  746. /* This is data on the special error reporting pipe for Win9x.
  747. Append it to the error buffer. */
  748. int length = cp->Pipe[cp->CurrentIndex].DataLength;
  749. if(length > CMPE_PIPE_BUFFER_SIZE - cp->ErrorMessageLength)
  750. {
  751. length = CMPE_PIPE_BUFFER_SIZE - cp->ErrorMessageLength;
  752. }
  753. if(length > 0)
  754. {
  755. memcpy(cp->ErrorMessage+cp->ErrorMessageLength,
  756. cp->Pipe[cp->CurrentIndex].DataBuffer, length);
  757. cp->ErrorMessageLength += length;
  758. }
  759. else
  760. {
  761. cp->ErrorMessage[cp->ErrorMessageLength] = 0;
  762. }
  763. }
  764. else if(pipes & (1 << cp->CurrentIndex))
  765. {
  766. /* Caller wants this data. Report it. */
  767. *data = cp->Pipe[cp->CurrentIndex].DataBuffer;
  768. *length = cp->Pipe[cp->CurrentIndex].DataLength;
  769. pipeId = (1 << cp->CurrentIndex);
  770. done = 1;
  771. }
  772. else
  773. {
  774. /* Caller does not care about this pipe. Ignore the data. */
  775. }
  776. }
  777. else
  778. {
  779. int i;
  780. /* Process has terminated. */
  781. cp->Terminated = 1;
  782. /* Close our copies of the pipe write handles so the pipe
  783. threads can detect end-of-data. */
  784. for(i=0; i < cp->PipeCount; ++i)
  785. {
  786. kwsysProcessCleanupHandle(&cp->Pipe[i].Write);
  787. }
  788. }
  789. }
  790. /* Update the user timeout. */
  791. if(userTimeout)
  792. {
  793. kwsysProcessTime userEndTime = kwsysProcessTimeGetCurrent();
  794. kwsysProcessTime difference = kwsysProcessTimeSubtract(userEndTime,
  795. userStartTime);
  796. double d = kwsysProcessTimeToDouble(difference);
  797. *userTimeout -= d;
  798. if(*userTimeout < 0)
  799. {
  800. *userTimeout = 0;
  801. }
  802. }
  803. /* Check what happened. */
  804. if(pipeId)
  805. {
  806. /* Data are ready on a pipe. */
  807. return pipeId;
  808. }
  809. else if(expired)
  810. {
  811. /* A timeout has expired. */
  812. if(user)
  813. {
  814. /* The user timeout has expired. It has no time left. */
  815. return kwsysProcess_Pipe_Timeout;
  816. }
  817. else
  818. {
  819. /* The process timeout has expired. Kill the child now. */
  820. kwsysProcess_Kill(cp);
  821. cp->TimeoutExpired = 1;
  822. cp->Killed = 0;
  823. return 0;
  824. }
  825. }
  826. else
  827. {
  828. /* The process has terminated and no more data are available. */
  829. return 0;
  830. }
  831. }
  832. /*--------------------------------------------------------------------------*/
  833. int kwsysProcess_WaitForExit(kwsysProcess* cp, double* userTimeout)
  834. {
  835. int i;
  836. int pipe = 0;
  837. /* Make sure we are executing a process. */
  838. if(cp->State != kwsysProcess_State_Executing)
  839. {
  840. return 1;
  841. }
  842. /* Wait for the process to terminate. Ignore all data. */
  843. while((pipe = kwsysProcess_WaitForData(cp, 0, 0, 0, userTimeout)) > 0)
  844. {
  845. if(pipe == kwsysProcess_Pipe_Timeout)
  846. {
  847. /* The user timeout has expired. */
  848. return 0;
  849. }
  850. }
  851. /* When the last pipe closes in WaitForData, the loop terminates
  852. without releaseing the pipe's thread. Release it now. */
  853. if(cp->CurrentIndex < CMPE_PIPE_COUNT)
  854. {
  855. ReleaseSemaphore(cp->Pipe[cp->CurrentIndex].Empty, 1, 0);
  856. cp->CurrentIndex = CMPE_PIPE_COUNT;
  857. }
  858. /* Wait for all pipe threads to reset. */
  859. for(i=0; i < cp->PipeCount; ++i)
  860. {
  861. WaitForSingleObject(cp->Pipe[i].Reset, INFINITE);
  862. }
  863. /* ---- It is now safe again to call kwsysProcessCleanup. ----- */
  864. /* Close all the pipes. */
  865. kwsysProcessCleanup(cp, 0);
  866. /* We are done reading all data. Wait for the child to terminate.
  867. This will only block if we killed the child and are waiting for
  868. it to cleanup. */
  869. WaitForSingleObject(cp->ProcessInformation.hProcess, INFINITE);
  870. /* Determine the outcome. */
  871. if(cp->Killed)
  872. {
  873. /* We killed the child. */
  874. cp->State = kwsysProcess_State_Killed;
  875. }
  876. else if(cp->ErrorMessageLength)
  877. {
  878. /* Failed to run the process. */
  879. cp->State = kwsysProcess_State_Error;
  880. }
  881. else if(cp->TimeoutExpired)
  882. {
  883. /* The timeout expired. */
  884. cp->State = kwsysProcess_State_Expired;
  885. }
  886. else if(GetExitCodeProcess(cp->ProcessInformation.hProcess,
  887. &cp->ExitCode))
  888. {
  889. /* The child exited. */
  890. if(cp->ExitCode & 0xC0000000)
  891. {
  892. /* Child terminated due to exceptional behavior. */
  893. cp->State = kwsysProcess_State_Exception;
  894. switch (cp->ExitCode)
  895. {
  896. case CONTROL_C_EXIT:
  897. cp->ExitException = kwsysProcess_Exception_Interrupt; break;
  898. case EXCEPTION_FLT_DENORMAL_OPERAND:
  899. case EXCEPTION_FLT_DIVIDE_BY_ZERO:
  900. case EXCEPTION_FLT_INEXACT_RESULT:
  901. case EXCEPTION_FLT_INVALID_OPERATION:
  902. case EXCEPTION_FLT_OVERFLOW:
  903. case EXCEPTION_FLT_STACK_CHECK:
  904. case EXCEPTION_FLT_UNDERFLOW:
  905. case EXCEPTION_INT_DIVIDE_BY_ZERO:
  906. case EXCEPTION_INT_OVERFLOW:
  907. cp->ExitException = kwsysProcess_Exception_Numerical; break;
  908. case EXCEPTION_ACCESS_VIOLATION:
  909. case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
  910. case EXCEPTION_DATATYPE_MISALIGNMENT:
  911. case EXCEPTION_INVALID_DISPOSITION:
  912. case EXCEPTION_IN_PAGE_ERROR:
  913. case EXCEPTION_NONCONTINUABLE_EXCEPTION:
  914. case EXCEPTION_STACK_OVERFLOW:
  915. cp->ExitException = kwsysProcess_Exception_Fault; break;
  916. case EXCEPTION_ILLEGAL_INSTRUCTION:
  917. case EXCEPTION_PRIV_INSTRUCTION:
  918. cp->ExitException = kwsysProcess_Exception_Illegal; break;
  919. default:
  920. cp->ExitException = kwsysProcess_Exception_Other; break;
  921. }
  922. cp->ExitValue = 1;
  923. }
  924. else
  925. {
  926. /* Child exited normally. */
  927. cp->State = kwsysProcess_State_Exited;
  928. cp->ExitException = kwsysProcess_Exception_None;
  929. cp->ExitValue = cp->ExitCode & 0x000000FF;
  930. }
  931. }
  932. else
  933. {
  934. /* Error getting the child return code. */
  935. strcpy(cp->ErrorMessage, "Error getting child return code.");
  936. cp->State = kwsysProcess_State_Error;
  937. }
  938. /* The child process is terminated. */
  939. CloseHandle(cp->ProcessInformation.hProcess);
  940. return 1;
  941. }
  942. /*--------------------------------------------------------------------------*/
  943. void kwsysProcess_Kill(kwsysProcess* cp)
  944. {
  945. int i;
  946. /* Make sure we are executing a process. */
  947. if(cp->State != kwsysProcess_State_Executing || cp->TimeoutExpired ||
  948. cp->Killed || cp->Terminated)
  949. {
  950. return;
  951. }
  952. /* If we are killing a process that just reported data, release
  953. the pipe's thread. */
  954. if(cp->CurrentIndex < CMPE_PIPE_COUNT)
  955. {
  956. ReleaseSemaphore(cp->Pipe[cp->CurrentIndex].Empty, 1, 0);
  957. cp->CurrentIndex = CMPE_PIPE_COUNT;
  958. }
  959. /* Wake up all the pipe threads with dummy data. */
  960. for(i=0; i < cp->PipeCount; ++i)
  961. {
  962. DWORD dummy;
  963. WriteFile(cp->Pipe[i].Write, "", 1, &dummy, 0);
  964. }
  965. /* Tell pipe threads to reset until we run another process. */
  966. while(cp->PipesLeft > 0)
  967. {
  968. WaitForSingleObject(cp->Full, INFINITE);
  969. cp->CurrentIndex = cp->SharedIndex;
  970. ReleaseSemaphore(cp->SharedIndexMutex, 1, 0);
  971. cp->Pipe[cp->CurrentIndex].Closed = 1;
  972. ReleaseSemaphore(cp->Pipe[cp->CurrentIndex].Empty, 1, 0);
  973. --cp->PipesLeft;
  974. }
  975. /* Kill the child. */
  976. cp->Killed = 1;
  977. if(cp->Win9x)
  978. {
  979. /* Windows 9x. Tell the forwarding executable to kill the child. */
  980. SetEvent(cp->Win9xKillEvent);
  981. }
  982. else
  983. {
  984. /* Not Windows 9x. Just terminate the child. */
  985. TerminateProcess(cp->ProcessInformation.hProcess, 255);
  986. }
  987. }
  988. /*--------------------------------------------------------------------------*/
  989. /*
  990. Function executed for each pipe's thread. Argument is a pointer to
  991. the kwsysProcessPipeData instance for this thread.
  992. */
  993. DWORD WINAPI kwsysProcessPipeThread(LPVOID ptd)
  994. {
  995. kwsysProcessPipeData* td = (kwsysProcessPipeData*)ptd;
  996. kwsysProcess* cp = td->Process;
  997. /* Wait for a process to be ready. */
  998. while((WaitForSingleObject(td->Ready, INFINITE), !cp->Deleting))
  999. {
  1000. /* Read output from the process for this thread's pipe. */
  1001. kwsysProcessPipeThreadReadPipe(cp, td);
  1002. /* We were signalled to exit with our buffer empty. Reset the
  1003. mutex for a new process. */
  1004. ReleaseSemaphore(td->Empty, 1, 0);
  1005. /* Signal the main thread we have reset for a new process. */
  1006. ReleaseSemaphore(td->Reset, 1, 0);
  1007. }
  1008. return 0;
  1009. }
  1010. /*--------------------------------------------------------------------------*/
  1011. /*
  1012. Function called in each pipe's thread to handle data for one
  1013. execution of a subprocess.
  1014. */
  1015. void kwsysProcessPipeThreadReadPipe(kwsysProcess* cp, kwsysProcessPipeData* td)
  1016. {
  1017. /* Wait for space in the thread's buffer. */
  1018. while((WaitForSingleObject(td->Empty, INFINITE), !td->Closed))
  1019. {
  1020. /* Read data from the pipe. This may block until data are available. */
  1021. if(!ReadFile(td->Read, td->DataBuffer, CMPE_PIPE_BUFFER_SIZE,
  1022. &td->DataLength, 0))
  1023. {
  1024. if(GetLastError() != ERROR_BROKEN_PIPE)
  1025. {
  1026. /* UNEXPECTED failure to read the pipe. */
  1027. }
  1028. /* The pipe closed. There are no more data to read. */
  1029. td->Closed = 1;
  1030. }
  1031. /* Wait for our turn to be handled by the main thread. */
  1032. WaitForSingleObject(cp->SharedIndexMutex, INFINITE);
  1033. /* Tell the main thread we have something to report. */
  1034. cp->SharedIndex = td->Index;
  1035. ReleaseSemaphore(cp->Full, 1, 0);
  1036. }
  1037. }
  1038. /*--------------------------------------------------------------------------*/
  1039. /* Close the given handle if it is open. Reset its value to 0. */
  1040. void kwsysProcessCleanupHandle(PHANDLE h)
  1041. {
  1042. if(h && *h)
  1043. {
  1044. CloseHandle(*h);
  1045. *h = 0;
  1046. }
  1047. }
  1048. /*--------------------------------------------------------------------------*/
  1049. /* Close all handles created by kwsysProcess_Execute. */
  1050. void kwsysProcessCleanup(kwsysProcess* cp, int error)
  1051. {
  1052. int i;
  1053. /* If this is an error case, report the error. */
  1054. if(error)
  1055. {
  1056. /* Format the error message. */
  1057. DWORD original = GetLastError();
  1058. DWORD length = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
  1059. FORMAT_MESSAGE_IGNORE_INSERTS, 0, original,
  1060. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  1061. cp->ErrorMessage, CMPE_PIPE_BUFFER_SIZE, 0);
  1062. if(length > 0)
  1063. {
  1064. /* Remove trailing period and newline, if any. */
  1065. if(cp->ErrorMessage[length-1] == '\n')
  1066. {
  1067. cp->ErrorMessage[length-1] = 0;
  1068. --length;
  1069. if(length > 0 && cp->ErrorMessage[length-1] == '\r')
  1070. {
  1071. cp->ErrorMessage[length-1] = 0;
  1072. --length;
  1073. }
  1074. }
  1075. if(cp->ErrorMessage[length-1] == '.')
  1076. {
  1077. cp->ErrorMessage[length-1] = 0;
  1078. --length;
  1079. }
  1080. }
  1081. else
  1082. {
  1083. /* FormatMessage failed. Use a default message. */
  1084. _snprintf(cp->ErrorMessage, CMPE_PIPE_BUFFER_SIZE,
  1085. "Process execution failed with error 0x%X. "
  1086. "FormatMessage failed with error 0x%X.",
  1087. original, GetLastError());
  1088. }
  1089. /* Set the error state. */
  1090. cp->State = kwsysProcess_State_Error;
  1091. }
  1092. /* Free memory. */
  1093. if(cp->RealCommand)
  1094. {
  1095. free(cp->RealCommand);
  1096. cp->RealCommand = 0;
  1097. }
  1098. /* Close each pipe. */
  1099. for(i=0; i < cp->PipeCount; ++i)
  1100. {
  1101. kwsysProcessCleanupHandle(&cp->Pipe[i].Write);
  1102. kwsysProcessCleanupHandle(&cp->Pipe[i].Read);
  1103. }
  1104. }
  1105. /*--------------------------------------------------------------------------*/
  1106. /* Get the time at which either the process or user timeout will
  1107. expire. Returns 1 if the user timeout is first, and 0 otherwise. */
  1108. int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout,
  1109. kwsysProcessTime* timeoutTime)
  1110. {
  1111. /* The first time this is called, we need to calculate the time at
  1112. which the child will timeout. */
  1113. if(cp->Timeout && cp->TimeoutTime.QuadPart < 0)
  1114. {
  1115. kwsysProcessTime length = kwsysProcessTimeFromDouble(cp->Timeout);
  1116. cp->TimeoutTime = kwsysProcessTimeAdd(cp->StartTime, length);
  1117. }
  1118. /* Start with process timeout. */
  1119. *timeoutTime = cp->TimeoutTime;
  1120. /* Check if the user timeout is earlier. */
  1121. if(userTimeout)
  1122. {
  1123. kwsysProcessTime currentTime = kwsysProcessTimeGetCurrent();
  1124. kwsysProcessTime userTimeoutLength = kwsysProcessTimeFromDouble(*userTimeout);
  1125. kwsysProcessTime userTimeoutTime = kwsysProcessTimeAdd(currentTime,
  1126. userTimeoutLength);
  1127. if(kwsysProcessTimeLess(userTimeoutTime, *timeoutTime))
  1128. {
  1129. *timeoutTime = userTimeoutTime;
  1130. return 1;
  1131. }
  1132. }
  1133. return 0;
  1134. }
  1135. /*--------------------------------------------------------------------------*/
  1136. /* Get the length of time before the given timeout time arrives.
  1137. Returns 1 if the time has already arrived, and 0 otherwise. */
  1138. int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime,
  1139. kwsysProcessTime* timeoutLength)
  1140. {
  1141. if(timeoutTime->QuadPart < 0)
  1142. {
  1143. /* No timeout time has been requested. */
  1144. return 0;
  1145. }
  1146. else
  1147. {
  1148. /* Calculate the remaining time. */
  1149. kwsysProcessTime currentTime = kwsysProcessTimeGetCurrent();
  1150. *timeoutLength = kwsysProcessTimeSubtract(*timeoutTime, currentTime);
  1151. if(timeoutLength->QuadPart < 0)
  1152. {
  1153. /* Timeout has already expired. */
  1154. return 1;
  1155. }
  1156. else
  1157. {
  1158. /* There is some time left. */
  1159. return 0;
  1160. }
  1161. }
  1162. }
  1163. /*--------------------------------------------------------------------------*/
  1164. kwsysProcessTime kwsysProcessTimeGetCurrent()
  1165. {
  1166. kwsysProcessTime current;
  1167. FILETIME ft;
  1168. GetSystemTimeAsFileTime(&ft);
  1169. current.LowPart = ft.dwLowDateTime;
  1170. current.HighPart = ft.dwHighDateTime;
  1171. return current;
  1172. }
  1173. /*--------------------------------------------------------------------------*/
  1174. DWORD kwsysProcessTimeToDWORD(kwsysProcessTime t)
  1175. {
  1176. return (DWORD)(t.QuadPart * 0.0001);
  1177. }
  1178. /*--------------------------------------------------------------------------*/
  1179. double kwsysProcessTimeToDouble(kwsysProcessTime t)
  1180. {
  1181. return t.QuadPart * 0.0000001;
  1182. }
  1183. /*--------------------------------------------------------------------------*/
  1184. kwsysProcessTime kwsysProcessTimeFromDouble(double d)
  1185. {
  1186. kwsysProcessTime t;
  1187. t.QuadPart = (LONGLONG)(d*10000000);
  1188. return t;
  1189. }
  1190. /*--------------------------------------------------------------------------*/
  1191. int kwsysProcessTimeLess(kwsysProcessTime in1, kwsysProcessTime in2)
  1192. {
  1193. return in1.QuadPart < in2.QuadPart;
  1194. }
  1195. /*--------------------------------------------------------------------------*/
  1196. kwsysProcessTime kwsysProcessTimeAdd(kwsysProcessTime in1, kwsysProcessTime in2)
  1197. {
  1198. kwsysProcessTime out;
  1199. out.QuadPart = in1.QuadPart + in2.QuadPart;
  1200. return out;
  1201. }
  1202. /*--------------------------------------------------------------------------*/
  1203. kwsysProcessTime kwsysProcessTimeSubtract(kwsysProcessTime in1, kwsysProcessTime in2)
  1204. {
  1205. kwsysProcessTime out;
  1206. out.QuadPart = in1.QuadPart - in2.QuadPart;
  1207. return out;
  1208. }