source: trunk/src/helpers/apps.c@ 77

Last change on this file since 77 was 77, checked in by umoeller, 24 years ago

Added apps.c, semaphores.c

  • Property svn:eol-style set to CRLF
  • Property svn:keywords set to Author Date Id Revision
File size: 33.9 KB
Line 
1
2/*
3 *@@sourcefile apps.c:
4 * contains program helpers (environments, application start).
5 *
6 * This file is new with V0.9.12 and contains functions
7 * previously in winh.c and dosh2.c.
8 *
9 * Note: Version numbering in this file relates to XWorkplace version
10 * numbering.
11 *
12 *@@header "helpers\apps.h"
13 *@@added V0.9.12 (2001-05-26) [umoeller]
14 */
15
16/*
17 * Copyright (C) 1997-2001 Ulrich M”ller.
18 * This file is part of the "XWorkplace helpers" source package.
19 * This is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published
21 * by the Free Software Foundation, in version 2 as it comes in the
22 * "COPYING" file of the XWorkplace main distribution.
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 */
28
29#define OS2EMX_PLAIN_CHAR
30 // this is needed for "os2emx.h"; if this is defined,
31 // emx will define PSZ as _signed_ char, otherwise
32 // as unsigned char
33
34#define INCL_DOSPROCESS
35#define INCL_DOSSESMGR
36#define INCL_DOSERRORS
37
38#define INCL_WINPROGRAMLIST // needed for PROGDETAILS, wppgm.h
39#include <os2.h>
40
41#include <stdio.h>
42
43#include "setup.h" // code generation and debugging options
44
45#include "helpers\apps.h"
46#include "helpers\dosh.h"
47#include "helpers\prfh.h"
48#include "helpers\stringh.h"
49#include "helpers\xstring.h"
50
51/*
52 *@@category: Helpers\PM helpers\Application helpers
53 */
54
55/* ******************************************************************
56 *
57 * Environment helpers
58 *
59 ********************************************************************/
60
61/*
62 *@@ appParseEnvironment:
63 * this takes one of those ugly environment strings
64 * as used by DosStartSession and WinStartApp (with
65 * lots of zero-terminated strings one after another
66 * and a duplicate zero byte as a terminator) as
67 * input and splits it into an array of separate
68 * strings in pEnv.
69 *
70 * The newly allocated strings are stored in in
71 * pEnv->papszVars. The array count is stored in
72 * pEnv->cVars.
73 *
74 * Each environment variable will be copied into
75 * one newly allocated string in the array. Use
76 * appFreeEnvironment to free the memory allocated
77 * by this function.
78 *
79 * Use the following code to browse thru the array:
80 +
81 + DOSENVIRONMENT Env = {0};
82 + if (appParseEnvironment(pszEnv,
83 + &Env)
84 + == NO_ERROR)
85 + {
86 + if (Env.papszVars)
87 + {
88 + PSZ *ppszThis = Env.papszVars;
89 + for (ul = 0;
90 + ul < Env.cVars;
91 + ul++)
92 + {
93 + PSZ pszThis = *ppszThis;
94 + // pszThis now has something like PATH=C:\TEMP
95 + // ...
96 + // next environment string
97 + ppszThis++;
98 + }
99 + }
100 + appFreeEnvironment(&Env);
101 + }
102 *
103 *@@added V0.9.4 (2000-08-02) [umoeller]
104 */
105
106APIRET appParseEnvironment(const char *pcszEnv,
107 PDOSENVIRONMENT pEnv)
108{
109 APIRET arc = NO_ERROR;
110 if (!pcszEnv)
111 arc = ERROR_INVALID_PARAMETER;
112 else
113 {
114 PSZ pszVarThis = (PSZ)pcszEnv;
115 ULONG cVars = 0;
116 // count strings
117 while (*pszVarThis)
118 {
119 cVars++;
120 pszVarThis += strlen(pszVarThis) + 1;
121 }
122
123 pEnv->cVars = cVars;
124 pEnv->papszVars = 0;
125
126 if (cVars)
127 {
128 PSZ *papsz = (PSZ*)malloc(sizeof(PSZ) * cVars);
129 if (!papsz)
130 arc = ERROR_NOT_ENOUGH_MEMORY;
131 else
132 {
133 PSZ *ppszTarget = papsz;
134 memset(papsz, 0, sizeof(PSZ) * cVars);
135 pszVarThis = (PSZ)pcszEnv;
136 while (*pszVarThis)
137 {
138 *ppszTarget = strdup(pszVarThis);
139 ppszTarget++;
140 pszVarThis += strlen(pszVarThis) + 1;
141 }
142
143 pEnv->papszVars = papsz;
144 }
145 }
146 }
147
148 return (arc);
149}
150
151/*
152 *@@ appGetEnvironment:
153 * calls appParseEnvironment for the current
154 * process environment, which is retrieved from
155 * the info blocks.
156 *
157 *@@added V0.9.4 (2000-07-19) [umoeller]
158 */
159
160APIRET appGetEnvironment(PDOSENVIRONMENT pEnv)
161{
162 APIRET arc = NO_ERROR;
163 if (!pEnv)
164 arc = ERROR_INVALID_PARAMETER;
165 else
166 {
167 PTIB ptib = 0;
168 PPIB ppib = 0;
169 arc = DosGetInfoBlocks(&ptib, &ppib);
170 if (arc == NO_ERROR)
171 {
172 PSZ pszEnv = ppib->pib_pchenv;
173 if (pszEnv)
174 arc = appParseEnvironment(pszEnv, pEnv);
175 else
176 arc = ERROR_BAD_ENVIRONMENT;
177 }
178 }
179
180 return (arc);
181}
182
183/*
184 *@@ appFindEnvironmentVar:
185 * returns the PSZ* in the pEnv->papszVars array
186 * which specifies the environment variable in pszVarName.
187 *
188 * With pszVarName, you can either specify the variable
189 * name only ("VARNAME") or a full environment string
190 * ("VARNAME=BLAH"). In any case, only the variable name
191 * is compared.
192 *
193 * Returns NULL if no such variable name was found in
194 * the array.
195 *
196 *@@added V0.9.4 (2000-07-19) [umoeller]
197 *@@changed V0.9.12 (2001-05-21) [umoeller]: fixed memory leak
198 */
199
200PSZ* appFindEnvironmentVar(PDOSENVIRONMENT pEnv,
201 PSZ pszVarName)
202{
203 PSZ *ppszRet = 0;
204 if (pEnv)
205 {
206 if ((pEnv->papszVars) && (pszVarName))
207 {
208 PSZ *ppszThis = pEnv->papszVars;
209 PSZ pszThis;
210 ULONG ul = 0;
211 ULONG ulVarNameLen = 0;
212
213 PSZ pszSearch = NULL; // receives "VARNAME="
214 PSZ pFirstEqual = strchr(pszVarName, '=');
215 if (pFirstEqual)
216 pszSearch = strhSubstr(pszVarName, pFirstEqual + 1);
217 else
218 {
219 ulVarNameLen = strlen(pszVarName);
220 pszSearch = (PSZ)malloc(ulVarNameLen + 2);
221 memcpy(pszSearch, pszVarName, ulVarNameLen);
222 *(pszSearch + ulVarNameLen) = '=';
223 *(pszSearch + ulVarNameLen + 1) = 0;
224 }
225
226 ulVarNameLen = strlen(pszSearch);
227
228 for (ul = 0;
229 ul < pEnv->cVars;
230 ul++)
231 {
232 pszThis = *ppszThis;
233
234 if (strnicmp(*ppszThis, pszSearch, ulVarNameLen) == 0)
235 {
236 ppszRet = ppszThis;
237 break;
238 }
239
240 // next environment string
241 ppszThis++;
242 }
243
244 free(pszSearch); // was missing V0.9.12 (2001-05-21) [umoeller]
245 }
246 }
247
248 return (ppszRet);
249}
250
251/*
252 *@@ appSetEnvironmentVar:
253 * sets an environment variable in the specified
254 * environment, which must have been initialized
255 * using appGetEnvironment first.
256 *
257 * pszNewEnv must be a full environment string
258 * in the form "VARNAME=VALUE".
259 *
260 * If "VARNAME" has already been set to something
261 * in the string array in pEnv, that array item
262 * is replaced.
263 *
264 * OTOH, if "VARNAME" has not been set yet, a new
265 * item is added to the array, and pEnv->cVars is
266 * raised by one. In that case, fAddFirst determines
267 * whether the new array item is added to the front
268 * or the tail of the environment list.
269 *
270 *@@added V0.9.4 (2000-07-19) [umoeller]
271 *@@changed V0.9.7 (2000-12-17) [umoeller]: added fAddFirst
272 *@@changed V0.9.12 (2001-05-21) [umoeller]: fixed memory leak
273 *@@changed V0.9.12 (2001-05-26) [umoeller]: fixed crash if !fAddFirst
274 */
275
276APIRET appSetEnvironmentVar(PDOSENVIRONMENT pEnv,
277 PSZ pszNewEnv,
278 BOOL fAddFirst)
279{
280 APIRET arc = NO_ERROR;
281 if ((!pEnv) || (!pszNewEnv))
282 arc = ERROR_INVALID_PARAMETER;
283 else
284 {
285 if (!pEnv->papszVars)
286 {
287 // no variables set yet:
288 pEnv->papszVars = (PSZ*)malloc(sizeof(PSZ));
289 pEnv->cVars = 1;
290
291 *(pEnv->papszVars) = strdup(pszNewEnv);
292 }
293 else
294 {
295 PSZ *ppszEnvLine = appFindEnvironmentVar(pEnv, pszNewEnv);
296 if (ppszEnvLine)
297 {
298 // was set already: replace
299 free(*ppszEnvLine);
300 *ppszEnvLine = strdup(pszNewEnv);
301 if (!(*ppszEnvLine))
302 arc = ERROR_NOT_ENOUGH_MEMORY;
303 }
304 else
305 {
306 // not set already:
307 PSZ *ppszNew = NULL;
308
309 // allocate new array, with one new entry
310 // fixed V0.9.12 (2001-05-26) [umoeller], this crashed
311 PSZ *papszNew = (PSZ*)malloc(sizeof(PSZ) * (pEnv->cVars + 1));
312
313 if (!papszNew)
314 arc = ERROR_NOT_ENOUGH_MEMORY;
315 else
316 {
317 if (fAddFirst)
318 {
319 // add as first entry:
320 // overwrite first entry
321 ppszNew = papszNew;
322 // copy old entries
323 memcpy(papszNew + 1, // second new entry
324 pEnv->papszVars, // first old entry
325 sizeof(PSZ) * pEnv->cVars);
326 }
327 else
328 {
329 // append at the tail:
330 // overwrite last entry
331 ppszNew = papszNew + pEnv->cVars;
332 // copy old entries
333 memcpy(papszNew, // first new entry
334 pEnv->papszVars, // first old entry
335 sizeof(PSZ) * pEnv->cVars);
336 }
337
338 if (pEnv->papszVars)
339 free(pEnv->papszVars); // was missing V0.9.12 (2001-05-21) [umoeller]
340
341 pEnv->papszVars = papszNew;
342 pEnv->cVars++;
343 *ppszNew = strdup(pszNewEnv);
344 }
345 }
346 }
347 }
348
349 return (arc);
350}
351
352/*
353 *@@ appConvertEnvironment:
354 * converts an environment initialized by appGetEnvironment
355 * to the string format required by WinStartApp and DosExecPgm,
356 * that is, one memory block is allocated in *ppszEnv and all
357 * strings in pEnv->papszVars are copied to that block. Each
358 * string is terminated with a null character; the last string
359 * is terminated with two null characters.
360 *
361 * Use free() to free the memory block allocated by this
362 * function in *ppszEnv.
363 *
364 *@@added V0.9.4 (2000-07-19) [umoeller]
365 */
366
367APIRET appConvertEnvironment(PDOSENVIRONMENT pEnv,
368 PSZ *ppszEnv, // out: environment string
369 PULONG pulSize) // out: size of block allocated in *ppszEnv; ptr can be NULL
370{
371 APIRET arc = NO_ERROR;
372 if (!pEnv)
373 arc = ERROR_INVALID_PARAMETER;
374 else
375 {
376 if (!pEnv->papszVars)
377 arc = ERROR_INVALID_PARAMETER;
378 else
379 {
380 // count memory needed for all strings
381 ULONG cbNeeded = 0,
382 ul = 0;
383 PSZ *ppszThis = pEnv->papszVars;
384
385 for (ul = 0;
386 ul < pEnv->cVars;
387 ul++)
388 {
389 cbNeeded += strlen(*ppszThis) + 1; // length of string plus null terminator
390
391 // next environment string
392 ppszThis++;
393 }
394
395 cbNeeded++; // for another null terminator
396
397 *ppszEnv = (PSZ)malloc(cbNeeded);
398 if (!(*ppszEnv))
399 arc = ERROR_NOT_ENOUGH_MEMORY;
400 else
401 {
402 PSZ pTarget = *ppszEnv;
403 if (pulSize)
404 *pulSize = cbNeeded;
405 ppszThis = pEnv->papszVars;
406
407 // now copy each string
408 for (ul = 0;
409 ul < pEnv->cVars;
410 ul++)
411 {
412 PSZ pSource = *ppszThis;
413
414 while ((*pTarget++ = *pSource++))
415 ;
416
417 // *pTarget++ = 0; // append null terminator per string
418
419 // next environment string
420 ppszThis++;
421 }
422
423 *pTarget++ = 0; // append second null terminator
424 }
425 }
426 }
427
428 return (arc);
429}
430
431/*
432 *@@ appFreeEnvironment:
433 * frees memory allocated by appGetEnvironment.
434 *
435 *@@added V0.9.4 (2000-07-19) [umoeller]
436 */
437
438APIRET appFreeEnvironment(PDOSENVIRONMENT pEnv)
439{
440 APIRET arc = NO_ERROR;
441 if (!pEnv)
442 arc = ERROR_INVALID_PARAMETER;
443 else
444 {
445 if (!pEnv->papszVars)
446 arc = ERROR_INVALID_PARAMETER;
447 else
448 {
449 PSZ *ppszThis = pEnv->papszVars;
450 PSZ pszThis;
451 ULONG ul = 0;
452
453 for (ul = 0;
454 ul < pEnv->cVars;
455 ul++)
456 {
457 pszThis = *ppszThis;
458 free(pszThis);
459 // *ppszThis = NULL;
460 // next environment string
461 ppszThis++;
462 }
463
464 free(pEnv->papszVars);
465 pEnv->cVars = 0;
466 }
467 }
468
469 return (arc);
470}
471
472/* ******************************************************************
473 *
474 * Application start
475 *
476 ********************************************************************/
477
478/*
479 *@@ CallBatchCorrectly:
480 * fixes the specified PROGDETAILS for
481 * command files in the executable part
482 * by inserting /C XXX into the parameters
483 * and setting the executable according
484 * to an environment variable.
485 *
486 *@@added V0.9.6 (2000-10-16) [umoeller]
487 *@@changed V0.9.7 (2001-01-15) [umoeller]: now using XSTRING
488 */
489
490VOID CallBatchCorrectly(PPROGDETAILS pProgDetails,
491 PXSTRING pstrParams, // in/out: modified parameters (reallocated)
492 const char *pcszEnvVar, // in: env var spec'g command proc
493 // (e.g. "OS2_SHELL"); can be NULL
494 const char *pcszDefProc) // in: def't command proc (e.g. "CMD.EXE")
495{
496 // XXX.CMD file as executable:
497 // fix args to /C XXX.CMD
498
499 PSZ pszOldParams = NULL;
500 ULONG ulOldParamsLength = pstrParams->ulLength;
501 if (ulOldParamsLength)
502 // we have parameters already:
503 // make a backup... we'll append that later
504 pszOldParams = strdup(pstrParams->psz);
505
506 // set new params to "/C filename.cmd"
507 xstrcpy(pstrParams, "/C ", 0);
508 xstrcat(pstrParams,
509 pProgDetails->pszExecutable,
510 0);
511
512 if (pszOldParams)
513 {
514 // .cmd had params:
515 // append space and old params
516 xstrcatc(pstrParams, ' ');
517 xstrcat(pstrParams,
518 pszOldParams,
519 ulOldParamsLength);
520 free(pszOldParams);
521 }
522
523 // set executable to $(OS2_SHELL)
524 pProgDetails->pszExecutable = NULL;
525 if (pcszEnvVar)
526 pProgDetails->pszExecutable = getenv(pcszEnvVar);
527 if (!pProgDetails->pszExecutable)
528 pProgDetails->pszExecutable = (PSZ)pcszDefProc;
529 // should be on PATH
530}
531
532/*
533 *@@ appQueryAppType:
534 * returns the Control Program (Dos) and
535 * Win* PROG_* application types for the
536 * specified executable. Essentially, this
537 * is a wrapper around DosQueryAppType.
538 *
539 * pcszExecutable must be fully qualified.
540 * You can use doshFindExecutable to qualify
541 * it.
542 *
543 * This returns the APIRET of DosQueryAppType.
544 * If this is NO_ERROR; *pulDosAppType receives
545 * the app type of DosQueryAppType. In addition,
546 * *pulWinAppType is set to one of the following:
547 *
548 * -- PROG_FULLSCREEN
549 *
550 * -- PROG_PDD
551 *
552 * -- PROG_VDD
553 *
554 * -- PROG_XWP_DLL: new apptype defined in winh.h for
555 * dynamic link libraries.
556 *
557 * -- PROG_WINDOWEDVDM
558 *
559 * -- PROG_PM
560 *
561 * -- PROG_31_ENH
562 *
563 * -- PROG_WINDOWABLEVIO
564 *
565 *@@added V0.9.9 (2001-03-07) [umoeller]
566 */
567
568APIRET appQueryAppType(const char *pcszExecutable,
569 PULONG pulDosAppType,
570 PULONG pulWinAppType)
571{
572 APIRET arc = DosQueryAppType((PSZ)pcszExecutable, pulDosAppType);
573 if (arc == NO_ERROR)
574 {
575 ULONG _ulDosAppType = *pulDosAppType;
576
577 if (_ulDosAppType == 0)
578 *pulWinAppType = PROG_FULLSCREEN;
579 else if (_ulDosAppType & 0x40)
580 *pulWinAppType = PROG_PDD;
581 else if (_ulDosAppType & 0x80)
582 *pulWinAppType = PROG_VDD;
583 else if ((_ulDosAppType & 0xF0) == 0x10)
584 // DLL bit set
585 *pulWinAppType = PROG_XWP_DLL;
586 else if (_ulDosAppType & 0x20)
587 // DOS bit set?
588 *pulWinAppType = PROG_WINDOWEDVDM;
589 else if ((_ulDosAppType & 0x0003) == 0x0003) // "Window-API" == PM
590 *pulWinAppType = PROG_PM;
591 else if ( ((_ulDosAppType & 0xFFFF) == 0x1000) // windows program (?!?)
592 || ((_ulDosAppType & 0xFFFF) == 0x0400) // windows program (?!?)
593 )
594 *pulWinAppType = PROG_31_ENH;
595 // *pulWinAppType = PROG_31_ENHSEAMLESSVDM;
596 else if ((_ulDosAppType & 0x03) == 0x02)
597 *pulWinAppType = PROG_WINDOWABLEVIO;
598 else if ((_ulDosAppType & 0x03) == 0x01)
599 *pulWinAppType = PROG_FULLSCREEN;
600 }
601
602 return (arc);
603}
604
605/*
606 *@@ appIsWindowsApp:
607 * checks the specified program category
608 * (PROGDETAILS.progt.progc) for whether
609 * it represents a Win-OS/2 application.
610 *
611 * Returns:
612 *
613 * -- 0: no windows app (it's VIO, OS/2
614 * or DOS fullscreen, or PM).
615 *
616 * -- 1: Win-OS/2 standard app.
617 *
618 * -- 2: Win-OS/2 enhanced-mode app.
619 *
620 *@@added V0.9.12 (2001-05-26) [umoeller]
621 */
622
623ULONG appIsWindowsApp(ULONG ulProgCategory)
624{
625 switch (ulProgCategory)
626 {
627 case PROG_31_ENHSEAMLESSVDM: // 17
628 case PROG_31_ENHSEAMLESSCOMMON: // 18
629 case PROG_31_ENH: // 19
630 return (2);
631
632#ifndef PROG_30_STD
633 #define PROG_30_STD (PROGCATEGORY)11
634#endif
635
636#ifndef PROG_30_STDSEAMLESSVDM
637 #define PROG_30_STDSEAMLESSVDM (PROGCATEGORY)13
638#endif
639
640 case PROG_WINDOW_REAL: // 10
641 case PROG_30_STD: // 11
642 case PROG_WINDOW_AUTO: // 12
643 case PROG_30_STDSEAMLESSVDM: // 13
644 case PROG_30_STDSEAMLESSCOMMON: // 14
645 case PROG_31_STDSEAMLESSVDM: // 15
646 case PROG_31_STDSEAMLESSCOMMON: // 16
647 case PROG_31_STD: // 20
648 return (1);
649 }
650
651 return (0);
652}
653
654/*
655 *@@ appQueryDefaultWin31Environment:
656 * returns the default Win-OS/2 3.1 environment
657 * from OS2.INI, which you can then merge with
658 * your process environment to be able to
659 * start Win-OS/2 sessions properly with
660 * appStartApp.
661 *
662 * Caller must free() the return value.
663 *
664 *@@added V0.9.12 (2001-05-26) [umoeller]
665 */
666
667PSZ appQueryDefaultWin31Environment(VOID)
668{
669 PSZ pszReturn = NULL;
670 ULONG ulSize = 0;
671 // get default environment (from Win-OS/2 settings object)
672 // from OS2.INI
673 PSZ pszDefEnv = prfhQueryProfileData(HINI_USER,
674 "WINOS2",
675 "PM_GlobalWindows31Settings",
676 &ulSize);
677 if (pszDefEnv)
678 {
679 if (pszReturn = (PSZ)malloc(ulSize + 2))
680 {
681 PSZ p;
682 memset(pszReturn, 0, ulSize + 2);
683 memcpy(pszReturn, pszDefEnv, ulSize);
684
685 for (p = pszReturn;
686 p < pszReturn + ulSize;
687 p++)
688 if (*p == ';')
689 *p = 0;
690
691 // okay.... now we got an OS/2-style environment
692 // with 0, 0, 00 strings
693 }
694
695 free(pszDefEnv);
696 }
697
698 return (pszReturn);
699}
700
701/*
702 *@@ appStartApp:
703 * wrapper around WinStartApp which fixes the
704 * specified PROGDETAILS to (hopefully) work
705 * work with all executable types.
706 *
707 * This fixes the executable info to support:
708 *
709 * -- starting "*" executables (command prompts
710 * for OS/2, DOS, Win-OS/2);
711 *
712 * -- starting ".CMD" and ".BAT" files as
713 * PROGDETAILS.pszExecutable.
714 *
715 * Unless it is "*", PROGDETAILS.pszExecutable must
716 * be a proper file name. The full path may be omitted
717 * if it is on the PATH, but the extension (.EXE etc.)
718 * must be given. You can use doshFindExecutable to
719 * find executables if you don't know the extension.
720 *
721 * This also handles and merges special and default
722 * environments for the app to be started. The
723 * following should be respected:
724 *
725 * -- As with WinStartApp, if PROGDETAILS.pszEnvironment
726 * is NULL, the new app inherits a default environment
727 * from the shell.
728 *
729 + -- However, if you specify an environment, you _must_
730 * specify a complemete environment. This function
731 * will not merge environments. Use
732 * appSetEnvironmentVar to change environment
733 * variables in a complete environment set.
734 *
735 * -- If PROGDETAILS specifies a Win-OS/2 session
736 * and PROGDETAILS.pszEnvironment is empty,
737 * this merges the current process environment
738 * with the default Win-OS/2 environment.
739 * See appQueryDefaultWin31Environment.
740 *
741 * Even though this isn't clearly said in PMREF,
742 * PROGDETAILS.swpInitial is important:
743 *
744 * -- To start a session minimized, set SWP_MINIMIZE.
745 *
746 * -- To start a VIO session auto-close disabled, set
747 * the half-documented SWP_NOAUTOCLOSE flag (0x8000)
748 * This flag is now in the newer toolkit headers.
749 *
750 * Since this calls WinStartApp in turn, this
751 * requires a message queue on the calling thread.
752 *
753 *@@added V0.9.6 (2000-10-16) [umoeller]
754 *@@changed V0.9.7 (2000-12-10) [umoeller]: PROGDETAILS.swpInitial no longer zeroed... this broke VIOs
755 *@@changed V0.9.7 (2000-12-17) [umoeller]: PROGDETAILS.pszEnvironment no longer zeroed
756 *@@changed V0.9.9 (2001-01-27) [umoeller]: crashed if PROGDETAILS.pszExecutable was NULL
757 *@@changed V0.9.12 (2001-05-26) [umoeller]: fixed PROG_DEFAULT
758 */
759
760HAPP appStartApp(HWND hwndNotify, // in: notify window (as with WinStartApp)
761 const PROGDETAILS *pcProgDetails) // in: program data
762{
763 HAPP happ = NULLHANDLE;
764 XSTRING strParamsPatched;
765 PROGDETAILS ProgDetails;
766
767 PSZ pszWinOS2Env = 0;
768
769 memcpy(&ProgDetails, pcProgDetails, sizeof(PROGDETAILS));
770 // pointers still point into old prog details buffer
771 ProgDetails.Length = sizeof(PROGDETAILS);
772 ProgDetails.progt.fbVisible = SHE_VISIBLE;
773 // ProgDetails.pszEnvironment = 0;
774
775 // all this only makes sense if this contains something...
776 // besides, this crashed on string comparisons V0.9.9 (2001-01-27) [umoeller]
777 if (ProgDetails.pszExecutable)
778 {
779 ULONG ulIsWinApp;
780
781 // memset(&ProgDetails.swpInitial, 0, sizeof(SWP));
782 // this wasn't a good idea... WPProgram stores stuff
783 // in here, such as the "minimize on startup" -> SWP_MINIMIZE
784
785 // duplicate parameters...
786 // we need this for string manipulations below...
787 if (ProgDetails.pszParameters)
788 xstrInitCopy(&strParamsPatched,
789 ProgDetails.pszParameters,
790 100);
791 else
792 // no old params:
793 xstrInit(&strParamsPatched, 100);
794
795 // _Pmpf((__FUNCTION__ ": old progc: 0x%lX", pcProgDetails->progt.progc));
796 // _Pmpf((" pszTitle: %s", (ProgDetails.pszTitle) ? ProgDetails.pszTitle : NULL));
797 // _Pmpf((" pszIcon: %s", (ProgDetails.pszIcon) ? ProgDetails.pszIcon : NULL));
798
799 // program type fixups
800 switch (ProgDetails.progt.progc) // that's a ULONG
801 {
802 case ((ULONG)-1): // we get that sometimes...
803 case PROG_DEFAULT:
804 {
805 // V0.9.12 (2001-05-26) [umoeller]
806 ULONG ulDosAppType;
807 appQueryAppType(ProgDetails.pszExecutable,
808 &ulDosAppType,
809 &ProgDetails.progt.progc);
810 }
811 break;
812 }
813
814 ulIsWinApp = appIsWindowsApp(ProgDetails.progt.progc);
815
816 // now try again...
817
818 /*
819 * command lines fixups:
820 *
821 */
822
823 if (strcmp(ProgDetails.pszExecutable, "*") == 0)
824 {
825 /*
826 * "*" for command sessions:
827 *
828 */
829
830 if (ulIsWinApp == 2)
831 {
832 // enhanced Win-OS/2 session:
833 PSZ psz = NULL;
834 if (strParamsPatched.ulLength)
835 // "/3 " + existing params
836 psz = strdup(strParamsPatched.psz);
837
838 xstrcpy(&strParamsPatched, "/3 ", 0);
839
840 if (psz)
841 {
842 xstrcat(&strParamsPatched, psz, 0);
843 free(psz);
844 }
845 }
846
847 if (ulIsWinApp)
848 {
849 // cheat: WinStartApp doesn't support NULL
850 // for Win-OS2 sessions, so manually start winos2.com
851 ProgDetails.pszExecutable = "WINOS2.COM";
852 // this is a DOS app, so fix this to DOS fullscreen
853 ProgDetails.progt.progc = PROG_VDM;
854 }
855 else
856 // for all other executable types
857 // (including OS/2 and DOS sessions),
858 // set pszExecutable to NULL; this will
859 // have WinStartApp start a cmd shell
860 ProgDetails.pszExecutable = NULL;
861
862 } // end if (strcmp(pProgDetails->pszExecutable, "*") == 0)
863 else
864 switch (ProgDetails.progt.progc)
865 {
866 /*
867 * .CMD files fixups
868 *
869 */
870
871 case PROG_FULLSCREEN: // OS/2 fullscreen
872 case PROG_WINDOWABLEVIO: // OS/2 window
873 {
874 PSZ pszExtension = doshGetExtension(ProgDetails.pszExecutable);
875 if (pszExtension)
876 {
877 if (stricmp(pszExtension, "CMD") == 0)
878 {
879 CallBatchCorrectly(&ProgDetails,
880 &strParamsPatched,
881 "OS2_SHELL",
882 "CMD.EXE");
883 }
884 }
885 break; }
886
887 case PROG_VDM: // DOS fullscreen
888 case PROG_WINDOWEDVDM: // DOS window
889 {
890 PSZ pszExtension = doshGetExtension(ProgDetails.pszExecutable);
891 if (pszExtension)
892 {
893 if (stricmp(pszExtension, "BAT") == 0)
894 {
895 CallBatchCorrectly(&ProgDetails,
896 &strParamsPatched,
897 NULL,
898 "COMMAND.COM");
899 }
900 }
901 break; }
902 } // end switch (ProgDetails.progt.progc)
903
904 if ( (ulIsWinApp)
905 && ( (ProgDetails.pszEnvironment == NULL)
906 || (!strlen(ProgDetails.pszEnvironment))
907 )
908 )
909 {
910 // this is a windoze app, and caller didn't bother
911 // to give us an environment:
912 // we MUST set one then, or we'll get the strangest
913 // errors, up to system hangs. V0.9.12 (2001-05-26) [umoeller]
914
915 DOSENVIRONMENT Env = {0};
916
917 // get standard WIN-OS/2 environment
918 PSZ pszTemp = appQueryDefaultWin31Environment();
919
920 /* if (!appParseEnvironment(pszTemp,
921 &Env)) */
922 {
923 // now override KBD_CTRL_BYPASS=CTRL_ESC
924 appSetEnvironmentVar(&Env,
925 "KBD_CTRL_BYPASS=CTRL_ESC",
926 FALSE); // add last
927 appSetEnvironmentVar(&Env,
928 "KBD_ALTHOME_BYPASS=1",
929 FALSE); // add last
930 appSetEnvironmentVar(&Env,
931 "INT_DURING_IO=1",
932 FALSE); // add last
933 appSetEnvironmentVar(&Env,
934 "HW_TIMER=1",
935 FALSE); // add last
936 appSetEnvironmentVar(&Env,
937 "MOUSE_EXCLUSIVE_ACCESS=0",
938 FALSE); // add last
939 appSetEnvironmentVar(&Env,
940 "VIDEO_RETRACE_EMULATION=1",
941 FALSE); // add last
942 appSetEnvironmentVar(&Env,
943 "VIDEO_SWITCH_NOTIFICATION=1",
944 FALSE); // add last
945 appSetEnvironmentVar(&Env,
946 "VIDEO_8514A_XGA_IOTRAP=0",
947 FALSE); // add last
948
949 if (!appConvertEnvironment(&Env,
950 &pszWinOS2Env, // freed at bottom
951 NULL))
952 ProgDetails.pszEnvironment = pszWinOS2Env;
953
954 appFreeEnvironment(&Env);
955 }
956
957 free(pszTemp);
958 }
959
960 if (!ProgDetails.pszTitle)
961 ProgDetails.pszTitle = ProgDetails.pszExecutable;
962
963 ProgDetails.pszParameters = strParamsPatched.psz;
964
965 _Pmpf(("progt.progc: %d", ProgDetails.progt.progc));
966 _Pmpf(("progt.fbVisible: 0x%lX", ProgDetails.progt.fbVisible));
967 _Pmpf(("progt.pszTitle: \"%s\"", (ProgDetails.pszTitle) ? ProgDetails.pszTitle : "NULL"));
968 _Pmpf(("exec: \"%s\"", (ProgDetails.pszExecutable) ? ProgDetails.pszExecutable : "NULL"));
969 _Pmpf(("params: \"%s\"", (ProgDetails.pszParameters) ? ProgDetails.pszParameters : "NULL"));
970 _Pmpf(("startup: \"%s\"", (ProgDetails.pszStartupDir) ? ProgDetails.pszStartupDir : "NULL"));
971 _Pmpf(("pszIcon: \"%s\"", (ProgDetails.pszIcon) ? ProgDetails.pszIcon : "NULL"));
972 _Pmpf(("environment: "));
973 {
974 PSZ pszThis = ProgDetails.pszEnvironment;
975 while (pszThis && *pszThis)
976 {
977 _Pmpf((" \"%s\"", pszThis));
978 pszThis += strlen(pszThis) + 1;
979 }
980 }
981
982 _Pmpf(("swpInitial.fl = 0x%lX, x = %d, y = %d, cx = %d, cy = %d:",
983 ProgDetails.swpInitial.fl,
984 ProgDetails.swpInitial.x,
985 ProgDetails.swpInitial.y,
986 ProgDetails.swpInitial.cx,
987 ProgDetails.swpInitial.cy));
988 _Pmpf((" behind = %d, hwnd = %d, res1 = %d, res2 = %d",
989 ProgDetails.swpInitial.hwndInsertBehind,
990 ProgDetails.swpInitial.hwnd,
991 ProgDetails.swpInitial.ulReserved1,
992 ProgDetails.swpInitial.ulReserved2));
993
994 /* if (WinMessageBox(HWND_DESKTOP,
995 NULLHANDLE,
996 (ProgDetails.pszExecutable) ? ProgDetails.pszExecutable : "NULL",
997 "Start?",
998 0,
999 MB_YESNO | MB_MOVEABLE)
1000 == MBID_YES) */
1001 happ = WinStartApp(hwndNotify,
1002 // receives WM_APPTERMINATENOTIFY
1003 &ProgDetails,
1004 strParamsPatched.psz,
1005 NULL, // "reserved", PMREF says...
1006 SAF_INSTALLEDCMDLINE);
1007 // we MUST use SAF_INSTALLEDCMDLINE
1008 // or no Win-OS/2 session will start...
1009 // whatever is going on here... Warp 4 FP11
1010
1011 // do not use SAF_STARTCHILDAPP, or the
1012 // app will be terminated automatically
1013 // when the WPS terminates!
1014
1015 // _Pmpf((__FUNCTION__ ": got happ 0x%lX", happ));
1016
1017 xstrClear(&strParamsPatched);
1018 if (pszWinOS2Env)
1019 free(pszWinOS2Env);
1020 } // end if (ProgDetails.pszExecutable)
1021
1022 return (happ);
1023}
1024
1025
Note: See TracBrowser for help on using the repository browser.