source: trunk/dll/systemf.c@ 1348

Last change on this file since 1348 was 1348, checked in by Gregg Young, 17 years ago

More code cleanup

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