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

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

Executable updates, mostly.

  • Property svn:eol-style set to CRLF
  • Property svn:keywords set to Author Date Id Revision
File size: 52.2 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_DOSMODULEMGR
36#define INCL_DOSSESMGR
37#define INCL_DOSERRORS
38
39#define INCL_WINPROGRAMLIST // needed for PROGDETAILS, wppgm.h
40#define INCL_WINERRORS
41#define INCL_SHLERRORS
42#include <os2.h>
43
44#include <stdio.h>
45
46#include "setup.h" // code generation and debugging options
47
48#include "helpers\apps.h"
49#include "helpers\dosh.h"
50#include "helpers\prfh.h"
51#include "helpers\stringh.h"
52#include "helpers\winh.h"
53#include "helpers\xstring.h"
54
55/*
56 *@@category: Helpers\PM helpers\Application helpers
57 */
58
59/* ******************************************************************
60 *
61 * Environment helpers
62 *
63 ********************************************************************/
64
65/*
66 *@@ appParseEnvironment:
67 * this takes one of those ugly environment strings
68 * as used by DosStartSession and WinStartApp (with
69 * lots of zero-terminated strings one after another
70 * and a duplicate zero byte as a terminator) as
71 * input and splits it into an array of separate
72 * strings in pEnv.
73 *
74 * The newly allocated strings are stored in in
75 * pEnv->papszVars. The array count is stored in
76 * pEnv->cVars.
77 *
78 * Each environment variable will be copied into
79 * one newly allocated string in the array. Use
80 * appFreeEnvironment to free the memory allocated
81 * by this function.
82 *
83 * Use the following code to browse thru the array:
84 +
85 + DOSENVIRONMENT Env = {0};
86 + if (appParseEnvironment(pszEnv,
87 + &Env)
88 + == NO_ERROR)
89 + {
90 + if (Env.papszVars)
91 + {
92 + PSZ *ppszThis = Env.papszVars;
93 + for (ul = 0;
94 + ul < Env.cVars;
95 + ul++)
96 + {
97 + PSZ pszThis = *ppszThis;
98 + // pszThis now has something like PATH=C:\TEMP
99 + // ...
100 + // next environment string
101 + ppszThis++;
102 + }
103 + }
104 + appFreeEnvironment(&Env);
105 + }
106 *
107 *@@added V0.9.4 (2000-08-02) [umoeller]
108 *@@changed V0.9.12 (2001-05-27) [umoeller]: moved from dosh2.c to apps.c
109 */
110
111APIRET appParseEnvironment(const char *pcszEnv,
112 PDOSENVIRONMENT pEnv) // out: new environment
113{
114 APIRET arc = NO_ERROR;
115 if (!pcszEnv)
116 arc = ERROR_INVALID_PARAMETER;
117 else
118 {
119 PSZ pszVarThis = (PSZ)pcszEnv;
120 ULONG cVars = 0;
121 // count strings
122 while (*pszVarThis)
123 {
124 cVars++;
125 pszVarThis += strlen(pszVarThis) + 1;
126 }
127
128 pEnv->cVars = 0;
129 pEnv->papszVars = 0;
130
131 if (cVars)
132 {
133 ULONG cbArray = sizeof(PSZ) * cVars;
134 PSZ *papsz;
135 if (!(papsz = (PSZ*)malloc(cbArray)))
136 arc = ERROR_NOT_ENOUGH_MEMORY;
137 else
138 {
139 PSZ *ppszTarget = papsz;
140 memset(papsz, 0, cbArray);
141 pszVarThis = (PSZ)pcszEnv;
142 while (*pszVarThis)
143 {
144 ULONG ulThisLen;
145 if (!(*ppszTarget = strhdup(pszVarThis, &ulThisLen)))
146 {
147 arc = ERROR_NOT_ENOUGH_MEMORY;
148 break;
149 }
150 (pEnv->cVars)++;
151 ppszTarget++;
152 pszVarThis += ulThisLen + 1;
153 }
154
155 pEnv->papszVars = papsz;
156 }
157 }
158 }
159
160 return (arc);
161}
162
163/*
164 *@@ appGetEnvironment:
165 * calls appParseEnvironment for the current
166 * process environment, which is retrieved from
167 * the info blocks.
168 *
169 * Returns:
170 *
171 * -- NO_ERROR:
172 *
173 * -- ERROR_INVALID_PARAMETER
174 *
175 * -- ERROR_BAD_ENVIRONMENT: no environment found in
176 * info blocks.
177 *
178 *@@added V0.9.4 (2000-07-19) [umoeller]
179 *@@changed V0.9.12 (2001-05-27) [umoeller]: moved from dosh2.c to apps.c
180 */
181
182APIRET appGetEnvironment(PDOSENVIRONMENT pEnv)
183{
184 APIRET arc = NO_ERROR;
185 if (!pEnv)
186 arc = ERROR_INVALID_PARAMETER;
187 else
188 {
189 PTIB ptib = 0;
190 PPIB ppib = 0;
191 arc = DosGetInfoBlocks(&ptib, &ppib);
192 if (arc == NO_ERROR)
193 {
194 PSZ pszEnv;
195 if (pszEnv = ppib->pib_pchenv)
196 arc = appParseEnvironment(pszEnv, pEnv);
197 else
198 arc = ERROR_BAD_ENVIRONMENT;
199 }
200 }
201
202 return (arc);
203}
204
205/*
206 *@@ appFindEnvironmentVar:
207 * returns the PSZ* in the pEnv->papszVars array
208 * which specifies the environment variable in pszVarName.
209 *
210 * With pszVarName, you can either specify the variable
211 * name only ("VARNAME") or a full environment string
212 * ("VARNAME=BLAH"). In any case, only the variable name
213 * is compared.
214 *
215 * Returns NULL if no such variable name was found in
216 * the array.
217 *
218 *@@added V0.9.4 (2000-07-19) [umoeller]
219 *@@changed V0.9.12 (2001-05-21) [umoeller]: fixed memory leak
220 *@@changed V0.9.12 (2001-05-27) [umoeller]: moved from dosh2.c to apps.c
221 *@@changed V0.9.16 (2002-01-01) [umoeller]: removed extra heap allocation
222 */
223
224PSZ* appFindEnvironmentVar(PDOSENVIRONMENT pEnv,
225 PSZ pszVarName)
226{
227 PSZ *ppszRet = 0;
228
229 if ( (pEnv)
230 && (pEnv->papszVars)
231 && (pszVarName)
232 )
233 {
234 ULONG ul = 0;
235 ULONG ulVarNameLen = 0;
236
237 PSZ pFirstEqual;
238 // rewrote all the following for speed V0.9.16 (2002-01-01) [umoeller]
239 if (pFirstEqual = strchr(pszVarName, '='))
240 // VAR=VALUE
241 // ^ pFirstEqual
242 ulVarNameLen = pFirstEqual - pszVarName;
243 else
244 ulVarNameLen = strlen(pszVarName);
245
246 for (ul = 0;
247 ul < pEnv->cVars;
248 ul++)
249 {
250 PSZ pszThis = pEnv->papszVars[ul];
251 if (pFirstEqual = strchr(pszThis, '='))
252 {
253 ULONG ulLenThis = pFirstEqual - pszThis;
254 if ( (ulLenThis == ulVarNameLen)
255 && (!memicmp(pszThis,
256 pszVarName,
257 ulVarNameLen))
258 )
259 {
260 ppszRet = &pEnv->papszVars[ul];
261 break;
262 }
263 }
264 }
265 }
266
267 return (ppszRet);
268}
269
270/*
271 *@@ appSetEnvironmentVar:
272 * sets an environment variable in the specified
273 * environment, which must have been initialized
274 * using appGetEnvironment first.
275 *
276 * pszNewEnv must be a full environment string
277 * in the form "VARNAME=VALUE".
278 *
279 * If "VARNAME" has already been set to something
280 * in the string array in pEnv, that array item
281 * is replaced.
282 *
283 * OTOH, if "VARNAME" has not been set yet, a new
284 * item is added to the array, and pEnv->cVars is
285 * raised by one. In that case, fAddFirst determines
286 * whether the new array item is added to the front
287 * or the tail of the environment list.
288 *
289 *@@added V0.9.4 (2000-07-19) [umoeller]
290 *@@changed V0.9.7 (2000-12-17) [umoeller]: added fAddFirst
291 *@@changed V0.9.12 (2001-05-21) [umoeller]: fixed memory leak
292 *@@changed V0.9.12 (2001-05-26) [umoeller]: fixed crash if !fAddFirst
293 *@@changed V0.9.12 (2001-05-27) [umoeller]: moved from dosh2.c to apps.c
294 */
295
296APIRET appSetEnvironmentVar(PDOSENVIRONMENT pEnv,
297 PSZ pszNewEnv,
298 BOOL fAddFirst)
299{
300 APIRET arc = NO_ERROR;
301 if ((!pEnv) || (!pszNewEnv))
302 arc = ERROR_INVALID_PARAMETER;
303 else
304 {
305 if (!pEnv->papszVars)
306 {
307 // no variables set yet:
308 pEnv->papszVars = (PSZ*)malloc(sizeof(PSZ));
309 pEnv->cVars = 1;
310
311 *(pEnv->papszVars) = strdup(pszNewEnv);
312 }
313 else
314 {
315 PSZ *ppszEnvLine;
316 if (ppszEnvLine = appFindEnvironmentVar(pEnv, pszNewEnv))
317 // was set already: replace
318 arc = strhStore(ppszEnvLine,
319 pszNewEnv,
320 NULL);
321 else
322 {
323 // not set already:
324 PSZ *ppszNew = NULL;
325
326 // allocate new array, with one new entry
327 // fixed V0.9.12 (2001-05-26) [umoeller], this crashed
328 PSZ *papszNew;
329
330 if (!(papszNew = (PSZ*)malloc(sizeof(PSZ) * (pEnv->cVars + 1))))
331 arc = ERROR_NOT_ENOUGH_MEMORY;
332 else
333 {
334 if (fAddFirst)
335 {
336 // add as first entry:
337 // overwrite first entry
338 ppszNew = papszNew;
339 // copy old entries
340 memcpy(papszNew + 1, // second new entry
341 pEnv->papszVars, // first old entry
342 sizeof(PSZ) * pEnv->cVars);
343 }
344 else
345 {
346 // append at the tail:
347 // overwrite last entry
348 ppszNew = papszNew + pEnv->cVars;
349 // copy old entries
350 memcpy(papszNew, // first new entry
351 pEnv->papszVars, // first old entry
352 sizeof(PSZ) * pEnv->cVars);
353 }
354
355 free(pEnv->papszVars); // was missing V0.9.12 (2001-05-21) [umoeller]
356 pEnv->papszVars = papszNew;
357 pEnv->cVars++;
358 *ppszNew = strdup(pszNewEnv);
359 }
360 }
361 }
362 }
363
364 return (arc);
365}
366
367/*
368 *@@ appConvertEnvironment:
369 * converts an environment initialized by appGetEnvironment
370 * to the string format required by WinStartApp and DosExecPgm,
371 * that is, one memory block is allocated in *ppszEnv and all
372 * strings in pEnv->papszVars are copied to that block. Each
373 * string is terminated with a null character; the last string
374 * is terminated with two null characters.
375 *
376 * Use free() to free the memory block allocated by this
377 * function in *ppszEnv.
378 *
379 *@@added V0.9.4 (2000-07-19) [umoeller]
380 *@@changed V0.9.12 (2001-05-27) [umoeller]: moved from dosh2.c to apps.c
381 */
382
383APIRET appConvertEnvironment(PDOSENVIRONMENT pEnv,
384 PSZ *ppszEnv, // out: environment string
385 PULONG pulSize) // out: size of block allocated in *ppszEnv; ptr can be NULL
386{
387 APIRET arc = NO_ERROR;
388 if ( (!pEnv)
389 || (!pEnv->papszVars)
390 )
391 arc = ERROR_INVALID_PARAMETER;
392 else
393 {
394 // count memory needed for all strings
395 ULONG cbNeeded = 0,
396 ul = 0;
397 PSZ *ppszThis = pEnv->papszVars;
398
399 for (ul = 0;
400 ul < pEnv->cVars;
401 ul++)
402 {
403 cbNeeded += strlen(*ppszThis) + 1; // length of string plus null terminator
404
405 // next environment string
406 ppszThis++;
407 }
408
409 cbNeeded++; // for another null terminator
410
411 if (!(*ppszEnv = (PSZ)malloc(cbNeeded)))
412 arc = ERROR_NOT_ENOUGH_MEMORY;
413 else
414 {
415 PSZ pTarget = *ppszEnv;
416 if (pulSize)
417 *pulSize = cbNeeded;
418 ppszThis = pEnv->papszVars;
419
420 // now copy each string
421 for (ul = 0;
422 ul < pEnv->cVars;
423 ul++)
424 {
425 PSZ pSource = *ppszThis;
426
427 while ((*pTarget++ = *pSource++))
428 ;
429
430 // *pTarget++ = 0; // append null terminator per string
431
432 // next environment string
433 ppszThis++;
434 }
435
436 *pTarget++ = 0; // append second null terminator
437 }
438 }
439
440 return (arc);
441}
442
443/*
444 *@@ appFreeEnvironment:
445 * frees memory allocated by appGetEnvironment.
446 *
447 *@@added V0.9.4 (2000-07-19) [umoeller]
448 *@@changed V0.9.12 (2001-05-27) [umoeller]: moved from dosh2.c to apps.c
449 */
450
451APIRET appFreeEnvironment(PDOSENVIRONMENT pEnv)
452{
453 APIRET arc = NO_ERROR;
454 if ( (!pEnv)
455 || (!pEnv->papszVars)
456 )
457 arc = ERROR_INVALID_PARAMETER;
458 else
459 {
460 PSZ *ppszThis = pEnv->papszVars;
461 PSZ pszThis;
462 ULONG ul = 0;
463
464 for (ul = 0;
465 ul < pEnv->cVars;
466 ul++)
467 {
468 pszThis = *ppszThis;
469 free(pszThis);
470 // *ppszThis = NULL;
471 // next environment string
472 ppszThis++;
473 }
474
475 free(pEnv->papszVars);
476 pEnv->cVars = 0;
477 }
478
479 return (arc);
480}
481
482/* ******************************************************************
483 *
484 * Application information
485 *
486 ********************************************************************/
487
488/*
489 *@@ appQueryAppType:
490 * returns the Control Program (Dos) and
491 * Win* PROG_* application types for the
492 * specified executable. Essentially, this
493 * is a wrapper around DosQueryAppType.
494 *
495 * pcszExecutable must be fully qualified.
496 * You can use doshFindExecutable to qualify
497 * it.
498 *
499 * This returns the APIRET of DosQueryAppType.
500 * If this is NO_ERROR; *pulDosAppType receives
501 * the app type of DosQueryAppType. In addition,
502 * *pulWinAppType is set to one of the following:
503 *
504 * -- PROG_FULLSCREEN
505 *
506 * -- PROG_PDD
507 *
508 * -- PROG_VDD
509 *
510 * -- PROG_DLL
511 *
512 * -- PROG_WINDOWEDVDM
513 *
514 * -- PROG_PM
515 *
516 * -- PROG_31_ENHSEAMLESSCOMMON
517 *
518 * -- PROG_WINDOWABLEVIO
519 *
520 * -- PROG_DEFAULT
521 *
522 *@@added V0.9.9 (2001-03-07) [umoeller]
523 *@@changed V0.9.12 (2001-05-27) [umoeller]: moved from winh.c to apps.c
524 *@@changed V0.9.14 (2001-08-07) [pr]: use FAPPTYP_* constants
525 *@@changed V0.9.16 (2001-12-08) [umoeller]: added checks for batch files, other optimizations
526 */
527
528APIRET appQueryAppType(const char *pcszExecutable,
529 PULONG pulDosAppType,
530 PULONG pulWinAppType)
531{
532 APIRET arc;
533
534/*
535 #define FAPPTYP_NOTSPEC 0x0000
536 #define FAPPTYP_NOTWINDOWCOMPAT 0x0001
537 #define FAPPTYP_WINDOWCOMPAT 0x0002
538 #define FAPPTYP_WINDOWAPI 0x0003
539 #define FAPPTYP_BOUND 0x0008
540 #define FAPPTYP_DLL 0x0010
541 #define FAPPTYP_DOS 0x0020
542 #define FAPPTYP_PHYSDRV 0x0040 // physical device driver
543 #define FAPPTYP_VIRTDRV 0x0080 // virtual device driver
544 #define FAPPTYP_PROTDLL 0x0100 // 'protected memory' dll
545 #define FAPPTYP_WINDOWSREAL 0x0200 // Windows real mode app
546 #define FAPPTYP_WINDOWSPROT 0x0400 // Windows protect mode app
547 #define FAPPTYP_WINDOWSPROT31 0x1000 // Windows 3.1 protect mode app
548 #define FAPPTYP_32BIT 0x4000
549*/
550
551 ULONG ulWinAppType = PROG_DEFAULT;
552
553 if (!(arc = DosQueryAppType((PSZ)pcszExecutable, pulDosAppType)))
554 {
555 // clear the 32-bit flag
556 // V0.9.16 (2001-12-08) [umoeller]
557 ULONG ulDosAppType = (*pulDosAppType) & ~FAPPTYP_32BIT,
558 ulLoAppType = ulDosAppType & 0xFFFF;
559
560 if (ulDosAppType & FAPPTYP_PHYSDRV) // 0x40
561 ulWinAppType = PROG_PDD;
562 else if (ulDosAppType & FAPPTYP_VIRTDRV) // 0x80
563 ulWinAppType = PROG_VDD;
564 else if ((ulDosAppType & 0xF0) == FAPPTYP_DLL) // 0x10
565 // DLL bit set
566 ulWinAppType = PROG_DLL;
567 else if (ulDosAppType & FAPPTYP_DOS) // 0x20
568 // DOS bit set?
569 ulWinAppType = PROG_WINDOWEDVDM;
570 else if ((ulDosAppType & FAPPTYP_WINDOWAPI) == FAPPTYP_WINDOWAPI) // 0x0003)
571 // "Window-API" == PM
572 ulWinAppType = PROG_PM;
573 else if (ulLoAppType == FAPPTYP_WINDOWSREAL)
574 ulWinAppType = PROG_31_ENHSEAMLESSCOMMON; // @@todo really?
575 else if ( (ulLoAppType == FAPPTYP_WINDOWSPROT31) // 0x1000) // windows program (?!?)
576 || (ulLoAppType == FAPPTYP_WINDOWSPROT) // ) // windows program (?!?)
577 )
578 ulWinAppType = PROG_31_ENHSEAMLESSCOMMON; // PROG_31_ENH;
579 else if ((ulDosAppType & FAPPTYP_WINDOWAPI /* 0x03 */ ) == FAPPTYP_WINDOWCOMPAT) // 0x02)
580 ulWinAppType = PROG_WINDOWABLEVIO;
581 else if ((ulDosAppType & FAPPTYP_WINDOWAPI /* 0x03 */ ) == FAPPTYP_NOTWINDOWCOMPAT) // 0x01)
582 ulWinAppType = PROG_FULLSCREEN;
583 }
584
585 if (ulWinAppType == PROG_DEFAULT)
586 {
587 // added checks for batch files V0.9.16 (2001-12-08) [umoeller]
588 PCSZ pcszExt;
589 if (pcszExt = doshGetExtension(pcszExecutable))
590 {
591 if (!stricmp(pcszExt, "BAT"))
592 {
593 ulWinAppType = PROG_WINDOWEDVDM;
594 arc = NO_ERROR;
595 }
596 else if (!stricmp(pcszExt, "CMD"))
597 {
598 ulWinAppType = PROG_WINDOWABLEVIO;
599 arc = NO_ERROR;
600 }
601 }
602 }
603
604 *pulWinAppType = ulWinAppType;
605
606 return (arc);
607}
608
609/*
610 *@@ appDescribeAppType:
611 * returns a "PROG_*" string for the given
612 * program type. Useful for WPProgram setup
613 * strings and such.
614 *
615 *@@added V0.9.16 (2001-10-06)
616 */
617
618PCSZ appDescribeAppType(PROGCATEGORY progc) // in: from PROGDETAILS.progc
619{
620 switch (progc)
621 {
622 case PROG_DEFAULT: return "PROG_DEFAULT";
623 case PROG_FULLSCREEN: return "PROG_FULLSCREEN";
624 case PROG_WINDOWABLEVIO: return "PROG_WINDOWABLEVIO";
625 case PROG_PM: return "PROG_PM";
626 case PROG_GROUP: return "PROG_GROUP";
627 case PROG_VDM: return "PROG_VDM";
628 // same as case PROG_REAL: return "PROG_REAL";
629 case PROG_WINDOWEDVDM: return "PROG_WINDOWEDVDM";
630 case PROG_DLL: return "PROG_DLL";
631 case PROG_PDD: return "PROG_PDD";
632 case PROG_VDD: return "PROG_VDD";
633 case PROG_WINDOW_REAL: return "PROG_WINDOW_REAL";
634 case PROG_30_STD: return "PROG_30_STD";
635 // same as case PROG_WINDOW_PROT: return "PROG_WINDOW_PROT";
636 case PROG_WINDOW_AUTO: return "PROG_WINDOW_AUTO";
637 case PROG_30_STDSEAMLESSVDM: return "PROG_30_STDSEAMLESSVDM";
638 // same as case PROG_SEAMLESSVDM: return "PROG_SEAMLESSVDM";
639 case PROG_30_STDSEAMLESSCOMMON: return "PROG_30_STDSEAMLESSCOMMON";
640 // same as case PROG_SEAMLESSCOMMON: return "PROG_SEAMLESSCOMMON";
641 case PROG_31_STDSEAMLESSVDM: return "PROG_31_STDSEAMLESSVDM";
642 case PROG_31_STDSEAMLESSCOMMON: return "PROG_31_STDSEAMLESSCOMMON";
643 case PROG_31_ENHSEAMLESSVDM: return "PROG_31_ENHSEAMLESSVDM";
644 case PROG_31_ENHSEAMLESSCOMMON: return "PROG_31_ENHSEAMLESSCOMMON";
645 case PROG_31_ENH: return "PROG_31_ENH";
646 case PROG_31_STD: return "PROG_31_STD";
647
648// Warp 4 toolkit defines, whatever these were designed for...
649#ifndef PROG_DOS_GAME
650 #define PROG_DOS_GAME (PROGCATEGORY)21
651#endif
652#ifndef PROG_WIN_GAME
653 #define PROG_WIN_GAME (PROGCATEGORY)22
654#endif
655#ifndef PROG_DOS_MODE
656 #define PROG_DOS_MODE (PROGCATEGORY)23
657#endif
658
659 case PROG_DOS_GAME: return "PROG_DOS_GAME";
660 case PROG_WIN_GAME: return "PROG_WIN_GAME";
661 case PROG_DOS_MODE: return "PROG_DOS_MODE";
662
663 // added this V0.9.16 (2001-12-08) [umoeller]
664 case PROG_WIN32: return "PROG_WIN32";
665 }
666
667 return NULL;
668}
669
670/*
671 *@@ appIsWindowsApp:
672 * checks the specified program category
673 * (PROGDETAILS.progt.progc) for whether
674 * it represents a Win-OS/2 application.
675 *
676 * Returns:
677 *
678 * -- 0: no windows app (it's VIO, OS/2
679 * or DOS fullscreen, or PM).
680 *
681 * -- 1: Win-OS/2 standard app.
682 *
683 * -- 2: Win-OS/2 enhanced-mode app.
684 *
685 *@@added V0.9.12 (2001-05-26) [umoeller]
686 */
687
688ULONG appIsWindowsApp(ULONG ulProgCategory)
689{
690 switch (ulProgCategory)
691 {
692 case PROG_31_ENHSEAMLESSVDM: // 17
693 case PROG_31_ENHSEAMLESSCOMMON: // 18
694 case PROG_31_ENH: // 19
695 return (2);
696
697#ifndef PROG_30_STD
698 #define PROG_30_STD (PROGCATEGORY)11
699#endif
700
701#ifndef PROG_30_STDSEAMLESSVDM
702 #define PROG_30_STDSEAMLESSVDM (PROGCATEGORY)13
703#endif
704
705 case PROG_WINDOW_REAL: // 10
706 case PROG_30_STD: // 11
707 case PROG_WINDOW_AUTO: // 12
708 case PROG_30_STDSEAMLESSVDM: // 13
709 case PROG_30_STDSEAMLESSCOMMON: // 14
710 case PROG_31_STDSEAMLESSVDM: // 15
711 case PROG_31_STDSEAMLESSCOMMON: // 16
712 case PROG_31_STD: // 20
713 return (1);
714 }
715
716 return (0);
717}
718
719/* ******************************************************************
720 *
721 * Application start
722 *
723 ********************************************************************/
724
725/*
726 *@@ CallBatchCorrectly:
727 * fixes the specified PROGDETAILS for
728 * command files in the executable part
729 * by inserting /C XXX into the parameters
730 * and setting the executable according
731 * to an environment variable.
732 *
733 *@@added V0.9.6 (2000-10-16) [umoeller]
734 *@@changed V0.9.7 (2001-01-15) [umoeller]: now using XSTRING
735 *@@changed V0.9.12 (2001-05-27) [umoeller]: moved from winh.c to apps.c
736 */
737
738VOID CallBatchCorrectly(PPROGDETAILS pProgDetails,
739 PXSTRING pstrParams, // in/out: modified parameters (reallocated)
740 const char *pcszEnvVar, // in: env var spec'g command proc
741 // (e.g. "OS2_SHELL"); can be NULL
742 const char *pcszDefProc) // in: def't command proc (e.g. "CMD.EXE")
743{
744 // XXX.CMD file as executable:
745 // fix args to /C XXX.CMD
746
747 PSZ pszOldParams = NULL;
748 ULONG ulOldParamsLength = pstrParams->ulLength;
749 if (ulOldParamsLength)
750 // we have parameters already:
751 // make a backup... we'll append that later
752 pszOldParams = strdup(pstrParams->psz);
753
754 // set new params to "/C filename.cmd"
755 xstrcpy(pstrParams, "/C ", 0);
756 xstrcat(pstrParams,
757 pProgDetails->pszExecutable,
758 0);
759
760 if (pszOldParams)
761 {
762 // .cmd had params:
763 // append space and old params
764 xstrcatc(pstrParams, ' ');
765 xstrcat(pstrParams,
766 pszOldParams,
767 ulOldParamsLength);
768 free(pszOldParams);
769 }
770
771 // set executable to $(OS2_SHELL)
772 pProgDetails->pszExecutable = NULL;
773 if (pcszEnvVar)
774 pProgDetails->pszExecutable = getenv(pcszEnvVar);
775 if (!pProgDetails->pszExecutable)
776 pProgDetails->pszExecutable = (PSZ)pcszDefProc;
777 // should be on PATH
778}
779
780/*
781 *@@ appQueryDefaultWin31Environment:
782 * returns the default Win-OS/2 3.1 environment
783 * from OS2.INI, which you can then merge with
784 * your process environment to be able to
785 * start Win-OS/2 sessions properly with
786 * appStartApp.
787 *
788 * Caller must free() the return value.
789 *
790 *@@added V0.9.12 (2001-05-26) [umoeller]
791 */
792
793PSZ appQueryDefaultWin31Environment(VOID)
794{
795 PSZ pszReturn = NULL;
796 ULONG ulSize = 0;
797 // get default environment (from Win-OS/2 settings object)
798 // from OS2.INI
799 PSZ pszDefEnv = prfhQueryProfileData(HINI_USER,
800 "WINOS2",
801 "PM_GlobalWindows31Settings",
802 &ulSize);
803 if (pszDefEnv)
804 {
805 if (pszReturn = (PSZ)malloc(ulSize + 2))
806 {
807 PSZ p;
808 memset(pszReturn, 0, ulSize + 2);
809 memcpy(pszReturn, pszDefEnv, ulSize);
810
811 for (p = pszReturn;
812 p < pszReturn + ulSize;
813 p++)
814 if (*p == ';')
815 *p = 0;
816
817 // okay.... now we got an OS/2-style environment
818 // with 0, 0, 00 strings
819 }
820
821 free(pszDefEnv);
822 }
823
824 return (pszReturn);
825}
826
827/*
828 *@@ appStartApp:
829 * wrapper around WinStartApp which fixes the
830 * specified PROGDETAILS to (hopefully) work
831 * work with all executable types.
832 *
833 * This fixes the executable info to support:
834 *
835 * -- starting "*" executables (command prompts
836 * for OS/2, DOS, Win-OS/2);
837 *
838 * -- starting ".CMD" and ".BAT" files as
839 * PROGDETAILS.pszExecutable;
840 *
841 * -- starting apps which are not fully qualified
842 * and therefore assumed to be on the PATH.
843 *
844 * Unless it is "*", PROGDETAILS.pszExecutable must
845 * be a proper file name. The full path may be omitted
846 * if it is on the PATH, but the extension (.EXE etc.)
847 * must be given. You can use doshFindExecutable to
848 * find executables if you don't know the extension.
849 *
850 * This also handles and merges special and default
851 * environments for the app to be started. The
852 * following should be respected:
853 *
854 * -- As with WinStartApp, if PROGDETAILS.pszEnvironment
855 * is NULL, the new app inherits a default environment
856 * from the shell.
857 *
858 * -- However, if you specify an environment, you _must_
859 * specify a complete environment. This function
860 * will not merge environments. Use
861 * appSetEnvironmentVar to change environment
862 * variables in a complete environment set.
863 *
864 * -- If PROGDETAILS specifies a Win-OS/2 session
865 * and PROGDETAILS.pszEnvironment is empty,
866 * this uses the default Win-OS/2 environment.
867 * See appQueryDefaultWin31Environment.
868 *
869 * Even though this isn't clearly said in PMREF,
870 * PROGDETAILS.swpInitial is important:
871 *
872 * -- To start a session minimized, set SWP_MINIMIZE.
873 *
874 * -- To start a VIO session with auto-close disabled,
875 * set the half-documented SWP_NOAUTOCLOSE flag (0x8000)
876 * This flag is now in the newer toolkit headers.
877 *
878 * In addition, this supports the following session
879 * flags with ulFlags if PROG_DEFAULT is specified:
880 *
881 * -- APP_RUN_FULLSCREEN
882 *
883 * -- APP_RUN_ENHANCED
884 *
885 * -- APP_RUN_STANDARD
886 *
887 * -- APP_RUN_SEPARATE
888 *
889 * Since this calls WinStartApp in turn, this
890 * requires a message queue on the calling thread.
891 *
892 * Note that this also does minimal checking on
893 * the specified parameters so it can return something
894 * more meaningful than FALSE like WinStartApp.
895 * As a result, you get a DOS error code now (V0.9.16).
896 *
897 * Most importantly:
898 *
899 * -- ERROR_INVALID_THREADID: not running on thread 1.
900 * Since this uses WinStartApp internally and
901 * WinStartApp completely hangs the session manager
902 * if a Win-OS/2 full-screen session is started from
903 * a thread that is NOT thread 1, this will now fail
904 * with this error for safety (V0.9.16).
905 *
906 * -- ERROR_INVALID_PARAMETER: pcProgDetails or
907 * phapp is NULL; or PROGDETAILS.pszExecutable is NULL.
908 *
909 * -- ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND:
910 * PROGDETAILS.pszExecutable and/or PROGDETAILS.pszStartupDir
911 * are invalid.
912 * A NULL PROGDETAILS.pszStartupDir is supported though.
913 *
914 * -- ERROR_NOT_ENOUGH_MEMORY
915 *
916 *@@added V0.9.6 (2000-10-16) [umoeller]
917 *@@changed V0.9.7 (2000-12-10) [umoeller]: PROGDETAILS.swpInitial no longer zeroed... this broke VIOs
918 *@@changed V0.9.7 (2000-12-17) [umoeller]: PROGDETAILS.pszEnvironment no longer zeroed
919 *@@changed V0.9.9 (2001-01-27) [umoeller]: crashed if PROGDETAILS.pszExecutable was NULL
920 *@@changed V0.9.12 (2001-05-26) [umoeller]: fixed PROG_DEFAULT
921 *@@changed V0.9.12 (2001-05-27) [umoeller]: moved from winh.c to apps.c
922 *@@changed V0.9.14 (2001-08-07) [pr]: removed some env. strings for Win. apps.
923 *@@changed V0.9.14 (2001-08-23) [pr]: added session type options
924 *@@changed V0.9.16 (2001-10-19) [umoeller]: added prototype to return APIRET
925 *@@changed V0.9.16 (2001-10-19) [umoeller]: added thread-1 check
926 *@@changed V0.9.16 (2001-12-06) [umoeller]: now using doshSearchPath for finding pszExecutable if not qualified
927 *@@changed V0.9.16 (2002-01-04) [umoeller]: removed error report if startup directory was drive letter only
928 *@@changed V0.9.16 (2002-01-04) [umoeller]: added more detailed error reports and *FailingName params
929 */
930
931APIRET appStartApp(HWND hwndNotify, // in: notify window or NULLHANDLE
932 const PROGDETAILS *pcProgDetails, // in: program spec (req.)
933 ULONG ulFlags, // in: APP_RUN_* flags
934 HAPP *phapp, // out: application handle if NO_ERROR is returned
935 ULONG cbFailingName,
936 PSZ pszFailingName)
937{
938 APIRET arc = NO_ERROR;
939 PROGDETAILS ProgDetails;
940
941 if (pszFailingName)
942 *pszFailingName = '\0';
943
944 if (!pcProgDetails || !phapp)
945 return (ERROR_INVALID_PARAMETER);
946
947 memcpy(&ProgDetails, pcProgDetails, sizeof(PROGDETAILS));
948 // pointers still point into old prog details buffer
949 ProgDetails.Length = sizeof(PROGDETAILS);
950 ProgDetails.progt.fbVisible = SHE_VISIBLE;
951
952 // all this only makes sense if this contains something...
953 // besides, this crashed on string comparisons V0.9.9 (2001-01-27) [umoeller]
954 if ( (!ProgDetails.pszExecutable)
955 || (!(*(ProgDetails.pszExecutable)))
956 )
957 arc = ERROR_INVALID_PARAMETER;
958 else if (doshMyTID() != 1) // V0.9.16 (2001-10-19) [umoeller]
959 arc = ERROR_INVALID_THREADID;
960 else
961 {
962 ULONG ulIsWinApp;
963
964 CHAR szFQExecutable[CCHMAXPATH];
965
966 XSTRING strParamsPatched;
967 PSZ pszWinOS2Env = 0;
968
969 // memset(&ProgDetails.swpInitial, 0, sizeof(SWP));
970 // this wasn't a good idea... WPProgram stores stuff
971 // in here, such as the "minimize on startup" -> SWP_MINIMIZE
972
973 // duplicate parameters...
974 // we need this for string manipulations below...
975 if (ProgDetails.pszParameters)
976 xstrInitCopy(&strParamsPatched,
977 ProgDetails.pszParameters,
978 100);
979 else
980 // no old params:
981 xstrInit(&strParamsPatched, 100);
982
983 // _Pmpf((__FUNCTION__ ": old progc: 0x%lX", pcProgDetails->progt.progc));
984 // _Pmpf((" pszTitle: %s", (ProgDetails.pszTitle) ? ProgDetails.pszTitle : NULL));
985 // _Pmpf((" pszIcon: %s", (ProgDetails.pszIcon) ? ProgDetails.pszIcon : NULL));
986
987 // program type fixups
988 switch (ProgDetails.progt.progc) // that's a ULONG
989 {
990 case ((ULONG)-1): // we get that sometimes...
991 case PROG_DEFAULT:
992 {
993 // V0.9.12 (2001-05-26) [umoeller]
994 ULONG ulDosAppType;
995 appQueryAppType(ProgDetails.pszExecutable,
996 &ulDosAppType,
997 &ProgDetails.progt.progc);
998 }
999 break;
1000 }
1001
1002 // set session type from option flags
1003 if (ulFlags & APP_RUN_FULLSCREEN)
1004 {
1005 if (ProgDetails.progt.progc == PROG_WINDOWABLEVIO)
1006 ProgDetails.progt.progc = PROG_FULLSCREEN;
1007
1008 if (ProgDetails.progt.progc == PROG_WINDOWEDVDM)
1009 ProgDetails.progt.progc = PROG_VDM;
1010 }
1011
1012 if (ulIsWinApp = appIsWindowsApp(ProgDetails.progt.progc))
1013 {
1014 if (ulFlags & APP_RUN_FULLSCREEN)
1015 ProgDetails.progt.progc = (ulFlags & APP_RUN_ENHANCED)
1016 ? PROG_31_ENH
1017 : PROG_31_STD;
1018 else
1019 {
1020 if (ulFlags & APP_RUN_STANDARD)
1021 ProgDetails.progt.progc = (ulFlags & APP_RUN_SEPARATE)
1022 ? PROG_31_STDSEAMLESSVDM
1023 : PROG_31_STDSEAMLESSCOMMON;
1024
1025 if (ulFlags & APP_RUN_ENHANCED)
1026 ProgDetails.progt.progc = (ulFlags & APP_RUN_SEPARATE)
1027 ? PROG_31_ENHSEAMLESSVDM
1028 : PROG_31_ENHSEAMLESSCOMMON;
1029 }
1030
1031 // re-run V0.9.16 (2001-10-19) [umoeller]
1032 ulIsWinApp = appIsWindowsApp(ProgDetails.progt.progc);
1033 }
1034
1035 /*
1036 * command lines fixups:
1037 *
1038 */
1039
1040 if (!strcmp(ProgDetails.pszExecutable, "*"))
1041 {
1042 /*
1043 * "*" for command sessions:
1044 *
1045 */
1046
1047 if (ulIsWinApp == 2)
1048 {
1049 // enhanced Win-OS/2 session:
1050 PSZ psz = NULL;
1051 if (strParamsPatched.ulLength)
1052 // "/3 " + existing params
1053 psz = strdup(strParamsPatched.psz);
1054
1055 xstrcpy(&strParamsPatched, "/3 ", 0);
1056
1057 if (psz)
1058 {
1059 xstrcat(&strParamsPatched, psz, 0);
1060 free(psz);
1061 }
1062 }
1063
1064 if (ulIsWinApp)
1065 {
1066 // cheat: WinStartApp doesn't support NULL
1067 // for Win-OS2 sessions, so manually start winos2.com
1068 ProgDetails.pszExecutable = "WINOS2.COM";
1069 // this is a DOS app, so fix this to DOS fullscreen
1070 ProgDetails.progt.progc = PROG_VDM;
1071 }
1072 else
1073 // for all other executable types
1074 // (including OS/2 and DOS sessions),
1075 // set pszExecutable to NULL; this will
1076 // have WinStartApp start a cmd shell
1077 ProgDetails.pszExecutable = NULL;
1078
1079 } // end if (strcmp(pProgDetails->pszExecutable, "*") == 0)
1080 else
1081 {
1082 // check if the executable is fully qualified; if so,
1083 // check if the executable file exists
1084 if ( (ProgDetails.pszExecutable[1] == ':')
1085 && (strchr(ProgDetails.pszExecutable, '\\'))
1086 )
1087 {
1088 ULONG ulAttr;
1089 if (!(arc = doshQueryPathAttr(ProgDetails.pszExecutable,
1090 &ulAttr)))
1091 {
1092 // make sure startup dir is really a directory
1093 if (ProgDetails.pszStartupDir)
1094 {
1095 // it is valid to specify a startup dir of "C:"
1096 if ( (strlen(ProgDetails.pszStartupDir) > 2)
1097 && (!(arc = doshQueryPathAttr(ProgDetails.pszStartupDir,
1098 &ulAttr)))
1099 && (!(ulAttr & FILE_DIRECTORY))
1100 )
1101 arc = ERROR_PATH_NOT_FOUND;
1102 }
1103 }
1104 }
1105 else
1106 {
1107 // _not_ fully qualified: look it up on the PATH then
1108 // V0.9.16 (2001-12-06) [umoeller]
1109 if (!(arc = doshSearchPath("PATH",
1110 ProgDetails.pszExecutable,
1111 szFQExecutable,
1112 sizeof(szFQExecutable))))
1113 // alright, found it:
1114 ProgDetails.pszExecutable = szFQExecutable;
1115 }
1116
1117 if (!arc)
1118 {
1119 PSZ pszExtension;
1120 switch (ProgDetails.progt.progc)
1121 {
1122 /*
1123 * .CMD files fixups
1124 *
1125 */
1126
1127 case PROG_FULLSCREEN: // OS/2 fullscreen
1128 case PROG_WINDOWABLEVIO: // OS/2 window
1129 {
1130 if ( (pszExtension = doshGetExtension(ProgDetails.pszExecutable))
1131 && (!stricmp(pszExtension, "CMD"))
1132 )
1133 {
1134 CallBatchCorrectly(&ProgDetails,
1135 &strParamsPatched,
1136 "OS2_SHELL",
1137 "CMD.EXE");
1138 }
1139 break; }
1140
1141 case PROG_VDM: // DOS fullscreen
1142 case PROG_WINDOWEDVDM: // DOS window
1143 {
1144 if ( (pszExtension = doshGetExtension(ProgDetails.pszExecutable))
1145 && (!stricmp(pszExtension, "BAT"))
1146 )
1147 {
1148 CallBatchCorrectly(&ProgDetails,
1149 &strParamsPatched,
1150 NULL,
1151 "COMMAND.COM");
1152 }
1153 break; }
1154 } // end switch (ProgDetails.progt.progc)
1155 }
1156 }
1157
1158 if (!arc)
1159 {
1160 if ( (ulIsWinApp)
1161 && ( (ProgDetails.pszEnvironment == NULL)
1162 || (!strlen(ProgDetails.pszEnvironment))
1163 )
1164 )
1165 {
1166 // this is a windoze app, and caller didn't bother
1167 // to give us an environment:
1168 // we MUST set one then, or we'll get the strangest
1169 // errors, up to system hangs. V0.9.12 (2001-05-26) [umoeller]
1170
1171 DOSENVIRONMENT Env = {0};
1172
1173 // get standard WIN-OS/2 environment
1174 PSZ pszTemp = appQueryDefaultWin31Environment();
1175
1176 if (!(arc = appParseEnvironment(pszTemp,
1177 &Env)))
1178 {
1179 // now override KBD_CTRL_BYPASS=CTRL_ESC
1180 if ( (!(arc = appSetEnvironmentVar(&Env,
1181 "KBD_CTRL_BYPASS=CTRL_ESC",
1182 FALSE))) // add last
1183 && (!(arc = appConvertEnvironment(&Env,
1184 &pszWinOS2Env, // freed at bottom
1185 NULL)))
1186 )
1187 ProgDetails.pszEnvironment = pszWinOS2Env;
1188
1189 appFreeEnvironment(&Env);
1190 }
1191
1192 free(pszTemp);
1193 }
1194
1195 if (!arc)
1196 {
1197 if (!ProgDetails.pszTitle)
1198 ProgDetails.pszTitle = ProgDetails.pszExecutable;
1199
1200 ProgDetails.pszParameters = strParamsPatched.psz;
1201
1202 _Pmpf((__FUNCTION__ ": progt.progc: %d", ProgDetails.progt.progc));
1203 _Pmpf((" progt.fbVisible: 0x%lX", ProgDetails.progt.fbVisible));
1204 _Pmpf((" progt.pszTitle: \"%s\"", (ProgDetails.pszTitle) ? ProgDetails.pszTitle : "NULL"));
1205 _Pmpf((" exec: \"%s\"", (ProgDetails.pszExecutable) ? ProgDetails.pszExecutable : "NULL"));
1206 _Pmpf((" params: \"%s\"", (ProgDetails.pszParameters) ? ProgDetails.pszParameters : "NULL"));
1207 _Pmpf((" startup: \"%s\"", (ProgDetails.pszStartupDir) ? ProgDetails.pszStartupDir : "NULL"));
1208 _Pmpf((" pszIcon: \"%s\"", (ProgDetails.pszIcon) ? ProgDetails.pszIcon : "NULL"));
1209 /* _Pmpf((" environment: "));
1210 {
1211 PSZ pszThis = ProgDetails.pszEnvironment;
1212 while (pszThis && *pszThis)
1213 {
1214 _Pmpf((" \"%s\"", pszThis));
1215 pszThis += strlen(pszThis) + 1;
1216 }
1217 }
1218 */
1219
1220 _Pmpf((" swpInitial.fl = 0x%lX, x = %d, y = %d, cx = %d, cy = %d:",
1221 ProgDetails.swpInitial.fl,
1222 ProgDetails.swpInitial.x,
1223 ProgDetails.swpInitial.y,
1224 ProgDetails.swpInitial.cx,
1225 ProgDetails.swpInitial.cy));
1226 _Pmpf((" behind = %d, hwnd = %d, res1 = %d, res2 = %d",
1227 ProgDetails.swpInitial.hwndInsertBehind,
1228 ProgDetails.swpInitial.hwnd,
1229 ProgDetails.swpInitial.ulReserved1,
1230 ProgDetails.swpInitial.ulReserved2));
1231
1232 if (pszFailingName)
1233 strhncpy0(pszFailingName, ProgDetails.pszExecutable, cbFailingName);
1234
1235 /* if (WinMessageBox(HWND_DESKTOP,
1236 NULLHANDLE,
1237 (ProgDetails.pszExecutable) ? ProgDetails.pszExecutable : "NULL",
1238 "Start?",
1239 0,
1240 MB_YESNO | MB_MOVEABLE)
1241 != MBID_YES)
1242 arc = ERROR_INTERRUPT;
1243 else */
1244 {
1245 if (!(*phapp = WinStartApp(hwndNotify,
1246 // receives WM_APPTERMINATENOTIFY
1247 &ProgDetails,
1248 strParamsPatched.psz,
1249 NULL, // "reserved", PMREF says...
1250 SAF_INSTALLEDCMDLINE)))
1251 // we MUST use SAF_INSTALLEDCMDLINE
1252 // or no Win-OS/2 session will start...
1253 // whatever is going on here... Warp 4 FP11
1254
1255 // do not use SAF_STARTCHILDAPP, or the
1256 // app will be terminated automatically
1257 // when the WPS terminates!
1258 {
1259 // cannot start app:
1260 _Pmpf((__FUNCTION__ ": WinStartApp failed"));
1261 arc = ERROR_FILE_NOT_FOUND;
1262 // unfortunately WinStartApp doesn't
1263 // return meaningful codes like DosStartSession, so
1264 // try to see what happened
1265 /*
1266 switch (ERRORIDERROR(WinGetLastError(0)))
1267 {
1268 case PMERR_DOS_ERROR: // (0x1200)
1269 {
1270 arc = ERROR_FILE_NOT_FOUND;
1271
1272 // this is probably the case where the module
1273 // couldn't be loaded, so try DosStartSession
1274 // to get a meaningful return code... note that
1275 // this cannot handle hwndNotify then
1276 /* RESULTCODES result;
1277 arc = DosExecPgm(pszFailingName,
1278 cbFailingName,
1279 EXEC_ASYNC,
1280 NULL, // ProgDetails.pszParameters,
1281 NULL, // ProgDetails.pszEnvironment,
1282 &result,
1283 ProgDetails.pszExecutable);
1284 */
1285 /* ULONG sid, pid;
1286 STARTDATA SData;
1287 SData.Length = sizeof(STARTDATA);
1288 SData.Related = SSF_RELATED_CHILD; //INDEPENDENT;
1289 SData.FgBg = SSF_FGBG_FORE;
1290 SData.TraceOpt = SSF_TRACEOPT_NONE;
1291
1292 SData.PgmTitle = ProgDetails.pszTitle;
1293 SData.PgmName = ProgDetails.pszExecutable;
1294 SData.PgmInputs = ProgDetails.pszParameters;
1295
1296 SData.TermQ = NULL;
1297 SData.Environment = ProgDetails.pszEnvironment;
1298 SData.InheritOpt = SSF_INHERTOPT_PARENT; // ignored
1299 SData.SessionType = SSF_TYPE_DEFAULT;
1300 SData.IconFile = 0;
1301 SData.PgmHandle = 0;
1302
1303 SData.PgmControl = SSF_CONTROL_VISIBLE;
1304
1305 SData.InitXPos = 30;
1306 SData.InitYPos = 40;
1307 SData.InitXSize = 200;
1308 SData.InitYSize = 140;
1309 SData.Reserved = 0;
1310 SData.ObjectBuffer = pszFailingName;
1311 SData.ObjectBuffLen = cbFailingName;
1312
1313 arc = DosStartSession(&SData, &sid, &pid);
1314 }
1315 break;
1316
1317 case PMERR_INVALID_APPL: // (0x1530)
1318 // Attempted to start an application whose type is not
1319 // recognized by OS/2.
1320 arc = ERROR_INVALID_EXE_SIGNATURE;
1321 break;
1322
1323 case PMERR_INVALID_PARAMETERS: // (0x1208)
1324 // An application parameter value is invalid for
1325 // its converted PM type. For example: a 4-byte
1326 // value outside the range -32 768 to +32 767 cannot be
1327 // converted to a SHORT, and a negative number cannot
1328 // be converted to a ULONG or USHORT.
1329 arc = ERROR_INVALID_DATA;
1330 break;
1331
1332 case PMERR_STARTED_IN_BACKGROUND: // (0x1532)
1333 // The application started a new session in the
1334 // background.
1335 arc = ERROR_SMG_START_IN_BACKGROUND;
1336 break;
1337
1338 case PMERR_INVALID_WINDOW: // (0x1206)
1339 // The window specified with a Window List call
1340 // is not a valid frame window.
1341
1342 default:
1343 arc = ERROR_BAD_FORMAT;
1344 break;
1345 }
1346 */
1347 }
1348 }
1349 }
1350 }
1351
1352 xstrClear(&strParamsPatched);
1353 if (pszWinOS2Env)
1354 free(pszWinOS2Env);
1355 } // end if (ProgDetails.pszExecutable)
1356
1357 _Pmpf((__FUNCTION__ ": returning %d", arc));
1358
1359 return (arc);
1360}
1361
1362/*
1363 *@@ appWaitForApp:
1364 * waits for the specified application to terminate
1365 * and returns its exit code.
1366 *
1367 *@@added V0.9.9 (2001-03-07) [umoeller]
1368 */
1369
1370BOOL appWaitForApp(HWND hwndNotify, // in: notify window
1371 HAPP happ, // in: app to wait for
1372 PULONG pulExitCode) // out: exit code (ptr can be NULL)
1373{
1374 BOOL brc = FALSE;
1375
1376 if (happ)
1377 {
1378 // app started:
1379 // enter a modal message loop until we get the
1380 // WM_APPTERMINATENOTIFY for happ. Then we
1381 // know the app is done.
1382 HAB hab = WinQueryAnchorBlock(hwndNotify);
1383 QMSG qmsg;
1384 // ULONG ulXFixReturnCode = 0;
1385 while (WinGetMsg(hab, &qmsg, NULLHANDLE, 0, 0))
1386 {
1387 if ( (qmsg.msg == WM_APPTERMINATENOTIFY)
1388 && (qmsg.hwnd == hwndNotify)
1389 && (qmsg.mp1 == (MPARAM)happ)
1390 )
1391 {
1392 // xfix has terminated:
1393 // get xfix return code from mp2... this is:
1394 // -- 0: everything's OK, continue.
1395 // -- 1: handle section was rewritten, restart Desktop
1396 // now.
1397 if (pulExitCode)
1398 *pulExitCode = (ULONG)qmsg.mp2;
1399 brc = TRUE;
1400 // do not dispatch this
1401 break;
1402 }
1403
1404 WinDispatchMsg(hab, &qmsg);
1405 }
1406 }
1407
1408 return (brc);
1409}
1410
1411/*
1412 *@@ appQuickStartApp:
1413 * shortcut for simply starting an app and
1414 * waiting until it's finished.
1415 *
1416 * On errors, NULLHANDLE is returned.
1417 *
1418 * If pulReturnCode != NULL, it receives the
1419 * return code of the app.
1420 *
1421 *@@added V0.9.16 (2001-10-19) [umoeller]
1422 */
1423
1424HAPP appQuickStartApp(const char *pcszFile,
1425 ULONG ulProgType, // e.g. PROG_PM
1426 const char *pcszArgs,
1427 PULONG pulExitCode)
1428{
1429 PROGDETAILS pd = {0};
1430 HAPP happ,
1431 happReturn = NULLHANDLE;
1432 CHAR szDir[CCHMAXPATH] = "";
1433 PCSZ p;
1434 HWND hwndObject;
1435
1436 pd.Length = sizeof(pd);
1437 pd.progt.progc = ulProgType;
1438 pd.progt.fbVisible = SHE_VISIBLE;
1439 pd.pszExecutable = (PSZ)pcszFile;
1440 pd.pszParameters = (PSZ)pcszArgs;
1441 if (p = strrchr(pcszFile, '\\'))
1442 {
1443 strhncpy0(szDir,
1444 pcszFile,
1445 p - pcszFile);
1446 pd.pszStartupDir = szDir;
1447 }
1448
1449 if ( (hwndObject = winhCreateObjectWindow(WC_STATIC, NULL))
1450 && (!appStartApp(hwndObject,
1451 &pd,
1452 0,
1453 &happ,
1454 0,
1455 NULL))
1456 )
1457 {
1458 if (appWaitForApp(hwndObject,
1459 happ,
1460 pulExitCode))
1461 happReturn = happ;
1462 }
1463
1464 return (happReturn);
1465}
Note: See TracBrowser for help on using the repository browser.