/*++ 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 "precomp.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; } FreeSplMem(pMem); pMem = AllocSplMem(dwNeeded); if (pMem == NULL) { return FALSE; } 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; } for (cTokens = 0; psz && *psz; ) { // // We're skipping consecutive commas // while (psz && *psz == L',') { psz++; } if (psz && *psz) { cTokens++; psz = wcschr(psz, L','); } } if (!cTokens) { SetLastError(ERROR_INVALID_PARAMETER); return NULL; } 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: */ StringCbCopy(pDest, cb - ((PBYTE)pDest - (PBYTE)pResult), pKeyData); ppToken = pResult->pTokens; for (psz = pDest; psz && *psz; ) { while (psz && *psz == L',') { psz++; } if (psz && *psz) { *ppToken++ = psz; psz = wcschr(psz, L','); if (psz) { *psz = L'\0'; psz++; } } } pResult->cTokens = cTokens; return( pResult ); }