source: trunk/dll/systemf.c@ 1200

Last change on this file since 1200 was 1193, checked in by John Small, 17 years ago

Improved comment on new "#if 0" lines.

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