source: trunk/dll/systemf.c@ 793

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

Move #pragma alloc_text to end for OpenWatcom compat

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