source: trunk/dll/systemf.c @ 730

Last change on this file since 730 was 730, checked in by Gregg Young, 13 years ago

Preliminary work on variable sized container buffers. Removes szFileName etc. Builds fine but traps.

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