source: trunk/dll/systemf.c@ 1014

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

Fix 2 more memory leaks.

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