313 lines
6.3 KiB
C
313 lines
6.3 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1994 - 1995 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
prnfile.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This module contains all the code necessary for testing printing"
|
||
|
to file to remote printers. There are two criteria based on which
|
||
|
we will print to a file.
|
||
|
|
||
|
Case 1:
|
||
|
|
||
|
This is the true NT style print to file. One of the ports of the
|
||
|
printer is a file port denoted as FILE: We will disregard any other
|
||
|
port and straight away dump this job to file.
|
||
|
|
||
|
|
||
|
Case 2:
|
||
|
|
||
|
This is the "PiggyBacking" case. Apps such as WinWord, Publisher
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Krishna Ganugapati (Krishna Ganugapati) 6-June-1994
|
||
|
|
||
|
Revision History:
|
||
|
6-June-1994 - Created.
|
||
|
|
||
|
--*/
|
||
|
#include <windows.h>
|
||
|
#include <winspool.h>
|
||
|
#include <winsplp.h>
|
||
|
#include <lm.h>
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include <rpc.h>
|
||
|
#include "winspl.h"
|
||
|
#include <offsets.h>
|
||
|
#include <w32types.h>
|
||
|
#include <local.h>
|
||
|
#include <splcom.h>
|
||
|
|
||
|
typedef struct _KEYDATA {
|
||
|
DWORD cb;
|
||
|
DWORD cTokens;
|
||
|
LPWSTR pTokens[1];
|
||
|
} KEYDATA, *PKEYDATA;
|
||
|
|
||
|
|
||
|
WCHAR *szFilePort = L"FILE:";
|
||
|
WCHAR *szNetPort = L"Net:";
|
||
|
|
||
|
//
|
||
|
// Function prototypes
|
||
|
//
|
||
|
|
||
|
PKEYDATA
|
||
|
CreateTokenList(
|
||
|
LPWSTR pKeyData
|
||
|
);
|
||
|
|
||
|
PKEYDATA
|
||
|
GetPrinterPortList(
|
||
|
HANDLE hPrinter
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
IsaFileName(
|
||
|
LPWSTR pOutputFile
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
IsaPortName(
|
||
|
PKEYDATA pKeyData,
|
||
|
LPWSTR pOutputFile
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
Win32IsGoingToFile(
|
||
|
HANDLE hPrinter,
|
||
|
LPWSTR pOutputFile
|
||
|
)
|
||
|
{
|
||
|
PKEYDATA pKeyData = NULL;
|
||
|
BOOL bErrorCode = FALSE;
|
||
|
|
||
|
if (!pOutputFile || !*pOutputFile) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
pKeyData = GetPrinterPortList(hPrinter);
|
||
|
|
||
|
if (pKeyData) {
|
||
|
|
||
|
//
|
||
|
// If it's not a port and it is a file name,
|
||
|
// then it is going to file.
|
||
|
//
|
||
|
if (!IsaPortName(pKeyData, pOutputFile) && IsaFileName(pOutputFile)) {
|
||
|
bErrorCode = TRUE;
|
||
|
}
|
||
|
|
||
|
FreeSplMem(pKeyData);
|
||
|
}
|
||
|
|
||
|
return bErrorCode;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
IsaFileName(
|
||
|
LPWSTR pOutputFile
|
||
|
)
|
||
|
{
|
||
|
HANDLE hFile = INVALID_HANDLE_VALUE;
|
||
|
WCHAR FullPathName[MAX_PATH];
|
||
|
LPWSTR pFileName=NULL;
|
||
|
|
||
|
//
|
||
|
// Hack for Word20c.Win
|
||
|
//
|
||
|
|
||
|
if (!_wcsicmp(pOutputFile, L"FILE")) {
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
if (wcslen(pOutputFile) < MAX_PATH &&
|
||
|
GetFullPathName(pOutputFile, COUNTOF(FullPathName), FullPathName, &pFileName)) {
|
||
|
if ((hFile = CreateFile(pOutputFile,
|
||
|
GENERIC_WRITE,
|
||
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||
|
NULL,
|
||
|
CREATE_ALWAYS,
|
||
|
FILE_ATTRIBUTE_NORMAL,
|
||
|
NULL)) != INVALID_HANDLE_VALUE) {
|
||
|
if (GetFileType(hFile) == FILE_TYPE_DISK) {
|
||
|
CloseHandle(hFile);
|
||
|
return(TRUE);
|
||
|
}else {
|
||
|
CloseHandle(hFile);
|
||
|
return(FALSE);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
IsaPortName(
|
||
|
PKEYDATA pKeyData,
|
||
|
LPWSTR pOutputFile
|
||
|
)
|
||
|
{
|
||
|
DWORD i = 0;
|
||
|
UINT uStrLen;
|
||
|
|
||
|
if (!pKeyData) {
|
||
|
return(FALSE);
|
||
|
}
|
||
|
for (i=0; i < pKeyData->cTokens; i++) {
|
||
|
if (!lstrcmpi(pKeyData->pTokens[i], pOutputFile)) {
|
||
|
return(TRUE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Hack for NeXY: ports
|
||
|
//
|
||
|
if (!_wcsnicmp(pOutputFile, L"Ne", 2)) {
|
||
|
|
||
|
uStrLen = wcslen( pOutputFile );
|
||
|
|
||
|
//
|
||
|
// Ne00: or Ne00 if app truncates it
|
||
|
//
|
||
|
if ( ( uStrLen == 5 ) || ( uStrLen == 4 ) ) {
|
||
|
|
||
|
// Check for two Digits
|
||
|
|
||
|
if (( pOutputFile[2] >= L'0' ) && ( pOutputFile[2] <= L'9' ) &&
|
||
|
( pOutputFile[3] >= L'0' ) && ( pOutputFile[3] <= L'9' )) {
|
||
|
|
||
|
//
|
||
|
// Check for the final : as in Ne01:,
|
||
|
// note some apps will truncate it.
|
||
|
//
|
||
|
if (( uStrLen == 5 ) && (pOutputFile[4] != L':')) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
PKEYDATA
|
||
|
GetPrinterPortList(
|
||
|
HANDLE hPrinter
|
||
|
)
|
||
|
{
|
||
|
LPBYTE pMem;
|
||
|
LPTSTR pPort;
|
||
|
DWORD dwPassed = 1024; //Try 1K to start with
|
||
|
LPPRINTER_INFO_2 pPrinter;
|
||
|
DWORD dwLevel = 2;
|
||
|
DWORD dwNeeded;
|
||
|
PKEYDATA pKeyData;
|
||
|
DWORD i = 0;
|
||
|
|
||
|
|
||
|
pMem = AllocSplMem(dwPassed);
|
||
|
if (pMem == NULL) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
if (!CacheGetPrinter(hPrinter, dwLevel, pMem, dwPassed, &dwNeeded)) {
|
||
|
DBGMSG(DBG_TRACE, ("GetPrinterPortList GetPrinter error is %d\n", GetLastError()));
|
||
|
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
|
||
|
return NULL;
|
||
|
}
|
||
|
pMem = ReallocSplMem(pMem, 0, dwNeeded);
|
||
|
dwPassed = dwNeeded;
|
||
|
if (!CacheGetPrinter(hPrinter, dwLevel, pMem, dwPassed, &dwNeeded)) {
|
||
|
FreeSplMem(pMem);
|
||
|
return (NULL);
|
||
|
}
|
||
|
}
|
||
|
pPrinter = (LPPRINTER_INFO_2)pMem;
|
||
|
|
||
|
//
|
||
|
// Fixes the null pPrinter->pPortName problem where
|
||
|
// downlevel may return null
|
||
|
//
|
||
|
|
||
|
if (!pPrinter->pPortName) {
|
||
|
FreeSplMem(pMem);
|
||
|
return(NULL);
|
||
|
}
|
||
|
|
||
|
pKeyData = CreateTokenList(pPrinter->pPortName);
|
||
|
FreeSplMem(pMem);
|
||
|
|
||
|
return(pKeyData);
|
||
|
}
|
||
|
|
||
|
|
||
|
PKEYDATA
|
||
|
CreateTokenList(
|
||
|
LPWSTR pKeyData
|
||
|
)
|
||
|
{
|
||
|
DWORD cTokens;
|
||
|
DWORD cb;
|
||
|
PKEYDATA pResult;
|
||
|
LPWSTR pDest;
|
||
|
LPWSTR psz = pKeyData;
|
||
|
LPWSTR *ppToken;
|
||
|
|
||
|
if (!psz || !*psz)
|
||
|
return NULL;
|
||
|
|
||
|
cTokens=1;
|
||
|
|
||
|
/* Scan through the string looking for commas,
|
||
|
* ensuring that each is followed by a non-NULL character:
|
||
|
*/
|
||
|
while ((psz = wcschr(psz, L',')) && psz[1]) {
|
||
|
|
||
|
cTokens++;
|
||
|
psz++;
|
||
|
}
|
||
|
|
||
|
cb = sizeof(KEYDATA) + (cTokens-1) * sizeof(LPWSTR) +
|
||
|
|
||
|
wcslen(pKeyData)*sizeof(WCHAR) + sizeof(WCHAR);
|
||
|
|
||
|
if (!(pResult = (PKEYDATA)AllocSplMem(cb)))
|
||
|
return NULL;
|
||
|
|
||
|
pResult->cb = cb;
|
||
|
|
||
|
/* Initialise pDest to point beyond the token pointers:
|
||
|
*/
|
||
|
pDest = (LPWSTR)((LPBYTE)pResult + sizeof(KEYDATA) +
|
||
|
(cTokens-1) * sizeof(LPWSTR));
|
||
|
|
||
|
/* Then copy the key data buffer there:
|
||
|
*/
|
||
|
wcscpy(pDest, pKeyData);
|
||
|
|
||
|
ppToken = pResult->pTokens;
|
||
|
|
||
|
psz = pDest;
|
||
|
|
||
|
do {
|
||
|
|
||
|
*ppToken++ = psz;
|
||
|
|
||
|
if ( psz = wcschr(psz, L',') )
|
||
|
*psz++ = L'\0';
|
||
|
|
||
|
} while (psz);
|
||
|
|
||
|
pResult->cTokens = cTokens;
|
||
|
|
||
|
return( pResult );
|
||
|
}
|