source: trunk/dll/systemf.c@ 775

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

Minor clean up add comments re recent changes

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