ProcessWin32.c 37 KB

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