🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.windows.ms.programmer
Article #2715

Re: Windows3/TSR interface HELP

#2715
From: glenn boozer
Date: Fri, 17 May 1991 22:39
298 lines
10521 bytes
>This is the second posting - I didn't see any replies the first time :-(
>
>I'm trying to write a Windows 3 application which needs to interface to a
>DOS TSR which communicates via an interrupt. Everything works fine in real
>mode, but I get UAEs and reboots in both standard and 386 enhanced mode.
>
>The code segment that's causing the trouble:
>
>        union   REGS    InRegs;
>        union   REGS    OutRegs;
>        struct  SREGS   SegRegs;
>        HANDLE          hBuffer;
>        LPSTR           lpBuffer;
>
>        InRegs.h.ah = 11;
>        InRegs.h.al = 1;
>        InRegs.x.dx = FP_OFF(lpBuffer);
>
>        hBuffer = GlobalAlloc(GHND,512L);

Does not work in either Protected mode

>        lpBuffer = GlobalLock(hBuffer);
>        InRegs.x.di = FP_OFF(lpBuffer);
>        SegRegs.es = FP_SEG(lpBuffer);
>
>        int86x(0x7f,&InRegs,&OutRegs,&SegRegs);
>
>I've done a lot of RTFM-ing, but to no avail (at least, the problem isn't
>solved). I didn't write the TSR, so it's difficult to get changes done
>there (I don't have the source).

You shouldn't need to change the TSR.

>
>My suspicions are that lpBuffer above is a 'selector' (whatever that is)
>rather than a true, _far address, and when the TSR (assembler) uses the
>ES:DI register pair, some sort of protect trap takes place.

You guessed it!

>
>Any ideas on how to solve this? Do I need to spend $500 on the DDK and write
>a special device driver? Please help - any comments would be appreciated;
>if you did respond via a posting last time, please respond again. My upstream
>site lost some news just about the "right" time :-(.

The DDK is not needed for this.


The problem is that the TSR runs in REAL mode and the windows applications
running in either protected mode use selectors[LDT] and not pointers[SEG:OFF]
to access buffers.

What follows I hastily pieced together from code I have working.

In a nutshell:
       To Send a buffer address to the TSR [Send it a REAL address of
        Segment:Offset, not a protected mode selector]
        1) DosAllocate a memory buffer  [This will be a buffer in the first
           640K of address space.  This buffer is LOCKED and will not move.
           [Not recomended by Microsoft]
        2) Copy the data from the buffer that is in "Windows Application space"
           into the DOS Buffer
        3) Get the Segment and Offset of the DOS buffer and pass that to the
           TSR.
        4) Release the DOS Buffer

       To use the buffer address [Segment:offset] that the TSR send you:
        1) Allocate a Selector [Not recomended by Microsoft]
        2) Set the selector base and length with the data returned from the
           TSR.  [Not recomended by Microsoft]
        3) Use the data
        4) Return the selector.  [Not recomended by Microsoft]


Code fragments follow.  If I left anything out, give me a note.

#define FarPtr far *
/* Data structure for calls to the TSR */
typedef union
    {
    char FarPtr p; /* treat as pointer */
    void FarPtr pv;
    struct /* treat as selector/offset */
        {
            unsigned off;
            unsigned sel;
   } w;
   long l;  /*treat as arithmetic item */
    } FPTR;

/* Data structure for value returned from GlobalDosAlloc*/
typedef union
    {
    struct /* treat as selector and a paragraph */
        {
            WORD sel;
            WORD par;
   } w;
   DWORD d; /*treat as DWORD */
    } DOSPS;

/* Windows kernel calls not in WINDOWS.H */

WORD  FAR PASCAL SetSelectorBase(HANDLE hSelector, DWORD dwBase);
WORD  FAR PASCAL SetSelectorLimit(HANDLE hSelector, DWORD dwLimit);
DWORD FAR PASCAL GlobalDosAlloc(DWORD);
WORD  FAR PASCAL GlobalDosFree(WORD);

#define WIND386ENHANCEDMODE (dwWinMemFlags & WF_ENHANCED)
#define WINDPROTECTEDMODE     (dwWinMemFlags & WF_PMODE)
#define WINDREALMODE        (!(dwWinMemFlags & WF_PMODE))

static DWORD  near dwWinMemFlags;        /* Window Memory configuration Flags */
static DOSPS  near lpsDosParagraphSelector;
static WORD   near hPhysMemHandle;           /* Handle to DOS memory */
static LPSTR  near lpPhysPtr;               /* pointer to DOS memory */

/***************************************************************************
*Name: GetWindowsMemoryConfig                                              *
*                                                                          *
*    Get windows memory configuration word so we can execute Real Mode and *
*    Protected Mode specific code.                                         *
*                                                                          *
*Returns: Nothing                                                          *
***************************************************************************/

void GetWindowsMemoryConfig ()
{
   dwWinMemFlags = GetWinFlags();
}


/***********************************************************************

Module:  GetPhysicalMemoryHandle

   Sets up a physical memory handle which can be used to access memory in
protected mode.
  If the selector cannot be created, the call fails and returns NULL.

  returns: Memory access handle.

**********************************************************************/

WORD FAR PASCAL GetPhysicalMemoryHandle()
{

    HANDLE hSel;
    HANDLE hSel2;


    /*. create a selector for use by MakePhysicalMemoryPtr() */
    /* The how of this is taken from an SR response. */
    if ((hSel2 = GlobalAlloc(GMEM_FIXED,(long) 64)) != NULL) {
        hSel = AllocSelector(hSel2);
        GlobalFree(hSel2);
    } else {
        return (WORD)NULL;
    }
    /* successful:  return a handle */
    return hSel;
}

/***********************************************************************

Module:  MakePhysicalMemoryPtr

   This routine sets up a protected mode pointer to a specified physical
address.  This pointer is good for 4K of memory at the specified physical
segment + offset address.  If NULL, an error occurred.

  returns: Memory access handle.

**********************************************************************/

LPSTR NEAR PASCAL MakePhysicalMemoryPtr(

    WORD wMemHandle,             /* Physical memory handle created by
                                    GetPhysicalMemoryHandle().
                                    a valid selector is passed.            */

    WORD wSegment,               /* Segment address to be referenced.  This
                                    is a real-mode paragraph number.       */


    WORD wOffset                 /* Offset from Segment address to be referenced. */

)
{
    /*. set selector base from wSegment parameter */
    SetSelectorBase(wMemHandle, (((LONG)wSegment)<<4) + wOffset );
    /*. set limit for 4K bytes accessable */
    SetSelectorLimit(wMemHandle,(long) 0x0FFF);
    /*. make and return a long pointer using passed wMemHandle */
    return (LPSTR)MAKELONG(0, wMemHandle);
}

/***************************************************************************

Routine: FreePhysicalMemoryPtr

   Deallocates the specified physical memory pointer.  This call is used to
free a selector in protect mode.  Once this function is run on a pointer,
the physical memory handle which was used to create that pointer
CANNOT BE USED AGAIN.

Returns:  nothing

***************************************************************************/

void FAR PASCAL FreePhysicalMemoryPtr(

    LPSTR lpMemPtr               /* Pointer used for access to physical
                                    memory.  The pointer must have been
                                    constructed by MakePhysicalMemoryPtr().*/

)
{
    /*. free the selector */
    FreeSelector(HIWORD(lpMemPtr));

}




[Main code fragment]

This code handles Real, Standard, and Enhanced memory models all at the
same time.


/* Get Memory Model  [Real/Standard/Enhanced] */
       GetWindowsMemoryConfig();


/* If in protected mode, assign LOW memory for use with TSR */
       if (WINDPROTECTEDMODE) {
           /* Assign a memory handle for physical address usage with TSR */
           if(!( hPhysMemHandle = GetPhysicalMemoryHandle())) {
               MessageBoxOKHand ((LPSTR) "Error ??: Could not get Physical Memory for TSR");
               return;
           }
       }

[call tsr-calling routine n times]

/* if in protected mode, return the handle we allocated */
       if ( WINDPROTECTEDMODE) {
           FreePhysicalMemoryPtr(lpPhysPtr);
       }
       return;




[TSR-Calling routine]
static FPTR   near fp;

        if( WINDPROTECTEDMODE) {  /* allocate DOS memory to put data into */
           lpsDosParagraphSelector.d = GlobalDosAlloc((DWORD)max( APImsg.len, 4));
           if(APImsg.buffer) {
                lmemcpy( (LPSTR)MAKELONG(0, lpsDosParagraphSelector.w.sel), APImsg.buffer,
                         max( APImsg.len, 4));
               fp.w.sel = lpsDosParagraphSelector.w.par;
               fp.w.off = 0;
           } else {    /* Null Pointer */
               fp.p = 0L;
           }
        } else {        /* If in real mode */
            fp.p = APImsg.buffer;
        }
        dx = fp.w.sel;
        bx = fp.w.off;
/* Call the tsr */
    rc = int2f(ax, cx, si, di, dx, bx, (unsigned int far *)&di,
        (unsigned int far *)&si, (unsigned int far *)&cx,
        (unsigned int far *)&dx, (unsigned int far *)&bx);

    if(WINDPROTECTEDMODE {
        (void) GlobalDosFree(lpsDosParagraphSelector.w.sel);
    }

    if(WINDREALMODE) {
        fp.w.sel = dx;
        fp.w.off = bx;
    } else {
        lpPhysPtr = MakePhysicalMemoryPtr(hPhysMemHandle, dx /* segment addr */,
                                        bx /* offset */);
        fp.p = lpPhysPtr;       /* use pointer lpPhysPtr */
    }


Glenn Boozer  glenn@imagen.com
QMS  [PostScript is what we do best]
Technical Details
Message-ID: <glenn.674519982@imagen>
Path: arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!rpi!zaphod.mps.ohio-state.edu!swrinde!cs.utexas.edu!sun-barr!newstop!sun!imagen!imagen!glenn
References: <1991May15.133642.40@mgc.uucp>

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!rpi!zaphod.mps.ohio-state.edu!swrinde!cs.utexas.edu!sun-barr!newstop!sun!imagen!imagen!glenn
From: glenn@imagen.com (glenn boozer)
Newsgroups: comp.windows.ms.programmer
Subject: Re: Windows3/TSR interface HELP
Keywords: win3 tsr interrupt selector far
Message-ID: <glenn.674519982@imagen>
Date: 17 May 91 22:39:42 GMT
References: <1991May15.133642.40@mgc.uucp>
Sender: news@imagen.com
Organization: imagen
Lines: 298