source: trunk/dll/systemf.c@ 771

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

Increase subject to 1024 reduce DosSleep times

  • 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 771 2007-08-06 03:05:35Z 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
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 & 15) == SYNCHRONOUS ||
734 (type & 15) == ASYNCHRONOUS ||
735 (type & 15) == 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 & 15) == ASYNCHRONOUS ? EXEC_ASYNC : 0) +
829 ((type & 15) == 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 & 15) == 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.