source: trunk/dll/systemf.c@ 1375

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

Updated history; comments minor code cleanup for recent changes

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