source: trunk/dll/systemf.c@ 1036

Last change on this file since 1036 was 1021, checked in by Steven Levine, 17 years ago

Use uiLineNumber correctly

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