source: trunk/dll/systemf.c@ 888

Last change on this file since 888 was 888, checked in by Gregg Young, 18 years ago

runemf2 now quotes executable strings if needed (Ticket 180); it also reports where it was called from on errors

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