Category : C Source Code
Archive   : DPMIXM.ZIP
Filename : ENDSPOOL.C

 
Output of file : ENDSPOOL.C contained in archive : DPMIXM.ZIP
/*****************************************************************************
* *
* WENDSPOOL - Execute Banyan Vines EndSpool API call *
* *
* This program is provided to illustrate how to examine the real mode *
* interrupt table, grab a vector and examine the real mode memory area *
* pointed to by the vector. In addition, it illustrates the use of the *
* GlobalDosAlloc call and the DPMI interface to talk to the BANYAN API. *
* *
* The Banyan API requires that you pass the address of a command block *
* in DS:DX. This program maintains this as a local structure, then copies *
* the structure to a memory area that the real mode Vines API can access. *
* *
******************************************************************************
* *
* Written on 03/09/91 By Mike Flynn - Compuserve ID 76376,2273 *
* *
* Special Thanks to Peter Gofton for the DPMI and GlobalDosAlloc stuff and *
* to Steve Goulet for the selector manipulation help. *
* *
******************************************************************************
* *
* EXCUSE: Please excuse the primitive nature of this program as it is my *
* very first C program, and my first Windows program! The ASM code *
* for copying the data should be cleaned up..... *
* *
******************************************************************************
* *
* NOTE: This code does not support real-mode. However, it would be easy *
* to add if desired. *
* *
*****************************************************************************/


#include // required for all Windows applications
#include // required for FP_SEG & FP_OFF macros

#define VSP_SUCCESS 1
#define VSP_NONETWORK 2
#define VSP_NOPRINTJOBS 3
#define VSP_DPMIERROR 4
#define VSP_ERROR 5

#define ABSADDR(seg, ofs) ((((unsigned long) seg) << 4) + (ofs & 0xffff))

struct VINESPARMBLOCK
{
unsigned nCommand;
unsigned nActive;
unsigned long nParm1;
};

BYTE GetVinesVector(void);
unsigned char VinesEndSpool(struct VINESPARMBLOCK *);
VOID FAR PASCAL SetSelectorBase(WORD, DWORD );
VOID FAR PASCAL SetSelectorLimit(WORD, DWORD);
DWORD FAR PASCAL GlobalDosAlloc( DWORD );
int CallDPMI (BYTE nVector);

typedef struct tagSIMRINT
{
DWORD EDI;
DWORD ESI;
DWORD EBP;
DWORD Reserved;
DWORD EBX;
DWORD EDX;
DWORD ECX;
DWORD EAX;
WORD Flags;
WORD ES;
WORD DS;
WORD FS;
WORD GS;
WORD IP;
WORD CS;
WORD SP;
WORD SS;
} SIMRINT ;

SIMRINT sRealModeIntRegs = {0L,0L,0L,0L,0L,0L,0L,0L,0,0,0,0,0,0,0,0,0};

unsigned int dos_buf_seg,wSharedSelector;

static DWORD dwParmBlock;
BOOL protected_mode = FALSE;

int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)

{


struct VINESPARMBLOCK sParmBlock={0x201,0,0L};
unsigned nSpoolResult;
char szStatusBuf[36],szAppName[]="Banyan EndSpool";


if (hPrevInstance) // Other instances of app running?
{

MessageBox (NULL, "A copy of EndSpool is already running!",
szAppName, MB_OK | MB_SYSTEMMODAL);
return FALSE;

}

dwParmBlock = GlobalDosAlloc(sizeof(sParmBlock)); //Allocate shared mem

if (dwParmBlock == NULL) // If no mem, report it and xit
{

MessageBox (NULL, "Unable to allocate memory for VINES command.",
szAppName, MB_OK | MB_ICONSTOP);
return FALSE;

}

dos_buf_seg = HIWORD(dwParmBlock); // Get real mode segment
wSharedSelector = LOWORD(dwParmBlock); // Get prot mode selector


if (GetWinFlags() & WF_PMODE)
protected_mode = TRUE;

nSpoolResult = VinesEndSpool(&sParmBlock); // do the VINES call

switch (nSpoolResult)
{
case VSP_SUCCESS:
wsprintf (szStatusBuf,"Print job has been spooled to LPT%d:",sParmBlock);
MessageBox (NULL, szStatusBuf,szAppName, MB_OK );
break;

case VSP_NONETWORK:
MessageBox (NULL, "No VINES software Loaded",
szAppName, MB_OK | MB_ICONSTOP);
break;

case VSP_NOPRINTJOBS:
MessageBox (NULL, "No jobs to EndSpool",
szAppName, MB_OK | MB_ICONSTOP);
break;

case VSP_ERROR:
MessageBox (NULL, "Vines Network ERROR!",
szAppName, MB_OK | MB_ICONSTOP);
break;

case VSP_DPMIERROR:
MessageBox (NULL, "DPMI real mode error",
szAppName, MB_OK | MB_ICONSTOP);
break;

}

return FALSE;

}



unsigned char VinesEndSpool(struct VINESPARMBLOCK *parmblock)
{
BYTE nVinesVector;
unsigned nCount;

if (! (nVinesVector=GetVinesVector())) //Then go find it
return VSP_NONETWORK; //Couldn't find it

parmblock->nCommand = 0x0205; // Get spooled printer

// This peice of ASM stuff copies my VINES API data block
// into the shared memory as returned from GlobalDosAlloc

_asm
{
push es ;save ES

mov es,wSharedSelector ;get shared selector

mov di,0 ;offset is zip
mov si,parmblock ;point to my data structure

mov cx,4 ;4 words to copy (this should be calced)
cld ;dir is forward
rep movsw ;copy the data

pop es ;restore ES
}

if (!CallDPMI(nVinesVector)) // do the VINES API call
return VSP_DPMIERROR;

// This peice of ASM stuff copies the shared memory block back
// into the local data area.

_asm
{
push ds ;save ES
push es ;save ES

push ds ;save ES
pop es

mov di,parmblock ;point to my data structure

mov ds,wSharedSelector ;point to shared data area as source
mov si,0

mov cx,4 ;4 words to copy (this should be calced)
cld ;dir is forward
rep movsw ;copy the data

pop es ;restore ES
pop ds ;restore ES
}

if (!parmblock->nActive)
return VSP_NOPRINTJOBS;

parmblock->nCommand = 0x0201; // Endspool Command

// This peice of ASM stuff copies my VINES API data block
// into the shared memory as returned from GlobalDosAlloc

_asm
{
push es ;save ES

mov es,wSharedSelector ;get shared selector

mov di,0 ;offset is zip
mov si,parmblock ;point to my data structure

mov cx,4 ;4 words to copy (this should be calced)
cld ;dir is forward
rep movsw ;copy the data

pop es ;restore ES
}

if (!CallDPMI(nVinesVector)) // do the VINES API call
return VSP_DPMIERROR;

if (sRealModeIntRegs.EAX) // If VINES API returned non 0 then error
return VSP_ERROR;

return VSP_SUCCESS; // Return success!!!


}
BYTE GetVinesVector()
{

WORD wLocalDataSelector,wRealAddrSelector,wCurrentSegment,wCurrentOffset;

WORD nBase = (0x60*4); // Start with int 60H
unsigned char status = FALSE;

_asm
{

mov ax,ds
mov wRealAddrSelector,ax ;use my ds as prototype

}
/*

Allocate a new selector using the current DS as a template
(for granularity, privlidge et. al.). Set it's limit to 64K.

*/

wLocalDataSelector = AllocSelector(wRealAddrSelector);
SetSelectorLimit(wLocalDataSelector, 0xffff);

while (!status && nBase < (0x68 * 4))
{

SetSelectorBase(wLocalDataSelector, ABSADDR(0x0000,0)); //Set to seg 0

_asm
{

push es ;save ES
push di ;and DI

mov es,wLocalDataSelector ;get selector for INT vector table seg

mov di,nBase ;get offset

mov ax, word ptr es:[di] ;get int offset
mov wCurrentOffset,ax ;and save it

mov ax, word ptr es:[di+2] ;get int seg
mov wCurrentSegment,ax ;save it also

pop di ;restore regs
pop es

}

// point my selector to segment that INT vector pointed to

SetSelectorBase(wLocalDataSelector, ABSADDR(wCurrentSegment,0));

_asm
{

push es ;save ES
push di ;save DS

mov es,wLocalDataSelector ;get selector

mov di,wCurrentOffset ;and offset that INT pointed to

cmp word ptr es:[di-4],0x4142 ;look for VINES signature
jne gbnext ;not found then try next vector

cmp word ptr es:[di-2],0x564e ;look for VINES signature
jne gbnext ;not found then try next vector

mov al,TRUE ;Else, found it, indicate success
mov status,al

gbnext:

pop di ;restore regs
pop es

}

if (!status)
nBase += 4; // point to next vector if status = FALSE

}

FreeSelector(wLocalDataSelector); // Free up the selector

return (status ? nBase/4 : FALSE); //return result or FALSE

}

int CallDPMI (BYTE nVector)

{
char far *d = (char far *) &sRealModeIntRegs;
unsigned p_seg = FP_SEG(d);
unsigned p_off = FP_OFF(d);

sRealModeIntRegs.SS = 0 ; // Let DPMI deal with stack
sRealModeIntRegs.SP = 0 ;

sRealModeIntRegs.DS = dos_buf_seg; //Point DS to my memory seg
sRealModeIntRegs.EDX = 0L; //Segment Offset is 0

sRealModeIntRegs.EAX = 5L; //VINES API requires a 5 in AX

_asm
{

mov bh, 00h
mov bl, nVector ; Interrupt to call (Vines API)

xor cx, cx ; Nothing to copy to stack

mov es, p_seg ; Make es:di point to sRealModeIntRegs structure
mov di, p_off

mov ax, 0300h ; DPMI simulate real mode interrupt
int 31h ; DPMI interrupt
jnc EndDP ; DPMI sets carry flag if error

}

return FALSE;

EndDP: /* DPMI worked ok */

return TRUE;
}
/*

Here is the excerpt from the DPMI spec that describes the previous function:


11.1 Simulate Real Mode Interrupt


This function simulates an interrupt in real mode. It
will invoke the CS:IP specified by the real mode
interrupt vector and the handler must return by
executing an iret.

To Call

AX = 0300h
BL = Interrupt number
BH = Flags
Bit 0 = 1 resets the interrupt controller and A20
line
Other flags reserved and must be 0
CX = Number of words to copy from protected mode to
real mode stack
ES:(E)DI = Selector:Offset of real mode call structure

Returns

If function was successful:
Carry flag is clear.
ES:(E)DI = Selector:Offset of modified real mode call
structure

If function was not successful:
Carry flag is set.

Programmer's Notes

o The CS:IP in the real mode call structure is
ignored by this service. The appropriate
interrupt handler will be called based on the
value passed in BL.

o If the SS:SP fields are zero then a real mode
stack will be provided by the DPMI host.
Otherwise, the real mode SS:SP will be set to the
specified values before the interrupt handler is
called.

o The flags specified in the real mode call
structure will be pushed on the real mode stack
iret frame. The interrupt handler will be called
with the interrupt and trace flags clear.

o When the Int 31h returns, the real mode call
register structure will contain the values that
were returned by the real mode interrupt handler.

o It is up to the caller to remove any parameters
that were pushed on the protected mode stack.

o 32-bit programs must use ES:EDI to point to the
real mode call structure. 16-bit programs should
use ES:DI.

o The flag to reset the interrupt controller and A20
line is ignored by DPMI implementations that run
in Virtual 8086 mode. It causes DPMI
implementations that return to real mode to set
the interrupt controller and A20 address line
hardware to its normal real mode state.

*/


  3 Responses to “Category : C Source Code
Archive   : DPMIXM.ZIP
Filename : ENDSPOOL.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/