source: trunk/dll/systemf.c@ 1488

Last change on this file since 1488 was 1488, checked in by Gregg Young, 16 years ago

Fixed commands so reordering them in commands.dat no longer changes their ID or hot key assignment; added 20 new hot keys; the environment information is now used when executing a command; some code clean up in command.c; added CheckExecutibleFlags to systemf.c the eliminate repetative code in assoc.c, command.c & cmdline.c

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