source: trunk/dll/systemf.c@ 893

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

Remark out quoting code in runemf; Cleanup of dialog update for mailrun; Enlarge VIEWDATA color array to include new mailrun colors which of course fixed the memfree crashes.

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