source: trunk/dll/systemf.c@ 1271

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

A fix for the ticket 58 hang which runs runemf2 with the WAIT flag in a separate thread. This appears to fix Ticket 58 for all cases. Removed semaphore fix and reverted hTermQSem code.

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