source: trunk/dll/systemf.c@ 773

Last change on this file since 773 was 773, checked in by Steven Levine, 18 years ago

Correct some compare directories collector nits
Use BldQuoted... functions
Move BldQuoted... functions near primary callers
Add RUNTYPE_MASK
Use Runtime_Error2 more

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