source: trunk/dll/systemf.c@ 889

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

Fix crash in runemf2 quote check code when program sring in capitals

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 31.7 KB
Line 
1
2/***********************************************************************
3
4 $Id: systemf.c 889 2007-12-24 02:17:16Z 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[2048], temparg[2048], 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(strlwr(pszPgm), ".exe");
688 offsetcmd = strstr(strlwr(pszPgm), ".cmd");
689 offsetcom = strstr(strlwr(pszPgm), ".com");
690 offsetbtm = strstr(strlwr(pszPgm), ".btm");
691 offsetbat = strstr(strlwr(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 Dos_Error(MB_CANCEL,rc,hwnd,pszSrcFile,__LINE__,GetPString(IDS_NOTDIRECTEXETEXT));
704 return -1;
705 }
706 offsetquote = strcspn(pszPgm, buf);
707 if (pszPgm[0] != '\"' && offsetquote < offset - pszPgm && offsetquote != NULL){
708 strcpy(tempcom, pszPgm);
709 tempcom[offset + 4 - pszPgm] = '\0';
710 strcpy (temparg, &pszPgm[offset + 4 - pszPgm]);
711 pszDirectory = szTempdir;
712 strcpy(pszDirectory, tempcom);
713 offset = strrchr(pszDirectory, '\\');
714 pszDirectory[offset +1 - pszDirectory] = '\0';
715 BldQuotedFileName(szTempPgm, tempcom);
716 strcat(szTempPgm, temparg);
717 memcpy(pszPgm, szTempPgm, 2048);
718 //printf("%s\n %s\n%s %s\n %d %d",
719 // pszPgm, szTempPgm, tempcom, temparg, offset, offsetquote); fflush(stdout);
720 }
721 if (pszEnvironment) {
722 p = &pszEnvironment[strlen(pszEnvironment)] + 1;
723 *p = 0;
724 p = pszEnvironment;
725 while ((p = convert_nl_to_nul(p)) != NULL)
726 ; // loop
727 }
728
729 if (!*pszPgm) {
730 p = GetCmdSpec(FALSE);
731 strcpy(pszPgm, p);
732 if (!*pszPgm) {
733 Runtime_Error2(pszSrcFile, __LINE__, IDS_NODATATEXT);
734 return -1;
735 }
736 }
737
738 if (*pszPgm) {
739 if (*pszPgm == '<' && strchr(pszPgm, '>')) {
740 /* is a workplace object */
741 HOBJECT hWPSObject;
742 char temp;
743
744 p = strchr(pszPgm, '>');
745 p++;
746 temp = *p;
747 if (temp) {
748 rc = DosAllocMem((PVOID)&pszArgs,
749 MAXSTRG * 2,
750 PAG_COMMIT | OBJ_TILE | PAG_READ | PAG_WRITE);
751 if (rc)
752 Dos_Error(MB_CANCEL,rc,hwnd,pszSrcFile,__LINE__,GetPString(IDS_OUTOFMEMORY));
753 }
754 else
755 pszArgs = NULL;
756 *p = 0;
757 /* Find the handle of the WPS object */
758 hWPSObject = WinQueryObject(pszPgm);
759 *p = temp;
760 if (hWPSObject != NULLHANDLE) {
761 if (pszArgs && *p) {
762 sprintf(pszArgs,"OPEN=DEFAULT;PARAMETERS=\"%s\"",p);
763 WinSetObjectData(hWPSObject,pszArgs);
764 }
765 else
766 WinSetObjectData(hWPSObject,"OPEN=DEFAULT");
767 ret = 0;
768 }
769 goto ObjectInterrupt;
770 }
771
772 if ((type & RUNTYPE_MASK) == SYNCHRONOUS ||
773 (type & RUNTYPE_MASK) == ASYNCHRONOUS ||
774 (type & RUNTYPE_MASK) == DETACHED)
775 {
776 strip_lead_char(" \t", pszPgm);
777 p = pszPgm;
778 wasquote = FALSE;
779 while (*p &&
780 (wasquote ||
781 (*p != ' ' &&
782 *p != '\t')))
783 {
784 if (*p == '\"') {
785 if (!wasquote) {
786 wasquote = TRUE;
787 memmove(p,
788 p + 1,
789 strlen(p));
790 while (*p == ' ' ||
791 *p == '\t')
792 p++;
793 }
794 else {
795 memmove(p,
796 p + 1,
797 strlen(p));
798 break;
799 }
800 }
801 else
802 p++;
803 }
804 if (*p) {
805 *p = 0;
806 p++;
807 }
808 else
809 p = pszPgm;
810 p[strlen(p) + 1] = 0; /* double-terminate args */
811 if (*pszPgm) {
812 if (!strchr(pszPgm, '\\') &&
813 !strchr(pszPgm, ':') &&
814 pszDirectory &&
815 *pszDirectory)
816 {
817 save_dir2(szSavedir);
818 switch_to(pszDirectory);
819 }
820 rc = DosQueryAppType(pszPgm,&ulAppType);
821 if (!strchr(pszPgm, '\\') &&
822 !strchr(pszPgm, ':') &&
823 pszDirectory &&
824 *pszDirectory)
825 switch_to(szSavedir);
826 if (rc) {
827 Dos_Error(MB_CANCEL,rc,hwnd,pszSrcFile,__LINE__,
828 GetPString(IDS_DOSQAPPTYPEFAILEDTEXT),
829 pszPgm, pszCallingFile, __LINE__);
830 DosFreeMem(pszPgm);
831 if (pszArgs)
832 DosFreeMem(pszArgs);
833 return -1;
834 }
835 if (ulAppType) {
836 if (ulAppType & FAPPTYP_DLL || ulAppType & FAPPTYP_VIRTDRV ||
837 ulAppType & FAPPTYP_PHYSDRV || ulAppType & FAPPTYP_PROTDLL)
838 {
839 Runtime_Error(pszSrcFile, __LINE__,
840 GetPString(IDS_APPTYPEUNEXPECTEDTEXT),
841 ulAppType, pszPgm, pszCallingFile, __LINE__);
842 if (pszPgm)
843 DosFreeMem(pszPgm);
844 if (pszArgs)
845 DosFreeMem(pszArgs);
846 return -1;
847 }
848 if (ulAppType & FAPPTYP_DOS || ulAppType & FAPPTYP_WINDOWSREAL ||
849 ulAppType & FAPPTYP_WINDOWSPROT || ulAppType & FAPPTYP_WINDOWSPROT31)
850 {
851 Runtime_Error(pszSrcFile, __LINE__,
852 GetPString(IDS_APPTYPEUNEXPECTEDTEXT),
853 ulAppType, pszPgm, pszCallingFile, __LINE__);
854 if (pszPgm)
855 DosFreeMem(pszPgm);
856 if (pszArgs)
857 DosFreeMem(pszArgs);
858 return -1;
859 }
860 }
861 memset(&results, 0, sizeof(results));
862 if (pszDirectory && *pszDirectory) {
863 save_dir2(szSavedir);
864 switch_to(pszDirectory);
865 }
866 ret = DosExecPgm(szObject, sizeof(szObject),
867 ((type & RUNTYPE_MASK) == ASYNCHRONOUS ? EXEC_ASYNC : 0) +
868 ((type & RUNTYPE_MASK) == DETACHED ? EXEC_BACKGROUND : 0),
869 pszPgm, pszEnvironment, &results, pszPgm);
870 if (pszDirectory && *pszDirectory)
871 switch_to(szSavedir);
872 if (ret) {
873 Dos_Error(MB_ENTER,ret,hwnd,pszSrcFile,__LINE__,
874 GetPString(IDS_DOSEXECPGMFAILEDTEXT), pszPgm,
875 pszCallingFile, __LINE__);
876 }
877 }
878 }
879 else {
880 if (~type & FULLSCREEN)
881 type |= WINDOWED;
882 rc = DosAllocMem((PVOID) & pszArgs, MAXSTRG * 2,
883 PAG_COMMIT | OBJ_TILE | PAG_READ | PAG_WRITE);
884 if (rc) {
885 Dos_Error(MB_CANCEL,rc,hwnd,pszSrcFile,__LINE__,GetPString(IDS_OUTOFMEMORY));
886 DosFreeMem(pszPgm);
887 return -1;
888 }
889 *pszArgs = 0;
890 memset(&sdata, 0, sizeof(sdata));
891 strip_lead_char(" \t", pszPgm);
892 p = pszPgm;
893 wasquote = FALSE;
894 while (*p && (wasquote || (*p != ' ' && *p != '\t'))) {
895 if (*p == '\"') {
896 if (!wasquote) {
897 wasquote = TRUE;
898 memmove(p, p + 1, strlen(p));
899 while (*p == ' ' || *p == '\t')
900 p++;
901 }
902 else {
903 memmove(p, p + 1, strlen(p));
904 break;
905 }
906 }
907 else
908 p++;
909 } // while
910 if (*p) {
911 *p = 0;
912 p++;
913 }
914 else
915 p = NullStr;
916 if (*p)
917 strcpy(pszArgs, p);
918
919 p = strrchr(pszPgm, '.');
920 if (p) {
921 char temp[CCHMAXPATH + 1];
922
923 if (!stricmp(p, ".BAT")) {
924 strcpy(temp, pszPgm);
925 strcpy(pszPgm, pszArgs);
926 strcpy(pszArgs, "/C ");
927 strcat(pszArgs, temp);
928 strcat(pszArgs, " ");
929 strcat(pszArgs, pszPgm);
930 strcpy(pszPgm, GetCmdSpec(TRUE)); // DOS
931 }
932 else if (!stricmp(p, ".CMD") || !stricmp(p, ".BTM")) {
933 // Assume 4OS2 is BTM
934 strcpy(temp, pszPgm);
935 strcpy(pszPgm, pszArgs);
936 strcpy(pszArgs, "/C ");
937 strcat(pszArgs, temp);
938 strcat(pszArgs, " ");
939 strcat(pszArgs, pszPgm);
940 strcpy(pszPgm, GetCmdSpec(FALSE)); // OS/2
941 }
942 }
943
944 // goddamned OS/2 limit
945
946 if (strlen(pszPgm) + strlen(pszArgs) > 1024)
947 pszArgs[1024 - strlen(pszPgm)] = 0;
948
949 if (!strchr(pszPgm, '\\') &&
950 !strchr(pszPgm, ':') &&
951 pszDirectory &&
952 *pszDirectory)
953 {
954 save_dir2(szSavedir);
955 switch_to(pszDirectory);
956 }
957 rc = DosQueryAppType(pszPgm,&ulAppType);
958 if (!strchr(pszPgm, '\\') &&
959 !strchr(pszPgm, ':') &&
960 pszDirectory &&
961 *pszDirectory)
962 switch_to(szSavedir);
963 if (rc){
964 Dos_Error(MB_CANCEL,rc,hwnd,pszSrcFile,__LINE__,
965 GetPString(IDS_DOSQAPPTYPEFAILEDTEXT),
966 pszPgm, pszCallingFile, __LINE__);
967 DosFreeMem(pszPgm);
968 if (pszArgs)
969 DosFreeMem(pszArgs);
970 return -1;
971 }
972
973 if (ulAppType) {
974 if (ulAppType & (FAPPTYP_DLL | FAPPTYP_VIRTDRV | FAPPTYP_PHYSDRV | FAPPTYP_PROTDLL))
975 {
976 Runtime_Error(pszSrcFile, __LINE__,
977 GetPString(IDS_APPTYPEUNEXPECTEDTEXT),
978 pszPgm, pszCallingFile, __LINE__);
979 DosFreeMem(pszPgm);
980 if (pszArgs)
981 DosFreeMem(pszArgs);
982 return -1;
983 }
984 ulAppType &= ~FAPPTYP_BOUND;
985 if (ulAppType & (FAPPTYP_DOS | FAPPTYP_WINDOWSREAL | FAPPTYP_WINDOWSPROT | FAPPTYP_WINDOWSPROT31))
986 {
987 if (ulAppType & (FAPPTYP_WINDOWSREAL | FAPPTYP_WINDOWSPROT | FAPPTYP_WINDOWSPROT31))
988 {
989 if (~type & FULLSCREEN &&
990 ulAppType & (FAPPTYP_WINDOWSREAL | FAPPTYP_WINDOWSPROT | FAPPTYP_WINDOWSPROT31))
991 {
992 ret = RunSeamless(pszPgm, pszArgs, hwnd);
993 if (pszPgm)
994 DosFreeMem(pszPgm);
995 if (pszArgs)
996 DosFreeMem(pszArgs);
997 return ret ? 0 : -1;
998 }
999 else {
1000 strcat(pszPgm, " ");
1001 strcat(pszPgm, pszArgs);
1002 *pszArgs = 0;
1003 if (ulAppType & (FAPPTYP_WINDOWSPROT | FAPPTYP_WINDOWSREAL | FAPPTYP_WINDOWSPROT31))
1004 strcat(pszArgs, "/3 ");
1005 strcat(pszArgs, pszPgm);
1006 strcpy(pszPgm, "WINOS2.COM");
1007 }
1008 }
1009 else {
1010 if (~type & FULLSCREEN) {
1011 type |= WINDOWED;
1012 ulAppType = SSF_TYPE_WINDOWEDVDM;
1013 }
1014 else {
1015 type &= ~WINDOWED;
1016 ulAppType = SSF_TYPE_VDM;
1017 }
1018 }
1019 }
1020 else if (ulAppType & FAPPTYP_32BIT) {
1021 ulAppType &= ~FAPPTYP_32BIT;
1022 if (ulAppType == FAPPTYP_WINDOWAPI)
1023 ulAppType = SSF_TYPE_PM;
1024 else if (ulAppType == FAPPTYP_WINDOWCOMPAT)
1025 ulAppType = SSF_TYPE_WINDOWABLEVIO;
1026 else if (ulAppType == FAPPTYP_NOTWINDOWCOMPAT) {
1027 ulAppType = SSF_TYPE_FULLSCREEN;
1028 type &= ~WINDOWED;
1029 type |= FULLSCREEN;
1030 }
1031 else /* ? */
1032 ulAppType = SSF_TYPE_WINDOWABLEVIO;
1033 }
1034 else if (ulAppType == FAPPTYP_WINDOWAPI)
1035 ulAppType = SSF_TYPE_PM;
1036 else if (ulAppType == FAPPTYP_WINDOWCOMPAT)
1037 ulAppType = SSF_TYPE_WINDOWABLEVIO;
1038 else if (ulAppType == FAPPTYP_NOTWINDOWCOMPAT) {
1039 type &= ~WINDOWED;
1040 ulAppType = SSF_TYPE_FULLSCREEN;
1041 }
1042 else
1043 ulAppType = SSF_TYPE_DEFAULT;
1044 if ((type & FULLSCREEN || ~type & WINDOWED) &&
1045 ulAppType == SSF_TYPE_WINDOWABLEVIO)
1046 {
1047 ulAppType = SSF_TYPE_FULLSCREEN;
1048 }
1049 // fixme parens?
1050 else if (type & FULLSCREEN ||
1051 (type & WINDOWED && ulAppType == SSF_TYPE_WINDOWEDVDM))
1052 {
1053 ulAppType = SSF_TYPE_VDM;
1054 }
1055 }
1056 if (ulAppType == SSF_TYPE_WINDOWEDVDM && type & SEPARATEKEEP) {
1057 type &= ~SEPARATEKEEP;
1058 type |= SEPARATE;
1059 }
1060
1061 DosGetInfoBlocks(&ptib, &ppib);
1062
1063 if (~type & WAIT)
1064 useTermQ = FALSE;
1065 else {
1066 rc = 0;
1067 DosEnterCritSec();
1068 if (!hTermQ) {
1069 // Create term queue and event semaphore just once
1070 sprintf(szTermQName, TERMQ_BASE_NAME "_%x", ppib->pib_ulpid);
1071 rc = DosCreateQueue(&hTermQ, QUE_FIFO | QUE_CONVERT_ADDRESS, szTermQName);
1072 if (rc) {
1073 hTermQ = (HQUEUE)0; // Try to survive
1074 DosExitCritSec();
1075 Dos_Error(MB_CANCEL,rc,hwnd,pszSrcFile,__LINE__,"DosCreateQueue");
1076 }
1077 else {
1078 rc = DosCreateEventSem(NULL,(PHEV)&hTermQSem,0,FALSE);
1079 if (rc) {
1080 hTermQSem = (HEV)0; // Try to survive
1081 DosCloseQueue(hTermQ);
1082 hTermQ = (HQUEUE)0; // Try to survive
1083 DosExitCritSec();
1084 Dos_Error(MB_ENTER,rc,HWND_DESKTOP,pszSrcFile,__LINE__,"DoCreateEventSem");
1085 }
1086 // if (!rc) fprintf(stderr,"%s %d qcreated ptib %x hTermQ %x\n",__FILE__, __LINE__,ptib,hTermQ);
1087 }
1088 } // if 1st time
1089 useTermQ = hTermQ && hTermQSem;
1090 if (!rc)
1091 DosExitCritSec();
1092 } // if wait
1093
1094 memset(&sdata,0,sizeof(sdata));
1095 sdata.Length = sizeof(sdata);
1096 sdata.Related = type & (WAIT | CHILD) ? SSF_RELATED_CHILD :
1097 SSF_RELATED_INDEPENDENT;
1098 sdata.FgBg = type & BACKGROUND ? SSF_FGBG_BACK : SSF_FGBG_FORE;
1099 sdata.TraceOpt = SSF_TRACEOPT_NONE;
1100 sdata.PgmName = pszPgm;
1101 if (*pszArgs)
1102 sdata.PgmInputs = pszArgs;
1103 if (useTermQ)
1104 sdata.TermQ = szTermQName;
1105 sdata.Environment = pszEnvironment;
1106 sdata.InheritOpt = SSF_INHERTOPT_PARENT;
1107 sdata.SessionType = ulAppType;
1108 sdata.ObjectBuffer = szObject;
1109 sdata.ObjectBuffLen = sizeof(szObject);
1110 if ((type & RUNTYPE_MASK) == SEPARATEKEEP)
1111 sdata.PgmControl |= SSF_CONTROL_NOAUTOCLOSE;
1112 if (type & MAXIMIZED)
1113 sdata.PgmControl |= SSF_CONTROL_MAXIMIZE;
1114 if (type & MINIMIZED)
1115 sdata.PgmControl |= SSF_CONTROL_MINIMIZE;
1116 if (type & INVISIBLE)
1117 sdata.PgmControl |= SSF_CONTROL_INVISIBLE;
1118
1119 if (pszDirectory && *pszDirectory) {
1120 save_dir2(szSavedir);
1121 switch_to(pszDirectory);
1122 }
1123
1124 // printf("%s %d DosStartsession thread 0x%x data\n ",
1125 // __FILE__, __LINE__,ptib->tib_ordinal); fflush(stdout); // 10 Mar 07 SHL hang
1126 // printf(" %d %d %d %s %s %s %d %d\n %s %x %x\n",
1127 // sdata.Length , sdata.Related, sdata.FgBg, sdata.PgmName,
1128 // sdata.PgmInputs, sdata.TermQ, sdata.InheritOpt,
1129 // sdata.SessionType, szTermQName,
1130 // hTermQ, hTermQSem); fflush(stdout);
1131 ret = DosStartSession(&sdata, &ulSessID, &sessPID);
1132
1133 // if (type & WAIT) {
1134 // printf("%s %d DosStartession thread 0x%x rc = %d sess = %u pid = 0x%x\n",
1135 // __FILE__, __LINE__, ptib->tib_ordinal,ret, ulSessID, sessPID); fflush(stdout); // 10 Mar 07 SHL hang
1136 // }
1137 // else {
1138 // printf("%s %d DosStartession thread 0x%x nowait rc = %d\n",
1139 // __FILE__, __LINE__, ptib->tib_ordinal,ret); fflush(stdout); // 10 Mar 07 SHL hang
1140 // }
1141
1142 if (pszDirectory && *pszDirectory)
1143 switch_to(szSavedir);
1144
1145 if (ret && ret != ERROR_SMG_START_IN_BACKGROUND) {
1146 Dos_Error(MB_CANCEL,ret,hwnd,pszSrcFile,__LINE__,
1147 GetPString(IDS_DOSSTARTSESSIONFAILEDTEXT),pszPgm,pszArgs,
1148 pszCallingFile, __LINE__);
1149 }
1150 else if (type & WAIT) {
1151 if (!(type & (BACKGROUND | MINIMIZED | INVISIBLE)))
1152 ShowSession(hwnd, sessPID);
1153
1154 if (!useTermQ) {
1155 STATUSDATA sd;
1156 // Could not create queue - fallback - fixme to be gone?
1157 // printf("%s %d waiting wo/termq\n", __FILE__, __LINE__); fflush(stdout); // 12 Mar 07 SHL hang
1158
1159 memset(&sd, 0, sizeof(sd));
1160 sd.Length = (USHORT) sizeof(sd);
1161 sd.SelectInd = SET_SESSION_UNCHANGED;
1162 sd.BondInd = SET_SESSION_UNCHANGED;
1163 for (ctr = 0;; ctr++)
1164 {
1165 DosSleep(100);//05 Aug 07 GKY 200
1166 if (DosSetSession(ulSessID, &sd)) // Check if session gone (i.e. finished)
1167 break;
1168 if (ctr > 10) {
1169 // printf("%s %d thread 0x%x showing slow sess %u pid 0x%x\n",
1170 // __FILE__, __LINE__,ptib->tib_ordinal,ulSessID,sessPID); fflush(stdout); // 12 Mar 07 SHL
1171 ShowSession(hwnd, sessPID); // Show every 2 seconds
1172 ctr = 0;
1173 }
1174 }
1175 }
1176 else {
1177 for (ctr = 0;; ctr++)
1178 {
1179 if (ctr < 20) {
1180 rc = DosReadQueue(hTermQ, &rq, &ulLength, (PPVOID)&pTermInfo, 0,
1181 DCWW_NOWAIT, &bPriority, hTermQSem);
1182 if (rc == ERROR_QUE_EMPTY) {
1183 DosSleep(50);//05 Aug 07 GKY 100
1184 continue;
1185 }
1186 }
1187 else {
1188 if (ctr == 20) {
1189 // printf("%s %d thread 0x%x showing slow sess %u pid 0x%x\n",
1190 // __FILE__, __LINE__,ptib->tib_ordinal,ulSessID,sessPID); fflush(stdout);
1191 ShowSession(hwnd, sessPID); // Show long running session
1192 }
1193 rc = DosReadQueue(hTermQ, &rq, &ulLength, (PPVOID)&pTermInfo, 0,
1194 DCWW_WAIT, &bPriority, 0);
1195 }
1196
1197 if (rc) {
1198 // Oh heck
1199 Dos_Error(MB_CANCEL,rc,hwnd,pszSrcFile,__LINE__,"DosReadQueue");
1200 DosSleep(100);//05 Aug 07 GKY 500
1201 continue;
1202 }
1203
1204 // printf("%s %d DosReadQueue thread 0x%x sess %u sessRC %u rq.pid 0x%x rq.data 0x%x\n",
1205 // __FILE__, __LINE__,ptib->tib_ordinal,pTermInfo->usSessID,pTermInfo->usRC,rq.pid, rq.ulData); fflush(stdout);
1206
1207 if (pTermInfo->usSessID == ulSessID)
1208 break; // Our session is done
1209
1210 // Requeue session for other thread
1211 {
1212 static ULONG ulLastSessID;
1213 // printf("%s %d requeue thread 0x%x our sess %u term sess %u term rc %u\n",
1214 // __FILE__, __LINE__,ptib->tib_ordinal,ulSessID,pTermInfo->usSessID,pTermInfo->usRC); fflush(stdout);
1215 // fixme to be gone when no longer needed for debug?
1216 if (ulLastSessID) {
1217 DosSleep(100);//05 Aug 07 GKY 500
1218 ulLastSessID = pTermInfo->usSessID;
1219 }
1220 // requeue term report for other thread and do not free yet
1221 rc = DosWriteQueue(hTermQ, rq.ulData, ulLength,(PVOID)pTermInfo, bPriority);
1222 if (rc)
1223 Dos_Error(MB_CANCEL,rc,hwnd,pszSrcFile,__LINE__,"DosWriteQueue");
1224 DosSleep(50); //05 Aug 07 GKY 100 // Let other thread see queue entry
1225 }
1226 } // for
1227
1228 ret = pTermInfo->usRC == 0; // Set 1 if rc 0 else 0
1229 // printf("%s %d thread 0x%x term for sess %u\n",
1230 // __FILE__, __LINE__,ptib->tib_ordinal,ulSessID);fflush(stdout);
1231 DosFreeMem(pTermInfo);
1232 }
1233 } // if wait
1234 else if (!(type & (BACKGROUND | MINIMIZED | INVISIBLE)))
1235 ShowSession(hwnd, sessPID);
1236 }
1237 }
1238
1239ObjectInterrupt:
1240
1241 if (pszPgm)
1242 DosFreeMem(pszPgm);
1243 if (pszArgs)
1244 DosFreeMem(pszArgs);
1245
1246 return ret;
1247}
1248
1249//== Exec() Start application with WinStartApp ==
1250
1251HAPP Exec(HWND hwndNotify, BOOL child, char *startdir, char *env,
1252 PROGTYPE *progt, ULONG fl, char *formatstring,...)
1253{
1254 PROGDETAILS pgd;
1255 register char *p;
1256 char *parameters = NULL, *executable = NULL;
1257 HAPP happ = (HAPP)0;
1258 ULONG ulOptions = SAF_INSTALLEDCMDLINE;
1259 BOOL wasquote;
1260 va_list parguments;
1261
1262 if (child)
1263 ulOptions |= SAF_STARTCHILDAPP;
1264
1265 executable = xmallocz(MAXSTRG,pszSrcFile,__LINE__);
1266 if (executable) {
1267 va_start(parguments, formatstring);
1268 vsprintf(executable, formatstring, parguments);
1269 va_end(parguments);
1270 strip_lead_char(" \t", executable);
1271 if (*executable) {
1272 parameters = xmalloc(MAXSTRG,pszSrcFile,__LINE__);
1273 if (parameters) {
1274 p = executable;
1275 wasquote = FALSE;
1276 while (*p && (wasquote || (*p != ' ' && *p != '\t'))) {
1277 if (*p == '\"') {
1278 if (!wasquote) {
1279 wasquote = TRUE;
1280 memmove(p, p + 1, strlen(p));
1281 while (*p == ' ' || *p == '\t')
1282 p++;
1283 }
1284 else {
1285 memmove(p, p + 1, strlen(p));
1286 break;
1287 }
1288 }
1289 else
1290 p++;
1291 }
1292 if (*p) {
1293 *p = 0;
1294 p++;
1295 }
1296 else
1297 p = NullStr;
1298 if (*p)
1299 strcpy(parameters, p);
1300
1301 if (p && (!stricmp(p, ".BAT") || !stricmp(p, ".CMD"))) {
1302 char *temp;
1303
1304 temp = xmalloc(CCHMAXPATH * 2,pszSrcFile,__LINE__);
1305 if (temp) {
1306 if (!stricmp(p, ".BAT")) {
1307 strcpy(temp, executable);
1308 strcpy(executable, parameters);
1309 strcpy(parameters, "/C ");
1310 strcat(parameters, temp);
1311 strcat(parameters, " ");
1312 strcat(parameters, executable);
1313 strcpy(executable, GetCmdSpec(TRUE));
1314 }
1315 else if (!stricmp(p, ".CMD")) {
1316 strcpy(temp, executable);
1317 strcpy(executable, parameters);
1318 strcpy(parameters, "/C ");
1319 strcat(parameters, temp);
1320 strcat(parameters, " ");
1321 strcat(parameters, executable);
1322 strcpy(executable, GetCmdSpec(FALSE));
1323 }
1324 free(temp);
1325 }
1326 }
1327
1328 memset(&pgd, 0, sizeof(pgd));
1329 pgd.Length = sizeof(pgd);
1330 pgd.progt = *progt;
1331 pgd.swpInitial.fl = fl;
1332 pgd.pszEnvironment = env;
1333 pgd.pszStartupDir = startdir;
1334 pgd.pszParameters = *parameters ? parameters : NULL;
1335 pgd.pszExecutable = executable;
1336 pgd.swpInitial.hwndInsertBehind = HWND_TOP;
1337 happ = WinStartApp(hwndNotify, &pgd, NULL, NULL, ulOptions);
1338 free(parameters);
1339 }
1340 }
1341 free(executable);
1342 }
1343 return happ;
1344}
1345
1346#pragma alloc_text(SYSTEMF,ShowSession,ExecOnList,runemf2)
Note: See TracBrowser for help on using the repository browser.