source: trunk/dll/systemf.c@ 1162

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

Ticket 187: Draft 1: Functions only

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