[comp.os.os2] Set WINDOWABLE bit

boegehol@az33.informatik.uni-stuttgart.de (Harald Boegeholz) (02/10/90)

In article <1989@ncrcan.Toronto.NCR.COM> brian@ncrcan.Toronto.NCR.COM (Brian A. Onn) writes:

   But does anyone know which bit int the header changes?  I don't have any of
   the PM toolkits, but I do have MSC5.1.

   If I knew which bit was the WINABLE bit, then I could flip it and all would
   be fine, n'est pas?

I wrote a little program called exehdr that allows to modify the
flag word in the new exe header. Starting it with EXEFLAGS x.EXE +200
sets the WINABLE bit of an exe file, but -- as opposed to the toolkit
programs -- WITHOUT CHECKING if the program uses any calls that are
not allowed. Since the program is only a few lines long, I appended
the source below. 

For the programs you write yourself, there is a more elegant way to
set the WINDOWABLE bit: use a DEF-file when linking. The minimum
DEF file that will do the job contains the single line
   NAME WINDOWCOMPAT
You can be slightly more elaborate, as in the exeflags program below.

Hope that helps

Harald Boegeholz

===== source file exeflags.c follows ... ====
/* this is exeflags.c. Exeflag modifies the flags
   in OS/2 executable files. (new header offset 0x0c) */

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#define INCL_BASE
#include <os2.h>

static void check_error(int err, int line, char *file);
static void error(char *, ...);
int main(int, char **);

#define chk(err) check_error(err, __LINE__, __FILE__)

static void check_error(err, line, file)
int err;
int line;
char *file;
{
  if (err==0)
    return;
  error("OS/2 error occured: code %d. Sourcefile %s (line %d)\n", err, file, line);
}

static void error(fmt, ...)
char *fmt;
{
  va_list arg_ptr;

  va_start(arg_ptr,fmt);
  vprintf(fmt,arg_ptr);
  va_end(arg_ptr);
  exit(2);
}

struct _oldexehdr
{
  USHORT mz;
  char dummy[0x3a];
  long newhdradr;
} oldexehdr;

struct _newexehdr
{
  USHORT ne;
  char dummy[0x0a];
  USHORT flags;
} newexehdr;

int main(argc, argv)
int argc;
char **argv;
{
  USHORT action, bytesread, byteswritten;
  HFILE exefile;
  long newpos;
  USHORT mask;
  
  printf("This is EXEFLAGS. (c) 1989 by Harald Boegeholz\n"
    "This program modifies the flags of an EXE-file\n");
  if (argc!=3 || (argv[2][0]!='+' && argv[2][0]!='-'))
    error("usage: EXEFLAGS exefilename [+|-]mask\n"
          "example: set window compatibility flag: EXEFLAGS x.EXE +200\n");
  if (sscanf(&argv[2][1], "%4hx", &mask)!=1)
    error("invalid mask: `%s'!\n", &argv[2][1]);
  chk(DosOpen(argv[1], &exefile, &action, 0L, 0, 1, 0x12, 0L));
  chk(DosRead(exefile, &oldexehdr, sizeof oldexehdr, &bytesread));
  if (bytesread!=sizeof oldexehdr)
    error("Invalid EXE-file: unexpected EOF\n");
  if (oldexehdr.mz != 0x5a4d)
    error("Invalid EXE-file: error in old header\n");
  chk(DosChgFilePtr(exefile, oldexehdr.newhdradr, 0, &newpos));
  chk(DosRead(exefile, &newexehdr, sizeof newexehdr, &bytesread));
  if (bytesread!=sizeof newexehdr)
    error("Invalid EXE-file: unexpected EOF\n");
  if (newexehdr.ne != 0x454e)
    error("Invalid EXE-file: error in new header\n");
  printf("Changing flags: %.4X", newexehdr.flags);
  if (argv[2][0]=='+')
    newexehdr.flags |= mask;
  else
    newexehdr.flags &= ~mask;
  printf(" to %.4X...\n", newexehdr.flags);
  chk(DosChgFilePtr(exefile, oldexehdr.newhdradr, 0, &newpos));
  chk(DosWrite(exefile, &newexehdr, sizeof newexehdr, &byteswritten));
  if (byteswritten!=sizeof newexehdr)
    error("Error writing to EXE-file. Disk full?\n");
  chk(DosClose(exefile));
  printf("done.\n");
  return 0;
}

====== file exeflags.def follows ... =====
; Module definition file for EXEFLAGS program

NAME Exeflags WINDOWCOMPAT
DESCRIPTION 'Exeflags  (c) 1989 by Harald Boegeholz'
====== make file exeflags follows ... =====
EXEFLAGS.OBJ: EXEFLAGS.C
        cl -W3 -c exeflags.c

EXEFLAGS.EXE: EXEFLAGS.OBJ
        link exeflags,,,/NOD:slibce slibcep,exeflags