windows-nt/Source/XPSP1/NT/base/mvdm/wow32/wgprnset.c
2020-09-26 16:20:57 +08:00

590 lines
19 KiB
C

/*++
*
* WOW v1.0
*
* Copyright (c) 1991, Microsoft Corporation
*
* WGPRNSET.C
* WOW32 printer setup support routines
*
* These routines help a Win 3.0 task to complete the printer set-up,
* when a user initiates the printer setup from the file menu of an
* application.
*
* History:
* Created 18-Apr-1991 by Chandan Chauhan (ChandanC)
--*/
#include "precomp.h"
#pragma hdrstop
MODNAME(wgprnset.c);
DLLENTRYPOINTS spoolerapis[WOW_SPOOLERAPI_COUNT] = {"EXTDEVICEMODE", NULL,
"DEVICEMODE", NULL,
"DEVICECAPABILITIES", NULL,
"OpenPrinterA", NULL,
"StartDocPrinterA", NULL,
"StartPagePrinter", NULL,
"EndPagePrinter", NULL,
"EndDocPrinter", NULL,
"ClosePrinter", NULL,
"WritePrinter", NULL,
"DeletePrinter", NULL,
"GetPrinterDriverDirectoryA", NULL,
"AddPrinterA", NULL,
"AddPrinterDriverA", NULL,
"AddPortExA",NULL};
/****************************************************************************
* *
* ULONG FASTCALL WG32DeviceMode (PVDMFRAME pFrame) *
* *
* (hWnd, hModule, lpDeviceName, lpOutPut) *
* *
* This function passes WDevMode structure (which is per wow task) to *
* Win32 printer driver ExtDeviceMode API. This structure is then *
* initialized by the printer driver based on the user input. *
* *
* Later on, when a WOW task creates a dc (by CreateDC API), the device *
* mode (WDevMode) structure associated with this wow task is passed along *
* with the CreateDC API. Which contains the printer setup information *
* needed to print the document. *
* *
****************************************************************************/
ULONG FASTCALL WG32DeviceMode (PVDMFRAME pFrame)
{
register PDEVICEMODE16 parg16;
PSZ psz3 = NULL;
PSZ psz4 = NULL;
ULONG l = 0;
HWND hwnd32;
GETARGPTR(pFrame, sizeof(DEVICEMODE16), parg16);
// copy all 16-bit params now since 16-bit memory may move if this calls
// into a 16-bit fax driver
hwnd32 = HWND32(parg16->f1);
if(parg16->f3) {
if(!(psz3 = malloc_w_strcpy_vp16to32(parg16->f3, FALSE, 0)))
goto ExitPath;
}
if(parg16->f4) {
if(!(psz4 = malloc_w_strcpy_vp16to32(parg16->f4, FALSE, 0)))
goto ExitPath;
}
// invalidate all flat ptrs to 16:16 memory now!
FREEARGPTR(parg16);
if (!(spoolerapis[WOW_DEVICEMODE].lpfn)) {
if (!LoadLibraryAndGetProcAddresses("WINSPOOL.DRV", spoolerapis, WOW_SPOOLERAPI_COUNT)) {
goto ExitPath;
}
}
// this can callback into a 16-bit fax driver!
(*spoolerapis[WOW_DEVICEMODE].lpfn)(hwnd32, NULL, psz3, psz4);
l = 1;
ExitPath:
if(psz3) {
free_w(psz3);
}
if(psz4) {
free_w(psz4);
}
RETURN(l); // DeviceMode returns void. Charisma checks the return value!
}
/*****************************************************************************
* *
* ULONG FASTCALL WG32ExtDeviceMode (PVDMFRAME pFrame) *
* *
* INT (hWnd, hDriver, lpDevModeOutput, lpDeviceName, lpPort, *
* lpDevModeInput, lpProfile, wMode) *
* *
* This function is same as DeviceMode except that the wow task supplies *
* a DeviceMode structure. Apart from it, this API can be called in *
* different modes. *
* *
*****************************************************************************/
ULONG FASTCALL WG32ExtDeviceMode (PVDMFRAME pFrame)
{
UINT cb;
LONG l = 0;
HWND hWnd1;
WORD wMode8;
PSZ psz4 = NULL;
PSZ psz5 = NULL;
PSZ psz7 = NULL;
VPVOID vpdm3, vpdm6;
LPDEVMODE lpdmInput6;
LPDEVMODE lpdmOutput3;
register PEXTDEVICEMODE16 parg16;
GETARGPTR(pFrame, sizeof(EXTDEVICEMODE16), parg16);
// copy the 16-bit parameters into local vars since this may callback
// into a 16-bit fax driver and cause 16-bit memory to move
hWnd1 = HWND32(parg16->f1);
vpdm3 = FETCHDWORD(parg16->f3);
vpdm6 = FETCHDWORD(parg16->f6);
wMode8 = FETCHWORD(parg16->f8);
if(parg16->f4) {
if(!(psz4 = malloc_w_strcpy_vp16to32(parg16->f4, FALSE, 0)))
goto ExitPath;
}
if(parg16->f5) {
if(!(psz5 = malloc_w_strcpy_vp16to32(parg16->f5, FALSE, 0)))
goto ExitPath;
}
if(parg16->f7) {
if(!(psz7 = malloc_w_strcpy_vp16to32(parg16->f7, FALSE, 0)))
goto ExitPath;
}
FREEARGPTR(parg16);
// all flat ptrs to 16:16 memory are now invalid!!
if (!(spoolerapis[WOW_EXTDEVICEMODE].lpfn)) {
if (!LoadLibraryAndGetProcAddresses("WINSPOOL.DRV", spoolerapis, WOW_SPOOLERAPI_COUNT)) {
goto ExitPath;
}
}
lpdmInput6 = ThunkDevMode16to32(FETCHDWORD(vpdm6));
/* if they want output buffer size OR they want to fill output buffer */
if( (wMode8 == 0) || (wMode8 & DM_OUT_BUFFER) ) {
/* get required size for output buffer */
l = (*spoolerapis[WOW_EXTDEVICEMODE].lpfn)(hWnd1,
NULL,
NULL,
psz4,
psz5,
lpdmInput6,
psz7,
0);
// adjust size for WOW handling (see notes in wstruc.c)
if(l > 0) {
l += sizeof(WOWDM31);
cb = (UINT)l;
}
/* if caller wants output buffer filled... */
if( (wMode8 != 0) && (vpdm3 != 0L) && l > 0 ) {
if( lpdmOutput3 = malloc_w(l) ) {
l = (*spoolerapis[WOW_EXTDEVICEMODE].lpfn)(hWnd1,
NULL,
lpdmOutput3,
psz4,
psz5,
lpdmInput6,
psz7,
wMode8);
/* Data in lpdmOutput3 is only valid with IDOK return. */
if( l == IDOK ) {
// do our WOW magic on this before we give it to the app
ThunkDevMode32to16(vpdm3, lpdmOutput3, cb);
}
free_w(lpdmOutput3);
}
else {
l = -1L;
}
}
}
/* else call for cases where they don't want to fill the output buffer */
else {
l = (*spoolerapis[WOW_EXTDEVICEMODE].lpfn)(hWnd1,
NULL,
NULL,
psz4,
psz5,
lpdmInput6,
psz7,
wMode8);
}
if( lpdmInput6 ) {
free_w(lpdmInput6);
}
ExitPath:
if(psz4) {
free_w(psz4);
}
if(psz5) {
free_w(psz5);
}
if(psz7) {
free_w(psz7);
}
RETURN((ULONG)l);
}
ULONG FASTCALL WG32DeviceCapabilities (PVDMFRAME pFrame)
{
LONG l=0L, cb;
WORD fwCap3;
PBYTE pOutput4, pOutput32;
VPVOID vpOutput4;
PSZ psz1 = NULL;
PSZ psz2 = NULL;
LPDEVMODE lpdmInput5;
DWORD dwDM5;
register PDEVICECAPABILITIES16 parg16;
GETARGPTR(pFrame, sizeof(DEVICECAPABILITIES16), parg16);
// copy the 16-bit parameters into local vars since this may callback
// into a 16-bit fax driver and cause 16-bit memory to move
if(parg16->f1) {
if(!(psz1 = malloc_w_strcpy_vp16to32(parg16->f1, FALSE, 0)))
goto ExitPath;
}
if(parg16->f2) {
if(!(psz2 = malloc_w_strcpy_vp16to32(parg16->f2, FALSE, 0)))
goto ExitPath;
}
fwCap3 = FETCHWORD(parg16->f3);
vpOutput4 = FETCHDWORD(parg16->f4);
dwDM5 = FETCHDWORD(parg16->f5);
FREEARGPTR(parg16);
// all flat ptrs to 16:16 memory are now invalid!!
if (!(spoolerapis[WOW_DEVICECAPABILITIES].lpfn)) {
if (!LoadLibraryAndGetProcAddresses("WINSPOOL.DRV",
spoolerapis,
WOW_SPOOLERAPI_COUNT)) {
goto ExitPath;
}
}
lpdmInput5 = ThunkDevMode16to32(dwDM5);
LOGDEBUG(LOG_TRACE, ("WG32DeviceCapabilities %d\n", fwCap3));
switch (fwCap3) {
// These ones do not fill up an output Buffer
case DC_FIELDS:
case DC_DUPLEX:
case DC_SIZE:
case DC_EXTRA:
case DC_VERSION:
case DC_DRIVER:
case DC_TRUETYPE:
case DC_ORIENTATION:
case DC_COPIES:
l = (*spoolerapis[WOW_DEVICECAPABILITIES].lpfn)(psz1,
psz2,
fwCap3,
NULL,
lpdmInput5);
LOGDEBUG(LOG_TRACE, ("WG32DeviceCapabilities simple case returned %d\n", l));
// adjust for WOW handling of devmodes // see notes in wstruc.c
if(fwCap3 == DC_SIZE) {
// we always convert NT DevModes to Win3.1 DevModes
WOW32WARNMSGF((l==sizeof(DEVMODE)),
("WG32DeviceCapabilities: Unexpected DevMode size: %d\n",l));
if(l == sizeof(DEVMODE)) {
l = sizeof(DEVMODE31);
}
}
// adjust DriverExtra to allow for difference between NT devmodes
// & Win3.1 devmodes + our secret WOW stuff at the end
else if(fwCap3 == DC_EXTRA) {
l += WOW_DEVMODEEXTRA;
}
// we tell them Win3.1 for the spec version too
else if(fwCap3 == DC_VERSION) {
l = WOW_DEVMODE31SPEC; // tell 'em the spec version is Win3.1
}
break;
#ifdef DBCS
// not supported the following indexes.
case DC_MINEXTENT:
case DC_MAXEXTENT:
#ifdef DBCS_LATER
#if DBG
LOGDEBUG(0,("WG32DeviceCapabilities more complicated:"));
#endif
pOutput = malloc_w(8);
if (pOutput) {
l = DEVICECAPABILITIES(psz1, psz2, parg16->f3, pOutput, pdmInput5);
if (l >= 0) {
#if DBG
LOGDEBUG(0,("Copying %d points from %0x to %0x\n", l, pOutput, pb4));
#endif
putpoint16(parg16->f4, 1, pOutput);
}
free_w(pOutput);
}
else {
l = -1;
}
#endif // DBCS_LATER
l = -1; // always error return
break;
#endif // DBCS
// These require an output buffer
case DC_PAPERS:
case DC_PAPERSIZE:
#ifndef DBCS
case DC_MINEXTENT:
case DC_MAXEXTENT:
#endif // !DBCS
case DC_BINS:
case DC_BINNAMES:
case DC_ENUMRESOLUTIONS:
case DC_FILEDEPENDENCIES:
case DC_PAPERNAMES:
LOGDEBUG(LOG_TRACE, ("WG32DeviceCapabilities more complicated:\n"));
// We've got to figure out how much memory we will need
GETMISCPTR(vpOutput4, pOutput4);
if (pOutput4) {
cb = (*spoolerapis[WOW_DEVICECAPABILITIES].lpfn)(psz1,
psz2,
fwCap3,
NULL,
lpdmInput5);
FREEPSZPTR(pOutput4); // invalidate -16bit memory may have moved
LOGDEBUG(LOG_TRACE, ("we need %d bytes ", cb));
if (cb > 0) {
switch (fwCap3) {
case DC_PAPERS:
cb *= 2;
break;
case DC_BINNAMES:
cb *= 24;
break;
case DC_BINS:
cb*=2;
break;
case DC_FILEDEPENDENCIES:
case DC_PAPERNAMES:
cb *= 64;
break;
case DC_MAXEXTENT:
case DC_MINEXTENT:
case DC_PAPERSIZE:
cb *= 8;
LOGDEBUG(LOG_TRACE, ("DC_PAPERSIZE called: Needed %d bytes\n", cb));
break;
case DC_ENUMRESOLUTIONS:
cb *= sizeof(LONG)*2;
break;
} // end switch
pOutput32 = malloc_w(cb);
if (pOutput32) {
l = (*spoolerapis[WOW_DEVICECAPABILITIES].lpfn)(psz1, psz2, fwCap3, pOutput32, lpdmInput5);
if (l >= 0) {
GETMISCPTR(vpOutput4, pOutput4);
switch (fwCap3) {
case DC_PAPERS:
if (CURRENTPTD()->dwWOWCompatFlags &
WOWCF_RESETPAPER29ANDABOVE) {
// wordperfect for windows 5.2 GPs if
// papertype is > 0x28. so reset such
// paper types to 0x1. In particular
// this happens if the selected printer
// is Epson LQ-510.
// - nanduri
LONG i = l;
while(i--) {
if (((LPWORD)pOutput32)[i] > 0x28) {
((LPWORD)pOutput32)[i] = 0x1;
}
}
} // end if
RtlCopyMemory(pOutput4, pOutput32, cb);
break;
case DC_MAXEXTENT:
case DC_MINEXTENT:
case DC_PAPERSIZE:
LOGDEBUG(LOG_TRACE, ("Copying %d points from %0x to %0x\n", l, pOutput32, pOutput4));
putpoint16(vpOutput4, l,(LPPOINT)pOutput32);
break;
default:
LOGDEBUG(LOG_TRACE, ("Copying %d bytes from %0x to %0x\n",cb, pOutput32, pOutput4));
RtlCopyMemory(pOutput4, pOutput32, cb);
break;
} // end switch
FLUSHVDMPTR(vpOutput4, (USHORT)cb, pOutput4);
FREEPSZPTR(pOutput4);
} // end if
free_w(pOutput32);
} else
l = -1;
} else
l = cb;
} else {
l = (*spoolerapis[WOW_DEVICECAPABILITIES].lpfn)(psz1,
psz2,
fwCap3,
NULL,
lpdmInput5);
LOGDEBUG(LOG_TRACE, ("No Output buffer specified: Returning %d\n", l));
}
break;
default:
LOGDEBUG(LOG_TRACE, ("!!!! WG32DeviceCapabilities unhandled %d\n", fwCap3));
l = -1L;
break;
} // end switch
if (lpdmInput5) {
free_w(lpdmInput5);
}
ExitPath:
if(psz1) {
free_w(psz1);
}
if(psz2) {
free_w(psz2);
}
RETURN(l);
}
BOOL LoadLibraryAndGetProcAddresses(char *name, DLLENTRYPOINTS *p, int num)
{
int i;
HINSTANCE hInst;
if (!(hInst = SafeLoadLibrary (name))) {
WOW32ASSERTMSGF (FALSE, ("WOW::LoadLibraryAndGetProcAddresses: LoadLibrary('%s') failed\n", name));
return FALSE;
}
for (i = 0; i < num ; i++) {
p[i].lpfn = (void *) GetProcAddress (hInst, (p[i].name));
WOW32ASSERTMSGF (p[i].lpfn, ("WOW::LoadLibraryAndGetProcAddresses: GetProcAddress(%s, '%s') failed\n", name, p[i].name));
}
return TRUE;
}
#ifdef i386
/*
* "Safe" version of LoadLibrary which preserves floating-point state
* across the load. This is critical on x86 because the FP state being
* preserved is the 16-bit app's state. MSVCRT.DLL is one offender which
* changes the Precision bits in its Dll init routine.
*
* On RISC, this is an alias for LoadLibrary
*
*/
HINSTANCE SafeLoadLibrary(char *name)
{
HINSTANCE hInst;
BYTE FpuState[108];
// Save the 487 state
_asm {
lea ecx, [FpuState]
fsave [ecx]
}
hInst = LoadLibrary(name);
// Restore the 487 state
_asm {
lea ecx, [FpuState]
frstor [ecx]
}
return hInst;
}
#endif //i386