source: trunk/dll/systemf.c@ 1213

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

Ticket 187: Move data declarations/definitions out of fm3dll.h

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