source: trunk/dll/systemf.c@ 1039

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

Removed unnecessary xfrees and included fortify.h where needed; moved several misplaced (x)frees;

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