|
|
/*++
* * 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(L"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(L"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(L"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); }
// Note: This will only load from the system32 dir
BOOL LoadLibraryAndGetProcAddresses(WCHAR *name, DLLENTRYPOINTS *p, int num) { int i; HINSTANCE hInst;
if (!(hInst = SafeLoadLibrary (name))) { WOW32ASSERTMSGF (FALSE, ("WOW::LoadLibraryAndGetProcAddresses: LoadLibrary ('%ls') 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(%ls, '%s') failed\n", name, p[i].name)); }
return TRUE; }
/*
* "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. * * 02/03/27 Added new meaning for "Safe". This Function now also assures * that the .dll being loaded will be loaded only from the sys32 dir * to prevent spoofing the .dll being loaded. */ HINSTANCE SafeLoadLibrary(WCHAR *pszFileNameW) { HINSTANCE h; HINSTANCE hInst = NULL; UNICODE_STRING UnicodeFileName;
#ifdef i386
BYTE FpuState[108];
// Save the 487 state
_asm { lea ecx, [FpuState] fsave [ecx] } #endif //i386
RtlInitUnicodeString(&UnicodeFileName, pszFileNameW);
WOW32ASSERTMSG((pszSystemDirectory), ("WOW::SafeLoadLibrary:pszSystemDirectory == NULL!"));
if(NT_SUCCESS(LdrLoadDll(pszSystemDirectoryW, NULL, &UnicodeFileName, &h))){ hInst = h; } #ifdef i386
// Restore the 487 state
_asm { lea ecx, [FpuState] frstor [ecx] } #endif //i386
return hInst; }
|