source: trunk/dll/systemf.c @ 766

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

format cleanup

  • 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 766 2007-08-05 20:21:20Z 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() & 4095));
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 = 3, 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(200);
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.