source: trunk/dll/systemf.c@ 1270

Last change on this file since 1270 was 1270, checked in by Gregg Young, 17 years ago

Comments and code cleanup for WaitChildThread solution to hang cused by viewer opening before archiver process closes (Ticket 58)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 39.4 KB
Line 
1
2/***********************************************************************
3
4 $Id: systemf.c 1270 2008-11-08 20:48:24Z gyoung $
5
6 System Interfaces
7
8 Copyright (c) 1993-98 M. Kimes
9 Copyright (c) 2003, 2008 Steven H.Levine
10
11 21 Nov 03 SHL Comments
12 31 Jul 04 SHL Indent -i2
13 01 Aug 04 SHL Rework lstrip/rstrip usage
14 17 Jul 06 SHL Use Runtime_Error
15 26 Jul 06 SHL Use convert_nl_to_nul
16 15 Aug 06 SHL More error popups
17 01 Nov 06 SHL runemf2: temp fix for hung windows caused by termq errors
18 03 Nov 06 SHL runemf2: rework termination queue logic to work for multiple threads
19 07 Jan 07 GKY Move error strings etc. to string file
20 06 Aug 07 GKY Reduce DosSleep times (ticket 148)
21 20 Aug 07 GKY Move #pragma alloc_text to end for OpenWatcom compat
22 29 Feb 08 GKY Changes to enable user settable command line length
23 29 Feb 08 GKY Refactor global command line variables to notebook.h
24 26 May 08 SHL Use uiLineNumber correctly
25 19 Jul 08 GKY Replace save_dir2(dir) with pFM2SaveDirectory or pTmpDir and use MakeTempName
26 08 Nov 08 GKY Post an event semaphore to WaitChildThread to fix hang caused by viewer trying
27 to open a file before the archiver process closes. (Ticket 58)
28
29***********************************************************************/
30
31#include <stdlib.h>
32#include <stdarg.h>
33#include <string.h>
34#include <ctype.h>
35
36#define INCL_DOS
37#define INCL_DOSERRORS
38#define INCL_WIN
39#define INCL_LONGLONG // dircnrs.h
40
41#include "fm3dll.h"
42#include "fm3dll2.h" // #define's for UM_*, control id's, etc.
43#include "mkdir.h" // Data declaration(s)
44#include "init.h" // Data declaration(s)
45#include "mainwnd.h" // Data declaration(s)
46#include "fm3dlg.h"
47#include "fm3str.h"
48#include "errutil.h" // Dos_Error...
49#include "strutil.h" // GetPString
50#include "notebook.h" //targetdirectory
51#include "pathutil.h"
52#include "cmdline.h" // CmdLineDlgProc
53#include "shadow.h" // RunSeamless
54#include "systemf.h"
55#include "strips.h" // convert_nl_to_nul, strip_lead_char
56#include "dirs.h" // switch_to
57#include "valid.h" // MakeFullName
58#include "misc.h" // GetCmdSpec
59#include "copyf.h" // MakeTempName
60#include "wrappers.h" // xfopen
61#include "fortify.h"
62
63static PSZ pszSrcFile = __FILE__;
64
65HEV hWaitChildSem;
66
67//static HAPP Exec(HWND hwndNotify, BOOL child, char *startdir, char *env,
68// PROGTYPE * progt, ULONG fl, char *formatstring, ...);
69
70/**
71 * Bring session foreground
72 * @return TRUE if OK, else FALSE
73 */
74
75BOOL ShowSession(HWND hwnd, PID pid)
76{
77 HSWITCH hswitch;
78 SWCNTRL swctl;
79 ULONG rc;
80
81 hswitch = WinQuerySwitchHandle(pid ? (HWND)0 : hwnd, pid);
82 if (hswitch) {
83 rc = WinQuerySwitchEntry(hswitch, &swctl);
84 if (!rc) {
85 if (swctl.idProcess == pid && swctl.uchVisibility == SWL_VISIBLE)
86 rc = WinSwitchToProgram(hswitch);
87 if (!rc)
88 return TRUE;
89 // else saymsg(MB_ENTER,HWND_DESKTOP,DEBUG_STRING,"Failed: %lu/%lx",rc,rc);
90
91 }
92 }
93 return FALSE;
94}
95
96/**
97 * Invoke runemf2 for command and file/directory list
98 * @return command return code or
99 * -1 if runtime error or
100 * -2 if user cancels command line edit dialog
101 */
102
103int ExecOnList(HWND hwnd, char *command, int flags, char *tpath,
104 char **list, char *prompt, PCSZ pszCallingFile, UINT uiLineNumber)
105{
106 /* executes the command once for all files in list */
107
108 char path[CCHMAXPATH], *commandline, modpath[CCHMAXPATH], listfile[CCHMAXPATH],
109 *p, *pp, drive, *file, *ext, *dot;
110 register int x;
111 BOOL spaces;
112
113 if (!command || !*command) {
114 Runtime_Error2(pszSrcFile, __LINE__, IDS_NODATATEXT);
115 return -1;
116 }
117 commandline = xmalloc(MaxComLineStrg + 1, pszSrcFile, __LINE__);
118 if (!commandline)
119 return -1; //already complained
120 *listfile = 0;
121 bstrip(command);
122
123 *path = 0;
124 if (tpath && *tpath)
125 strcpy(path, tpath);
126 else if (*command != '<' || !strchr(command, '>')) {
127 strcpy(path, command + (*command == '"'));
128 if (*command == '\"')
129 p = strchr(path, '\"');
130 else
131 p = strchr(path, ' ');
132 if (p)
133 *p = 0;
134 p = strrchr(path, '\\');
135 if (!p)
136 p = strrchr(path, ':');
137 if (p) {
138 if (*p == ':') {
139 p++;
140 *p = '\\';
141 p++;
142 }
143 *p = 0;
144 }
145 else
146 *path = 0;
147 }
148 if (!*path) {
149 if (list && list[0])
150 strcpy(path, list[0]);
151 p = strrchr(path, '\\');
152 if (!p)
153 p = strrchr(path, ':');
154 if (p) {
155 if (*p == ':') {
156 p++;
157 *p = '\\';
158 p++;
159 }
160 *p = 0;
161 }
162 else
163 *path = 0;
164 }
165 *modpath = 0;
166 if (list && list[0])
167 strcpy(modpath, list[0]);
168 p = strrchr(modpath, '\\');
169 if (!p)
170 p = strrchr(modpath, ':');
171 if (p) {
172 if (*p == ':') {
173 p++;
174 *p = '\\';
175 p++;
176 }
177 *p = 0;
178 }
179 else
180 *modpath = 0;
181 if (!*modpath)
182 strcpy(modpath, path);
183 if (*path)
184 MakeFullName(path);
185 if (*modpath)
186 MakeFullName(modpath);
187 if (IsFullName(path))
188 drive = toupper(*path);
189 else
190 drive = 0;
191
192 p = command; // substitue for special % sequences
193
194 pp = commandline;
195 *commandline = 0;
196 while (*p) {
197 if (*p == '%') {
198 switch (*(p + 1)) {
199 case '!': /* write list to file, add filename */
200 if (list) {
201 if (!*listfile) {
202 FILE *fp;
203
204
205 strcpy(listfile, pTmpDir ? pTmpDir : pFM2SaveDirectory);
206 MakeTempName(listfile, "$FM2LI$T", 2);
207 /*if (listfile[strlen(listfile) - 1] != '\\')
208 strcat(listfile, "\\");
209 sprintf(&listfile[strlen(listfile)], "%s.%03x",
210 LISTTEMPROOT, (clock() & 4095));*/
211 fp = xfopen(listfile, "w",pszSrcFile,__LINE__);
212 if (fp) {
213 for (x = 0; list[x]; x++)
214 {
215 fputs(list[x], fp);
216 if (list[x + 1])
217 fputc('\n', fp);
218 }
219 fclose(fp);
220 }
221 }
222 strcpy(pp, listfile);
223 pp += strlen(listfile);
224 }
225 p += 2;
226 break;
227
228 case 'c': /* add name of command processor */
229 {
230 char *env = GetCmdSpec(FALSE);
231
232 if (needs_quoting(env) && !strchr(env, '\"')) {
233 *pp = '\"';
234 pp++;
235 spaces = TRUE;
236 }
237 else
238 spaces = FALSE;
239 strcpy(pp, env);
240 p += 2;
241 pp += strlen(env);
242 if (spaces) {
243 *pp = '\"';
244 pp++;
245 }
246 }
247 break;
248
249 case 't': /* add Target directory */
250 if (needs_quoting(targetdir) && !strchr(targetdir, '\"')) {
251 *pp = '\"';
252 pp++;
253 spaces = TRUE;
254 }
255 else
256 spaces = FALSE;
257 strcpy(pp, targetdir);
258 p += 2;
259 pp += strlen(targetdir);
260 if (spaces) {
261 *pp = '\"';
262 pp++;
263 }
264 break;
265
266 case '$': /* add drive letter */
267 if (drive)
268 *pp = drive;
269 else {
270 ULONG ulDriveNum = 3, ulDriveMap;
271
272 DosQCurDisk(&ulDriveNum, &ulDriveMap);
273 *pp = (char) (ulDriveNum + '@');
274 }
275 pp++;
276 p += 2;
277 break;
278
279 case 'U': /* add path of first list component */
280 case 'u':
281 if (*modpath) {
282 if (needs_quoting(modpath) && !strchr(modpath, '\"')) {
283 spaces = TRUE;
284 *pp = '\"';
285 pp++;
286 }
287 else
288 spaces = FALSE;
289 if (*(p + 1) == 'u') {
290 strcpy(pp, modpath);
291 pp += strlen(modpath);
292 }
293 else {
294 strcpy(pp, modpath + 2);
295 pp += strlen(modpath + 2);
296 }
297 if (spaces) {
298 if (modpath[strlen(modpath) - 1] == '\\') {
299 *pp = '\\';
300 pp++;
301 }
302 *pp = '\"';
303 pp++;
304 }
305 }
306 else {
307 char temp[CCHMAXPATH];
308
309 strcpy(temp, pFM2SaveDirectory);
310 if (needs_quoting(temp) && !strchr(temp, '\"')) {
311 spaces = TRUE;
312 *pp = '\"';
313 pp++;
314 }
315 else
316 spaces = FALSE;
317 strcpy(pp, temp);
318 pp += strlen(temp);
319 if (spaces) {
320 if (temp[strlen(temp) - 1] == '\\') {
321 *pp = '\\';
322 pp++;
323 }
324 *pp = '\"';
325 pp++;
326 }
327 }
328 p += 2;
329 break;
330
331 case 'P': /* add path of execution */
332 case 'p':
333 if (*path) {
334 if (needs_quoting(path) && !strchr(path, '\"')) {
335 spaces = TRUE;
336 *pp = '\"';
337 pp++;
338 }
339 else
340 spaces = FALSE;
341 if (*(p + 1) == 'p') {
342 strcpy(pp, path);
343 pp += strlen(path);
344 }
345 else {
346 strcpy(pp, path + 2);
347 pp += strlen(path + 2);
348 }
349 if (spaces) {
350 if (path[strlen(path) - 1] == '\\') {
351 *pp = '\\';
352 pp++;
353 }
354 *pp = '\"';
355 pp++;
356 }
357 }
358 else {
359 char temp[CCHMAXPATH];
360
361 strcpy(temp, pFM2SaveDirectory);
362 if (needs_quoting(temp) && !strchr(temp, '\"')) {
363 spaces = TRUE;
364 *pp = '\"';
365 pp++;
366 }
367 else
368 spaces = FALSE;
369 strcpy(pp, temp);
370 pp += strlen(temp);
371 if (spaces) {
372 if (temp[strlen(temp) - 1] == '\\') {
373 *pp = '\\';
374 pp++;
375 }
376 *pp = '\"';
377 pp++;
378 }
379 }
380 p += 2;
381 break;
382
383 case 'D':
384 if (hwndMain) {
385 PCNRITEM pci;
386
387 pci = (PCNRITEM) WinSendMsg(WinWindowFromID(WinWindowFromID(
388 hwndTree, FID_CLIENT), TREE_CNR),
389 CM_QUERYRECORDEMPHASIS,
390 MPFROMLONG(CMA_FIRST),
391 MPFROMSHORT(CRA_CURSORED));
392 if (pci && (int) pci != -1 && *pci->pszFileName) {
393 if (needs_quoting(pci->pszFileName) &&
394 !strchr(pci->pszFileName, '\"'))
395 {
396 *pp = '\"';
397 pp++;
398 spaces = TRUE;
399 }
400 else
401 spaces = FALSE;
402 strcpy(pp, pci->pszFileName);
403 pp += strlen(pci->pszFileName);
404 if (spaces) {
405 *pp = '\"';
406 pp++;
407 }
408 }
409 }
410 p += 2;
411 break;
412
413 case 'd':
414 if (hwndMain) {
415 HENUM henum;
416 char retstr[CCHMAXPATH];
417 HWND hwndC, hwndDir;
418 USHORT id;
419 BOOL first = TRUE;
420
421 henum = WinBeginEnumWindows(hwndMain);
422 while ((hwndC = WinGetNextWindow(henum)) != NULLHANDLE) {
423 if (hwndC != hwndTree) {
424 id = WinQueryWindowUShort(hwndC, QWS_ID);
425 if (id) {
426 hwndDir = WinWindowFromID(hwndC, FID_CLIENT);
427 if (hwndDir) {
428 hwndDir = WinWindowFromID(hwndDir, DIR_CNR);
429 if (hwndDir) {
430 *retstr = 0;
431 WinSendMsg(hwndC, UM_CONTAINERDIR, MPFROMP(retstr), MPVOID);
432 if (*retstr) {
433 if (!first) {
434 *pp = ' ';
435 pp++;
436 }
437 first = FALSE;
438 if (needs_quoting(retstr) && !strchr(retstr, '\"')) {
439 *pp = '\"';
440 pp++;
441 spaces = TRUE;
442 }
443 else
444 spaces = FALSE;
445 strcpy(pp, retstr);
446 pp += strlen(retstr);
447 if (spaces) {
448 *pp = '\"';
449 pp++;
450 }
451 }
452 }
453 }
454 }
455 }
456 }
457 WinEndEnumWindows(henum);
458 }
459 p += 2;
460 break;
461
462 case '%':
463 *pp = '%';
464 pp++;
465 p += 2;
466 break;
467
468 case 'R':
469 case 'F':
470 case 'A':
471 case 'r':
472 case 'f':
473 case 'a':
474 case 'e':
475 if (list) {
476 for (x = 0; list[x]; x++)
477 {
478 file = strrchr(list[x], '\\');
479 if (!file)
480 file = strrchr(list[x], ':');
481 if (file)
482 file++;
483 else
484 file = list[x];
485 ext = strrchr(file, '.');
486 dot = ext;
487 if (ext)
488 ext++;
489 switch (*(p + 1)) {
490 case 'R':
491 case 'r':
492 if (pp + strlen(list[x]) > commandline + MaxComLineStrg)
493 goto BreakOut;
494 if (*(p + 1) == 'r') {
495 strcpy(pp, list[x]);
496 pp += strlen(list[x]);
497 }
498 else {
499 strcpy(pp, list[x] + 2);
500 pp += strlen(list[x] + 2);
501 }
502 break;
503
504 case 'F':
505 case 'f':
506 if (*(p + 1) == 'F' && dot)
507 *dot = 0;
508 if (pp + strlen(file) > commandline + MaxComLineStrg)
509 goto BreakOut;
510 if (needs_quoting(file)) {
511 spaces = TRUE;
512 *pp = '\"';
513 pp++;
514 }
515 else
516 spaces = FALSE;
517 strcpy(pp, file);
518 pp += strlen(file);
519 if (*(p + 1) == 'F' && dot)
520 *dot = '.';
521 if (spaces) {
522 if (*(pp - 1) != '\"') {
523 *pp = '\"';
524 pp++;
525 }
526 }
527 break;
528
529 case 'A':
530 case 'a':
531 if (pp + strlen(list[x]) > commandline + MaxComLineStrg)
532 goto BreakOut;
533 if (needs_quoting(list[x]) && !strchr(list[x], '\"')) {
534 spaces = TRUE;
535 *pp = '\"';
536 pp++;
537 }
538 else
539 spaces = FALSE;
540 if (*(p + 1) == 'a') {
541 strcpy(pp, list[x]);
542 pp += strlen(list[x]);
543 }
544 else {
545 strcpy(pp, list[x] + 2);
546 pp += strlen(list[x] + 2);
547 }
548 if (spaces) {
549 if (list[x][strlen(list[x]) - 1] == '\\') {
550 *pp = '\\';
551 pp++;
552 }
553 *pp = '\"';
554 pp++;
555 }
556 break;
557
558 case 'e':
559 if (ext) {
560 if (pp + strlen(ext) > commandline + MaxComLineStrg)
561 goto BreakOut;
562 if (needs_quoting(ext)) {
563 spaces = TRUE;
564 *pp = '\"';
565 pp++;
566 }
567 else
568 spaces = FALSE;
569 strcpy(pp, ext);
570 pp += strlen(ext);
571 if (spaces) {
572 if (*(pp - 1) != '\"') {
573 *pp = '\"';
574 pp++;
575 }
576 }
577 }
578 break;
579 }
580 if (list[x + 1]) {
581 *pp = ' ';
582 pp++;
583 }
584 }
585 }
586 p += 2;
587 break;
588
589 default:
590 *pp = *p;
591 p++;
592 pp++;
593 break;
594 }
595 }
596 else {
597 *pp = *p;
598 pp++;
599 p++;
600 }
601 *pp = 0;
602 }
603
604BreakOut:
605
606 {
607 EXECARGS ex;
608 ULONG size;
609 int ret;
610
611 memset(&ex, 0, sizeof(EXECARGS));
612 size = sizeof(ex.environment) - 1;
613 PrfQueryProfileData(fmprof, FM3Str, command, ex.environment, &size);
614 if (flags & PROMPT) {
615 /* allow editing command line */
616 ex.flags = (flags & (~PROMPT));
617 ex.commandline = commandline;
618 strcpy(ex.path, path);
619 if (prompt)
620 strcpy(ex.title, prompt);
621 ret = WinDlgBox(HWND_DESKTOP, hwnd, CmdLineDlgProc, FM3ModHandle,
622 EXEC_FRAME, &ex);
623 if (ret != 1) {
624 free(commandline);
625 return (ret == 0) ? -1 : -2;
626 }
627 }
628 else
629 ex.flags = flags;
630 ex.flags &= (~PROMPT);
631 ret = runemf2(ex.flags, hwnd, pszCallingFile, uiLineNumber, path,
632 (*ex.environment) ? ex.environment : NULL,
633 "%s", commandline);
634 free(commandline);
635 return ret;
636 }
637}
638
639/** Run requested app
640 * @return application return code or -1 if problem starting app
641 */
642
643int runemf2(int type, HWND hwnd, PCSZ pszCallingFile, UINT uiLineNumber,
644 char *pszDirectory, char *pszEnvironment,
645 char *formatstring,...)
646{
647 /** example:
648
649 * status = runemf2(SEPARATE | WINDOWED,
650 * hwnd, pszCallingFile, __LINE__,
651 * NullStr,
652 * NULL,
653 * "%s /C %s",
654 * getenv("COMSPEC"),
655 * batchfilename);
656 *
657 * use (HWND)0 for hwnd if window handle not handy.
658 * pszCallingFile and __LINE__ are used to determine caller for easier error tracking
659 */
660
661 /**
662 * type bitmapped flag -- see systemf.h
663 */
664
665 va_list parguments;
666 int ret = -1;
667 RESULTCODES results;
668 STARTDATA sdata;
669 REQUESTDATA rq;
670 ULONG ulSessID;
671 ULONG ulLength;
672 UINT ctr;
673 ULONG ulAppType;
674 PID sessPID;
675 BOOL wasquote;
676 char *pszPgm, *pszArgs = NULL;
677 char szObject[32] = "", *p, szSavedir[CCHMAXPATH];
678 BOOL useTermQ = FALSE;
679 char szTempdir[CCHMAXPATH];
680
681 typedef struct {
682 USHORT usSessID;
683 USHORT usRC;
684 } TERMINFO;
685
686 TERMINFO *pTermInfo;
687 BYTE bPriority;
688 APIRET rc;
689 PIB *ppib;
690 TIB *ptib;
691
692 // Shared by all threads
693# define TERMQ_BASE_NAME "\\QUEUES\\FM3WAIT"
694 static char szTermQName[30];
695 static HQUEUE hTermQ;
696 //static HEV hTermQSem;
697
698 if (pszDirectory && *pszDirectory) {
699 if (!DosQueryPathInfo(pszDirectory,
700 FIL_QUERYFULLNAME,
701 szTempdir,
702 sizeof(szTempdir)))
703 pszDirectory = szTempdir;
704 }
705
706 if (!hwnd)
707 hwnd = HWND_DESKTOP;
708
709 rc = DosAllocMem((PVOID)&pszPgm,
710 MaxComLineStrg,
711 PAG_COMMIT | OBJ_TILE | PAG_READ | PAG_WRITE);
712 if (rc) {
713 Dos_Error(MB_CANCEL,rc,hwnd,pszSrcFile,__LINE__,GetPString(IDS_OUTOFMEMORY));
714 return -1;
715 }
716
717 *szSavedir = 0;
718
719 *pszPgm = 0;
720 va_start(parguments,
721 formatstring);
722 vsprintf(pszPgm,
723 formatstring,
724 parguments);
725 va_end(parguments);
726
727 if (pszEnvironment) {
728 p = &pszEnvironment[strlen(pszEnvironment)] + 1;
729 *p = 0;
730 p = pszEnvironment;
731 while ((p = convert_nl_to_nul(p)) != NULL)
732 ; // loop
733 }
734
735 if (!*pszPgm) {
736 p = GetCmdSpec(FALSE);
737 strcpy(pszPgm, p);
738 if (!*pszPgm) {
739 Runtime_Error2(pszSrcFile, __LINE__, IDS_NODATATEXT);
740 return -1;
741 }
742 }
743
744 if (*pszPgm) {
745 if (*pszPgm == '<' && strchr(pszPgm, '>')) {
746 /* is a workplace object */
747 HOBJECT hWPSObject;
748 char temp;
749
750 p = strchr(pszPgm, '>');
751 p++;
752 temp = *p;
753 if (temp) {
754 rc = DosAllocMem((PVOID)&pszArgs,
755 MaxComLineStrg * 2,
756 PAG_COMMIT | OBJ_TILE | PAG_READ | PAG_WRITE);
757 if (rc)
758 Dos_Error(MB_CANCEL,rc,hwnd,pszSrcFile,__LINE__,GetPString(IDS_OUTOFMEMORY));
759 }
760 else
761 pszArgs = NULL;
762 *p = 0;
763 /* Find the handle of the WPS object */
764 hWPSObject = WinQueryObject(pszPgm);
765 *p = temp;
766 if (hWPSObject != NULLHANDLE) {
767 if (pszArgs && *p) {
768 sprintf(pszArgs,"OPEN=DEFAULT;PARAMETERS=\"%s\"",p);
769 WinSetObjectData(hWPSObject,pszArgs);
770 }
771 else
772 WinSetObjectData(hWPSObject,"OPEN=DEFAULT");
773 ret = 0;
774 }
775 goto ObjectInterrupt;
776 }
777
778 if ((type & RUNTYPE_MASK) == SYNCHRONOUS ||
779 (type & RUNTYPE_MASK) == ASYNCHRONOUS ||
780 (type & RUNTYPE_MASK) == DETACHED)
781 {
782 strip_lead_char(" \t", pszPgm);
783 p = pszPgm;
784 wasquote = FALSE;
785 while (*p &&
786 (wasquote ||
787 (*p != ' ' &&
788 *p != '\t')))
789 {
790 if (*p == '\"') {
791 if (!wasquote) {
792 wasquote = TRUE;
793 memmove(p,
794 p + 1,
795 strlen(p));
796 while (*p == ' ' ||
797 *p == '\t')
798 p++;
799 }
800 else {
801 memmove(p,
802 p + 1,
803 strlen(p));
804 break;
805 }
806 }
807 else
808 p++;
809 }
810 if (*p) {
811 *p = 0;
812 p++;
813 }
814 else
815 p = pszPgm;
816 p[strlen(p) + 1] = 0; /* double-terminate args */
817 if (*pszPgm) {
818 if (!strchr(pszPgm, '\\') &&
819 !strchr(pszPgm, ':') &&
820 pszDirectory &&
821 *pszDirectory)
822 {
823 strcpy(szSavedir, pFM2SaveDirectory);
824 switch_to(pszDirectory);
825 }
826 rc = DosQueryAppType(pszPgm,&ulAppType);
827 if (!strchr(pszPgm, '\\') &&
828 !strchr(pszPgm, ':') &&
829 pszDirectory &&
830 *pszDirectory)
831 switch_to(szSavedir);
832 if (rc) {
833 Dos_Error(MB_CANCEL,rc,hwnd,pszSrcFile,__LINE__,
834 GetPString(IDS_DOSQAPPTYPEFAILEDTEXT),
835 pszPgm, pszCallingFile, uiLineNumber); // 26 May 08 SHL
836 DosFreeMem(pszPgm);
837 if (pszArgs)
838 DosFreeMem(pszArgs);
839 return -1;
840 }
841 if (ulAppType) {
842 if (ulAppType & FAPPTYP_DLL || ulAppType & FAPPTYP_VIRTDRV ||
843 ulAppType & FAPPTYP_PHYSDRV || ulAppType & FAPPTYP_PROTDLL)
844 {
845 Runtime_Error(pszSrcFile, __LINE__,
846 GetPString(IDS_APPTYPEUNEXPECTEDTEXT),
847 ulAppType, pszPgm, pszCallingFile, uiLineNumber); // 26 May 08 SHL
848 if (pszPgm)
849 DosFreeMem(pszPgm);
850 if (pszArgs)
851 DosFreeMem(pszArgs);
852 return -1;
853 }
854 if (ulAppType & FAPPTYP_DOS || ulAppType & FAPPTYP_WINDOWSREAL ||
855 ulAppType & FAPPTYP_WINDOWSPROT || ulAppType & FAPPTYP_WINDOWSPROT31)
856 {
857 Runtime_Error(pszSrcFile, __LINE__,
858 GetPString(IDS_APPTYPEUNEXPECTEDTEXT),
859 ulAppType, pszPgm, pszCallingFile, uiLineNumber); // 26 May 08 SHL
860 if (pszPgm)
861 DosFreeMem(pszPgm);
862 if (pszArgs)
863 DosFreeMem(pszArgs);
864 return -1;
865 }
866 }
867 memset(&results, 0, sizeof(results));
868 if (pszDirectory && *pszDirectory) {
869 strcpy(szSavedir, pFM2SaveDirectory);
870 switch_to(pszDirectory);
871 }
872 ret = DosExecPgm(szObject, sizeof(szObject),
873 ((type & RUNTYPE_MASK) == ASYNCHRONOUS ? EXEC_ASYNC : 0) +
874 ((type & RUNTYPE_MASK) == DETACHED ? EXEC_BACKGROUND : 0),
875 pszPgm, pszEnvironment, &results, pszPgm);
876 if (pszDirectory && *pszDirectory)
877 switch_to(szSavedir);
878 if (ret) {
879 Dos_Error(MB_ENTER,ret,hwnd,pszSrcFile,__LINE__,
880 GetPString(IDS_DOSEXECPGMFAILEDTEXT), pszPgm,
881 pszCallingFile, uiLineNumber); // 26 May 08 SHL
882 }
883 }
884 }
885 else {
886 if (~type & FULLSCREEN)
887 type |= WINDOWED;
888 rc = DosAllocMem((PVOID) & pszArgs, MaxComLineStrg * 2,
889 PAG_COMMIT | OBJ_TILE | PAG_READ | PAG_WRITE);
890 if (rc) {
891 Dos_Error(MB_CANCEL,rc,hwnd,pszSrcFile,__LINE__,GetPString(IDS_OUTOFMEMORY));
892 DosFreeMem(pszPgm);
893 return -1;
894 }
895 *pszArgs = 0;
896 memset(&sdata, 0, sizeof(sdata));
897 strip_lead_char(" \t", pszPgm);
898 p = pszPgm;
899 wasquote = FALSE;
900 while (*p && (wasquote || (*p != ' ' && *p != '\t'))) {
901 if (*p == '\"') {
902 if (!wasquote) {
903 wasquote = TRUE;
904 memmove(p, p + 1, strlen(p));
905 while (*p == ' ' || *p == '\t')
906 p++;
907 }
908 else {
909 memmove(p, p + 1, strlen(p));
910 break;
911 }
912 }
913 else
914 p++;
915 } // while
916 if (*p) {
917 *p = 0;
918 p++;
919 }
920 else
921 p = NullStr;
922 if (*p)
923 strcpy(pszArgs, p);
924
925 p = strrchr(pszPgm, '.');
926 if (p) {
927 char temp[CCHMAXPATH + 1];
928
929 if (!stricmp(p, ".BAT")) {
930 strcpy(temp, pszPgm);
931 strcpy(pszPgm, pszArgs);
932 strcpy(pszArgs, "/C ");
933 strcat(pszArgs, temp);
934 strcat(pszArgs, " ");
935 strcat(pszArgs, pszPgm);
936 strcpy(pszPgm, GetCmdSpec(TRUE)); // DOS
937 }
938 else if (!stricmp(p, ".CMD") || !stricmp(p, ".BTM")) {
939 // Assume 4OS2 is BTM
940 strcpy(temp, pszPgm);
941 strcpy(pszPgm, pszArgs);
942 strcpy(pszArgs, "/C ");
943 strcat(pszArgs, temp);
944 strcat(pszArgs, " ");
945 strcat(pszArgs, pszPgm);
946 strcpy(pszPgm, GetCmdSpec(FALSE)); // OS/2
947 }
948 }
949
950 // goddamned OS/2 limit
951
952 if (strlen(pszPgm) + strlen(pszArgs) > 1024)
953 pszArgs[1024 - strlen(pszPgm)] = 0;
954
955 if (!strchr(pszPgm, '\\') &&
956 !strchr(pszPgm, ':') &&
957 pszDirectory &&
958 *pszDirectory)
959 {
960 strcpy(szSavedir, pFM2SaveDirectory);
961 switch_to(pszDirectory);
962 }
963 rc = DosQueryAppType(pszPgm,&ulAppType);
964 if (!strchr(pszPgm, '\\') &&
965 !strchr(pszPgm, ':') &&
966 pszDirectory &&
967 *pszDirectory)
968 switch_to(szSavedir);
969 if (rc) {
970 Dos_Error(MB_CANCEL,rc,hwnd,pszSrcFile,__LINE__,
971 GetPString(IDS_DOSQAPPTYPEFAILEDTEXT),
972 pszPgm, pszCallingFile, uiLineNumber); // 26 May 08 SHL
973 DosFreeMem(pszPgm);
974 if (pszArgs)
975 DosFreeMem(pszArgs);
976 return -1;
977 }
978
979 if (ulAppType) {
980 if (ulAppType & (FAPPTYP_DLL | FAPPTYP_VIRTDRV | FAPPTYP_PHYSDRV | FAPPTYP_PROTDLL))
981 {
982 Runtime_Error(pszSrcFile, __LINE__,
983 GetPString(IDS_APPTYPEUNEXPECTEDTEXT),
984 pszPgm, pszCallingFile, uiLineNumber); // 26 May 08 SHL
985 DosFreeMem(pszPgm);
986 if (pszArgs)
987 DosFreeMem(pszArgs);
988 return -1;
989 }
990 ulAppType &= ~FAPPTYP_BOUND;
991 if (ulAppType & (FAPPTYP_DOS | FAPPTYP_WINDOWSREAL | FAPPTYP_WINDOWSPROT | FAPPTYP_WINDOWSPROT31))
992 {
993 if (ulAppType & (FAPPTYP_WINDOWSREAL | FAPPTYP_WINDOWSPROT | FAPPTYP_WINDOWSPROT31))
994 {
995 if (~type & FULLSCREEN &&
996 ulAppType & (FAPPTYP_WINDOWSREAL | FAPPTYP_WINDOWSPROT | FAPPTYP_WINDOWSPROT31))
997 {
998 ret = RunSeamless(pszPgm, pszArgs, hwnd);
999 if (pszPgm)
1000 DosFreeMem(pszPgm);
1001 if (pszArgs)
1002 DosFreeMem(pszArgs);
1003 return ret ? 0 : -1;
1004 }
1005 else {
1006 strcat(pszPgm, " ");
1007 strcat(pszPgm, pszArgs);
1008 *pszArgs = 0;
1009 if (ulAppType & (FAPPTYP_WINDOWSPROT | FAPPTYP_WINDOWSREAL | FAPPTYP_WINDOWSPROT31))
1010 strcat(pszArgs, "/3 ");
1011 strcat(pszArgs, pszPgm);
1012 strcpy(pszPgm, "WINOS2.COM");
1013 }
1014 }
1015 else {
1016 if (~type & FULLSCREEN) {
1017 type |= WINDOWED;
1018 ulAppType = SSF_TYPE_WINDOWEDVDM;
1019 }
1020 else {
1021 type &= ~WINDOWED;
1022 ulAppType = SSF_TYPE_VDM;
1023 }
1024 }
1025 }
1026 else if (ulAppType & FAPPTYP_32BIT) {
1027 ulAppType &= ~FAPPTYP_32BIT;
1028 if (ulAppType == FAPPTYP_WINDOWAPI)
1029 ulAppType = SSF_TYPE_PM;
1030 else if (ulAppType == FAPPTYP_WINDOWCOMPAT)
1031 ulAppType = SSF_TYPE_WINDOWABLEVIO;
1032 else if (ulAppType == FAPPTYP_NOTWINDOWCOMPAT) {
1033 ulAppType = SSF_TYPE_FULLSCREEN;
1034 type &= ~WINDOWED;
1035 type |= FULLSCREEN;
1036 }
1037 else /* ? */
1038 ulAppType = SSF_TYPE_WINDOWABLEVIO;
1039 }
1040 else if (ulAppType == FAPPTYP_WINDOWAPI)
1041 ulAppType = SSF_TYPE_PM;
1042 else if (ulAppType == FAPPTYP_WINDOWCOMPAT)
1043 ulAppType = SSF_TYPE_WINDOWABLEVIO;
1044 else if (ulAppType == FAPPTYP_NOTWINDOWCOMPAT) {
1045 type &= ~WINDOWED;
1046 ulAppType = SSF_TYPE_FULLSCREEN;
1047 }
1048 else
1049 ulAppType = SSF_TYPE_DEFAULT;
1050 if ((type & FULLSCREEN || ~type & WINDOWED) &&
1051 ulAppType == SSF_TYPE_WINDOWABLEVIO)
1052 {
1053 ulAppType = SSF_TYPE_FULLSCREEN;
1054 }
1055 // fixme parens?
1056 else if (type & FULLSCREEN ||
1057 (type & WINDOWED && ulAppType == SSF_TYPE_WINDOWEDVDM))
1058 {
1059 ulAppType = SSF_TYPE_VDM;
1060 }
1061 }
1062 if (ulAppType == SSF_TYPE_WINDOWEDVDM && type & SEPARATEKEEP) {
1063 type &= ~SEPARATEKEEP;
1064 type |= SEPARATE;
1065 }
1066
1067 DosGetInfoBlocks(&ptib, &ppib);
1068
1069 if (~type & WAIT)
1070 useTermQ = FALSE;
1071 else {
1072 rc = 0;
1073 DosEnterCritSec();
1074 if (!hTermQ) {
1075 // Create term queue and event semaphore just once
1076 sprintf(szTermQName, TERMQ_BASE_NAME "_%x", ppib->pib_ulpid);
1077 rc = DosCreateQueue(&hTermQ, QUE_FIFO | QUE_CONVERT_ADDRESS, szTermQName);
1078 if (rc) {
1079 hTermQ = (HQUEUE)0; // Try to survive
1080 DosExitCritSec();
1081 Dos_Error(MB_CANCEL,rc,hwnd,pszSrcFile,__LINE__,"DosCreateQueue");
1082 }
1083 else {
1084 rc = DosCreateEventSem(NULL,(PHEV)&hWaitChildSem,0,FALSE);
1085 if (rc) {
1086 hWaitChildSem = (HEV)0; // Try to survive
1087 DosCloseQueue(hTermQ);
1088 hTermQ = (HQUEUE)0; // Try to survive
1089 DosExitCritSec();
1090 Dos_Error(MB_ENTER,rc,HWND_DESKTOP,pszSrcFile,__LINE__,"DosCreateEventSem");
1091 }
1092 // if (!rc) fprintf(stderr,"%s %d qcreated ptib %x hTermQ %x\n",__FILE__, __LINE__,ptib,hTermQ);
1093 }
1094 } // if 1st time
1095 useTermQ = hTermQ && hWaitChildSem;
1096 if (!rc)
1097 DosExitCritSec();
1098 } // if wait
1099
1100 memset(&sdata,0,sizeof(sdata));
1101 sdata.Length = sizeof(sdata);
1102 sdata.Related = type & (WAIT | CHILD) ? SSF_RELATED_CHILD :
1103 SSF_RELATED_INDEPENDENT;
1104 sdata.FgBg = type & BACKGROUND ? SSF_FGBG_BACK : SSF_FGBG_FORE;
1105 sdata.TraceOpt = SSF_TRACEOPT_NONE;
1106 sdata.PgmName = pszPgm;
1107 if (*pszArgs)
1108 sdata.PgmInputs = pszArgs;
1109 if (useTermQ)
1110 sdata.TermQ = szTermQName;
1111 sdata.Environment = pszEnvironment;
1112 sdata.InheritOpt = SSF_INHERTOPT_PARENT;
1113 sdata.SessionType = ulAppType;
1114 sdata.ObjectBuffer = szObject;
1115 sdata.ObjectBuffLen = sizeof(szObject);
1116 if ((type & RUNTYPE_MASK) == SEPARATEKEEP)
1117 sdata.PgmControl |= SSF_CONTROL_NOAUTOCLOSE;
1118 if (type & MAXIMIZED)
1119 sdata.PgmControl |= SSF_CONTROL_MAXIMIZE;
1120 if (type & MINIMIZED)
1121 sdata.PgmControl |= SSF_CONTROL_MINIMIZE;
1122 if (type & INVISIBLE)
1123 sdata.PgmControl |= SSF_CONTROL_INVISIBLE;
1124
1125 if (pszDirectory && *pszDirectory) {
1126 strcpy(szSavedir, pFM2SaveDirectory);
1127 switch_to(pszDirectory);
1128 }
1129
1130 // printf("%s %d DosStartsession thread 0x%x data\n ",
1131 // __FILE__, __LINE__,ptib->tib_ordinal); fflush(stdout); // 10 Mar 07 SHL hang
1132 // printf(" %d %d %d %s %s %s %d %d\n %s %x %x\n",
1133 // sdata.Length , sdata.Related, sdata.FgBg, sdata.PgmName,
1134 // sdata.PgmInputs, sdata.TermQ, sdata.InheritOpt,
1135 // sdata.SessionType, szTermQName,
1136 // hTermQ, hWaitChildSem); fflush(stdout);
1137 ret = DosStartSession(&sdata, &ulSessID, &sessPID);
1138
1139 // if (type & WAIT) {
1140 // printf("%s %d DosStartession thread 0x%x rc = %d sess = %u pid = 0x%x\n",
1141 // __FILE__, __LINE__, ptib->tib_ordinal,ret, ulSessID, sessPID); fflush(stdout); // 10 Mar 07 SHL hang
1142 // }
1143 // else {
1144 // printf("%s %d DosStartession thread 0x%x nowait rc = %d\n",
1145 // __FILE__, __LINE__, ptib->tib_ordinal,ret); fflush(stdout); // 10 Mar 07 SHL hang
1146 // }
1147
1148 if (pszDirectory && *pszDirectory)
1149 switch_to(szSavedir);
1150
1151 if (ret && ret != ERROR_SMG_START_IN_BACKGROUND) {
1152 Dos_Error(MB_CANCEL,ret,hwnd,pszSrcFile,__LINE__,
1153 GetPString(IDS_DOSSTARTSESSIONFAILEDTEXT),pszPgm,pszArgs,
1154 pszCallingFile, uiLineNumber); // 26 May 08 SHL
1155 }
1156 else if (type & WAIT) {
1157 if (!(type & (BACKGROUND | MINIMIZED | INVISIBLE)))
1158 ShowSession(hwnd, sessPID);
1159
1160 if (!useTermQ) {
1161 STATUSDATA sd;
1162 // Could not create queue - fallback - fixme to be gone?
1163 // printf("%s %d waiting wo/termq\n", __FILE__, __LINE__); fflush(stdout); // 12 Mar 07 SHL hang
1164
1165 memset(&sd, 0, sizeof(sd));
1166 sd.Length = (USHORT) sizeof(sd);
1167 sd.SelectInd = SET_SESSION_UNCHANGED;
1168 sd.BondInd = SET_SESSION_UNCHANGED;
1169 for (ctr = 0;; ctr++)
1170 {
1171 DosSleep(100);//05 Aug 07 GKY 200
1172 if (DosSetSession(ulSessID, &sd)) // Check if session gone (i.e. finished)
1173 break;
1174 if (ctr > 20) {
1175 // printf("%s %d thread 0x%x showing slow sess %u pid 0x%x\n",
1176 // __FILE__, __LINE__,ptib->tib_ordinal,ulSessID,sessPID); fflush(stdout); // 12 Mar 07 SHL
1177 ShowSession(hwnd, sessPID); // Show every 2 seconds
1178 ctr = 0;
1179 }
1180 }
1181 }
1182 else {
1183 ULONG clPosted;
1184
1185 DosResetEventSem(hWaitChildSem, &clPosted);
1186 for (ctr = 0;; ctr++)
1187 {
1188 if (ctr < 20) {
1189 rc = DosReadQueue(hTermQ, &rq, &ulLength, (PPVOID)&pTermInfo, 0,
1190 DCWW_NOWAIT, &bPriority, hWaitChildSem);
1191 if (rc == ERROR_QUE_EMPTY) {
1192 DosSleep(50);//05 Aug 07 GKY 100
1193 continue;
1194 }
1195 }
1196 else {
1197 if (ctr == 20) {
1198 // printf("%s %d thread 0x%x showing slow sess %u pid 0x%x\n",
1199 // __FILE__, __LINE__,ptib->tib_ordinal,ulSessID,sessPID); fflush(stdout);
1200 ShowSession(hwnd, sessPID); // Show long running session
1201 }
1202 rc = DosReadQueue(hTermQ, &rq, &ulLength, (PPVOID)&pTermInfo, 0,
1203 DCWW_WAIT, &bPriority, 0);
1204 }
1205
1206 if (rc) {
1207 // Oh heck
1208 Dos_Error(MB_CANCEL,rc,hwnd,pszSrcFile,__LINE__,"DosReadQueue");
1209 DosSleep(100);//05 Aug 07 GKY 500
1210 continue;
1211 }
1212
1213 //printf("%s %d DosReadQueue thread 0x%x sess %u sessRC %u rq.pid 0x%x rq.data 0x%x\n",
1214 // __FILE__, __LINE__,ptib->tib_ordinal,pTermInfo->usSessID,pTermInfo->usRC,rq.pid, rq.ulData); fflush(stdout);
1215
1216 if (pTermInfo->usSessID == ulSessID) {
1217 DosPostEventSem(hWaitChildSem); //Posted to WaitChildThread (arccnrs.c)
1218 break; // Our session is done
1219 }
1220
1221 // Requeue session for other thread
1222 {
1223 static ULONG ulLastSessID;
1224 // printf("%s %d requeue thread 0x%x our sess %u term sess %u term rc %u\n",
1225 // __FILE__, __LINE__,ptib->tib_ordinal,ulSessID,pTermInfo->usSessID,pTermInfo->usRC); fflush(stdout);
1226 // fixme to be gone when no longer needed for debug?
1227 if (ulLastSessID) {
1228 DosSleep(100);//05 Aug 07 GKY 500
1229 ulLastSessID = pTermInfo->usSessID;
1230 }
1231 // requeue term report for other thread and do not free yet
1232 rc = DosWriteQueue(hTermQ, rq.ulData, ulLength,(PVOID)pTermInfo, bPriority);
1233 if (rc)
1234 Dos_Error(MB_CANCEL,rc,hwnd,pszSrcFile,__LINE__,"DosWriteQueue");
1235 DosSleep(50); //05 Aug 07 GKY 100 // Let other thread see queue entry
1236 }
1237 } // for
1238
1239 ret = pTermInfo->usRC == 0; // Set 1 if rc 0 else 0
1240 // printf("%s %d thread 0x%x term for sess %u\n",
1241 // __FILE__, __LINE__,ptib->tib_ordinal,ulSessID);fflush(stdout);
1242 DosFreeMem(pTermInfo);
1243 }
1244 } // if wait
1245 else if (!(type & (BACKGROUND | MINIMIZED | INVISIBLE)))
1246 ShowSession(hwnd, sessPID);
1247 }
1248 }
1249
1250ObjectInterrupt:
1251
1252 if (pszPgm)
1253 DosFreeMem(pszPgm);
1254 if (pszArgs)
1255 DosFreeMem(pszArgs);
1256
1257 return ret;
1258}
1259
1260//== Exec() Start application with WinStartApp ==
1261#if 0 // JBS 11 Sep 08
1262HAPP Exec(HWND hwndNotify, BOOL child, char *startdir, char *env,
1263 PROGTYPE *progt, ULONG fl, char *formatstring,...)
1264{
1265 PROGDETAILS pgd;
1266 register char *p;
1267 char *parameters = NULL, *executable = NULL;
1268 HAPP happ = (HAPP)0;
1269 ULONG ulOptions = SAF_INSTALLEDCMDLINE;
1270 BOOL wasquote;
1271 va_list parguments;
1272
1273 if (child)
1274 ulOptions |= SAF_STARTCHILDAPP;
1275
1276 executable = xmallocz(MaxComLineStrg, pszSrcFile, __LINE__);
1277 if (executable) {
1278 va_start(parguments, formatstring);
1279 vsprintf(executable, formatstring, parguments);
1280 va_end(parguments);
1281 strip_lead_char(" \t", executable);
1282 if (*executable) {
1283 parameters = xmalloc(MaxComLineStrg, pszSrcFile, __LINE__);
1284 if (parameters) {
1285 p = executable;
1286 wasquote = FALSE;
1287 while (*p && (wasquote || (*p != ' ' && *p != '\t'))) {
1288 if (*p == '\"') {
1289 if (!wasquote) {
1290 wasquote = TRUE;
1291 memmove(p, p + 1, strlen(p));
1292 while (*p == ' ' || *p == '\t')
1293 p++;
1294 }
1295 else {
1296 memmove(p, p + 1, strlen(p));
1297 break;
1298 }
1299 }
1300 else
1301 p++;
1302 }
1303 if (*p) {
1304 *p = 0;
1305 p++;
1306 }
1307 else
1308 p = NullStr;
1309 if (*p)
1310 strcpy(parameters, p);
1311
1312 if (p && (!stricmp(p, ".BAT") || !stricmp(p, ".CMD"))) {
1313 char *temp;
1314
1315 temp = xmalloc(CCHMAXPATH * 2,pszSrcFile,__LINE__);
1316 if (temp) {
1317 if (!stricmp(p, ".BAT")) {
1318 strcpy(temp, executable);
1319 strcpy(executable, parameters);
1320 strcpy(parameters, "/C ");
1321 strcat(parameters, temp);
1322 strcat(parameters, " ");
1323 strcat(parameters, executable);
1324 strcpy(executable, GetCmdSpec(TRUE));
1325 }
1326 else if (!stricmp(p, ".CMD")) {
1327 strcpy(temp, executable);
1328 strcpy(executable, parameters);
1329 strcpy(parameters, "/C ");
1330 strcat(parameters, temp);
1331 strcat(parameters, " ");
1332 strcat(parameters, executable);
1333 strcpy(executable, GetCmdSpec(FALSE));
1334 }
1335 free(temp);
1336 }
1337 }
1338
1339 memset(&pgd, 0, sizeof(pgd));
1340 pgd.Length = sizeof(pgd);
1341 pgd.progt = *progt;
1342 pgd.swpInitial.fl = fl;
1343 pgd.pszEnvironment = env;
1344 pgd.pszStartupDir = startdir;
1345 pgd.pszParameters = *parameters ? parameters : NULL;
1346 pgd.pszExecutable = executable;
1347 pgd.swpInitial.hwndInsertBehind = HWND_TOP;
1348 happ = WinStartApp(hwndNotify, &pgd, NULL, NULL, ulOptions);
1349 free(parameters);
1350 }
1351 }
1352 free(executable);
1353 }
1354 return happ;
1355}
1356#endif
1357#pragma alloc_text(SYSTEMF,ShowSession,ExecOnList,runemf2)
Note: See TracBrowser for help on using the repository browser.