source: trunk/dll/systemf.c@ 1120

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

Replace save_dir2(dir) with strcpy(dir, pFM2SaveDirectory)

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