Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1108 lines
30 KiB

/*++
Copyright (c) 1997 Microsoft Corporation
Abstract:
This module provides functionality for publishing printers
Author:
Steve Wilson (NT) November 1997
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
#include "pubprn.hxx"
#include "varconv.hxx"
#include "property.hxx"
#include "dsutil.hxx"
#include "client.h"
#define PPM_FACTOR 48
BOOL
PublishPrinterW(
HWND hwnd,
PCWSTR pszUNCName,
PCWSTR pszDN,
PCWSTR pszCN,
PWSTR *ppszDN,
DWORD dwAction
)
{
PRINTER_DEFAULTS Defaults;
HANDLE hPrinter = NULL;
HANDLE hServer = NULL;
PWSTR pszServerName = NULL;
PWSTR pszPrinterName = NULL;
PPRINTER_INFO_2 pInfo2 = NULL;
DWORD dwRet = ERROR_SUCCESS;
DWORD dwType;
DWORD dwMajorVersion;
DWORD dwDsPresent;
DWORD cbNeeded;
DWORD dwLength;
HRESULT hr;
WCHAR szDNSMachineName[INTERNET_MAX_HOST_NAME_LENGTH + 1];
WCHAR szFullUNCName[MAX_UNC_PRINTER_NAME];
WCHAR szShortServerName[MAX_PATH+1];
PWSTR pszFullUNCName;
PWSTR pszShortServerName;
PWSTR pszFullServerName;
if (InCSRProcess()) {
SetLastError(ERROR_NOT_SUPPORTED);
return FALSE;
}
hr = CoInitialize(NULL);
if (hr != S_OK && hr != S_FALSE) {
SetLastError((DWORD)((HRESULT_FACILITY(hr) == FACILITY_WIN32) ? HRESULT_CODE(hr) : hr));
return FALSE;
}
if (ppszDN)
*ppszDN = NULL;
//
// Get server name
//
if (dwRet = UNC2Server(pszUNCName, &pszServerName))
goto error;
if(!OpenPrinter(pszServerName, &hServer, NULL)) {
dwMajorVersion = 0;
} else {
dwRet = GetPrinterData( hServer,
SPLREG_MAJOR_VERSION,
&dwType,
(PBYTE) &dwMajorVersion,
sizeof dwMajorVersion,
&cbNeeded);
if (dwRet != ERROR_SUCCESS) {
//
// ignore errors and assume lowest version
//
dwMajorVersion = 0;
dwRet = ERROR_SUCCESS;
}
if (dwMajorVersion >= WIN2000_SPOOLER_VERSION) {
hr = MachineIsInMyForest(pszServerName);
if (FAILED(hr)) {
dwRet = HRESULT_CODE(hr);
goto error;
} else if(HRESULT_CODE(hr) == 1) {
//
// Machine is in my forest and is NT5+
//
dwRet = ERROR_INVALID_LEVEL;
goto error;
} else {
//
// Downgrade the version for NT5+ printers published in a non-DS domain
//
dwMajorVersion = WIN2000_SPOOLER_VERSION;
}
}
}
Defaults.pDatatype = NULL;
Defaults.pDevMode = NULL;
Defaults.DesiredAccess = PRINTER_ACCESS_USE;
if (!OpenPrinter((PWSTR) pszUNCName, &hPrinter, &Defaults)) {
dwRet = GetLastError();
goto error;
}
hr = GetPrinterInfo2(hPrinter, &pInfo2);
if (FAILED(hr)) {
dwRet = HRESULT_CODE(hr);
goto error;
}
if (dwRet = UNC2Printer(pInfo2->pPrinterName, &pszPrinterName))
goto error;
if( dwMajorVersion >= WIN2000_SPOOLER_VERSION){
if(dwRet = GetPrinterData( hServer,
SPLREG_DNS_MACHINE_NAME,
&dwType,
(PBYTE) szDNSMachineName,
(INTERNET_MAX_HOST_NAME_LENGTH + 1) * sizeof(WCHAR),
&cbNeeded) != ERROR_SUCCESS ) {
goto error;
}
if (FAILED(hr = StringCchPrintf( szFullUNCName,
COUNTOF(szFullUNCName),
L"\\\\%s\\%s",
szDNSMachineName,
pszPrinterName )))
{
dwRet = HRESULT_CODE(hr);
goto error;
}
dwLength = MAX_PATH + 1;
if (!DnsHostnameToComputerName(pszServerName,
szShortServerName,
&dwLength)) {
dwRet = GetLastError();
goto error;
}
pszFullUNCName = szFullUNCName;
pszFullServerName = szDNSMachineName;
pszShortServerName = szShortServerName+2;
} else {
pszFullUNCName = (PWSTR)pszUNCName;
pszFullServerName = pszServerName+2;
pszShortServerName = pszServerName+2;
}
//
// Verify PrintQueue doesn't already exist
//
if (dwAction != PUBLISHPRINTER_IGNORE_DUPLICATES) {
if(dwRet = PrintQueueExists(hwnd, hPrinter, pszFullUNCName, dwAction, (PWSTR) pszDN, (PWSTR *) ppszDN))
goto error;
}
if (dwRet = PublishDownlevelPrinter(hPrinter,
(PWSTR) pszDN,
(PWSTR) pszCN,
pszFullServerName,
pszShortServerName,
pszFullUNCName,
pszPrinterName,
dwMajorVersion,
ppszDN))
goto error;
error:
if (hPrinter != NULL)
ClosePrinter(hPrinter);
if (hServer != NULL)
ClosePrinter(hServer);
if (pszServerName)
FreeSplMem(pszServerName);
if (pszPrinterName)
FreeSplMem(pszPrinterName);
FreeSplMem(pInfo2);
if (dwRet != ERROR_SUCCESS) {
SetLastError(dwRet);
return FALSE;
}
CoUninitialize();
return TRUE;
}
DWORD
PublishDownlevelPrinter(
HANDLE hPrinter,
PWSTR pszDN,
PWSTR pszCN,
PWSTR pszServerName,
PWSTR pszShortServerName,
PWSTR pszUNCName,
PWSTR pszPrinterName,
DWORD dwVersion,
PWSTR *ppszObjectDN
)
{
HRESULT hr = S_OK;
DWORD dwRet = ERROR_SUCCESS;
IADs *pPrintQueue = NULL;
IADsContainer *pADsContainer = NULL;
IDispatch *pDispatch = NULL;
PWSTR pszCommonName = pszCN;
BSTR bstrADsPath = NULL;
PWSTR pszDNWithDC = NULL;
if (ppszObjectDN)
*ppszObjectDN = NULL;
//
// If pszCN is not supplied, generate default common name
//
if (!pszCommonName || !*pszCommonName) {
dwRet = GetCommonName(hPrinter, &pszCommonName);
if (dwRet != ERROR_SUCCESS) {
hr = dw2hr(dwRet);
BAIL_ON_FAILURE(hr);
}
}
//
// Stick DC in DN
//
if (!(pszDNWithDC = GetDNWithServer(pszDN))) {
pszDNWithDC = pszDN;
}
//
// Get container
//
hr = ADsGetObject(pszDNWithDC, IID_IADsContainer, (void **) &pADsContainer);
BAIL_ON_FAILURE(hr);
//
// Create printqueue
//
hr = pADsContainer->Create(SPLDS_PRINTER_CLASS, pszCommonName, &pDispatch);
BAIL_ON_FAILURE(hr);
hr = pDispatch->QueryInterface(IID_IADs, (void **) &pPrintQueue);
BAIL_ON_FAILURE(hr);
//
// Set properties
//
hr = SetProperties( hPrinter,
pszServerName,
pszShortServerName,
pszUNCName,
pszPrinterName,
dwVersion,
pPrintQueue);
BAIL_ON_FAILURE(hr);
//
// Get ADsPath to printQueue
//
if (ppszObjectDN) {
hr = pPrintQueue->get_ADsPath(&bstrADsPath);
BAIL_ON_FAILURE(hr);
if (!(*ppszObjectDN = AllocGlobalStr(bstrADsPath))) {
dwRet = GetLastError();
hr = dw2hr(dwRet);
BAIL_ON_FAILURE(hr);
}
}
error:
if (pszDNWithDC != pszDN)
FreeSplMem(pszDNWithDC);
if (bstrADsPath)
SysFreeString(bstrADsPath);
if (pszCommonName != pszCN)
FreeSplMem(pszCommonName);
if (pADsContainer)
pADsContainer->Release();
if (pDispatch)
pDispatch->Release();
if (pPrintQueue)
pPrintQueue->Release();
if (FAILED(hr) && ppszObjectDN && *ppszObjectDN)
FreeGlobalStr(*ppszObjectDN);
return hr2dw(hr);
}
HRESULT
SetProperties(
HANDLE hPrinter,
PWSTR pszServerName,
PWSTR pszShortServerName,
PWSTR pszUNCName,
PWSTR pszPrinterName,
DWORD dwVersion,
IADs *pPrintQueue
)
{
HRESULT hr;
hr = SetMandatoryProperties(pszServerName,
pszShortServerName,
pszUNCName,
pszPrinterName,
dwVersion,
pPrintQueue);
BAIL_ON_FAILURE(hr);
SetSpoolerProperties(hPrinter, pPrintQueue, dwVersion);
SetDriverProperties(hPrinter, pPrintQueue);
error:
return hr;
}
HRESULT
SetMandatoryProperties(
PWSTR pszServerName,
PWSTR pszShortServerName,
PWSTR pszUNCName,
PWSTR pszPrinterName,
DWORD dwVersion,
IADs *pPrintQueue
)
{
HRESULT hr;
//
// ServerName
//
hr = put_BSTR_Property(pPrintQueue, SPLDS_SERVER_NAME, pszServerName);
BAIL_ON_FAILURE(hr);
//
// ShortServerName
//
hr = put_BSTR_Property(pPrintQueue, SPLDS_SHORT_SERVER_NAME, pszShortServerName);
BAIL_ON_FAILURE(hr);
//
// UNC Name
//
hr = put_BSTR_Property(pPrintQueue, SPLDS_UNC_NAME, pszUNCName);
BAIL_ON_FAILURE(hr);
//
// PrinterName
//
hr = put_BSTR_Property(pPrintQueue, SPLDS_PRINTER_NAME, pszPrinterName);
BAIL_ON_FAILURE(hr);
//
// versionNumber
//
hr = put_DWORD_Property(pPrintQueue, SPLDS_VERSION_NUMBER, &dwVersion);
BAIL_ON_FAILURE(hr);
hr = pPrintQueue->SetInfo();
if (FAILED(hr))
pPrintQueue->GetInfo();
error:
return hr;
}
HRESULT
SetSpoolerProperties(
HANDLE hPrinter,
IADs *pPrintQueue,
DWORD dwVersion
)
{
HRESULT hr = E_FAIL;
PPRINTER_INFO_2 pInfo2 = NULL;
DWORD cbNeeded;
BYTE Byte;
PWSTR psz;
//
// Get PRINTER_INFO_2 properties
//
if (!GetPrinter(hPrinter, 2, (PBYTE) pInfo2, 0, &cbNeeded)) {
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
hr = dw2hr(GetLastError());
goto error;
}
if (!(pInfo2 = (PPRINTER_INFO_2) AllocSplMem(cbNeeded))) {
hr = dw2hr(GetLastError());
goto error;
}
if (!GetPrinter(hPrinter, 2, (PBYTE) pInfo2, cbNeeded, &cbNeeded)) {
hr = dw2hr(GetLastError());
goto error;
}
//
// Description
//
hr = PublishDsData( pPrintQueue,
SPLDS_DESCRIPTION,
REG_SZ,
(PBYTE) pInfo2->pComment);
//
// Driver-Name
//
hr = PublishDsData( pPrintQueue,
SPLDS_DRIVER_NAME,
REG_SZ,
(PBYTE) pInfo2->pDriverName);
//
// Location
//
hr = PublishDsData( pPrintQueue,
SPLDS_LOCATION,
REG_SZ,
(PBYTE) pInfo2->pLocation);
//
// portName (Port1,Port2,Port3)
//
if (pInfo2->pPortName) {
PWSTR pszPortName;
//
// copy comma delimited strings to Multi-sz format
//
pszPortName = DelimString2MultiSz(pInfo2->pPortName, L',');
if (pszPortName) {
hr = PublishDsData( pPrintQueue,
SPLDS_PORT_NAME,
REG_MULTI_SZ,
(PBYTE) pszPortName);
FreeSplMem(pszPortName);
}
}
//
// startTime
//
hr = PublishDsData( pPrintQueue,
SPLDS_PRINT_START_TIME,
REG_DWORD,
(PBYTE) &pInfo2->StartTime);
//
// endTime
//
hr = PublishDsData( pPrintQueue,
SPLDS_PRINT_END_TIME,
REG_DWORD,
(PBYTE) &pInfo2->UntilTime);
// keepPrintedJobs
Byte = pInfo2->Attributes & PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS ? 1 : 0;
hr = PublishDsData( pPrintQueue,
SPLDS_PRINT_KEEP_PRINTED_JOBS,
REG_BINARY,
(PBYTE) &Byte );
//
// printSeparatorFile
//
hr = PublishDsData( pPrintQueue,
SPLDS_PRINT_SEPARATOR_FILE,
REG_SZ,
(PBYTE) pInfo2->pSepFile);
//
// printShareName
//
hr = PublishDsData( pPrintQueue,
SPLDS_PRINT_SHARE_NAME,
REG_SZ,
(PBYTE) pInfo2->pShareName);
//
// printSpooling
//
if (pInfo2->Attributes & PRINTER_ATTRIBUTE_DIRECT) {
psz = L"PrintDirect";
} else if (pInfo2->Attributes & PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST) {
psz = L"PrintAfterSpooled";
} else {
psz = L"PrintWhileSpooling";
}
hr = PublishDsData( pPrintQueue,
SPLDS_PRINT_SPOOLING,
REG_SZ,
(PBYTE) psz);
//
// priority
//
hr = PublishDsData( pPrintQueue,
SPLDS_PRIORITY,
REG_DWORD,
(PBYTE) &pInfo2->Priority);
//
// Non-Info2 properties
// URL - downlevel machines don't support http printers, so don't publish useless url
//
if (dwVersion >= WIN2000_SPOOLER_VERSION) {
DWORD dwRet, dwType;
PWSTR pszUrl = NULL;
//
// Get the url from the print server
//
dwRet = GetPrinterDataEx( hPrinter,
SPLDS_SPOOLER_KEY,
SPLDS_URL,
&dwType,
(PBYTE) pszUrl,
0,
&cbNeeded);
if (dwRet == ERROR_MORE_DATA) {
if ((pszUrl = (PWSTR) AllocSplMem(cbNeeded))) {
dwRet = GetPrinterDataEx( hPrinter,
SPLDS_SPOOLER_KEY,
SPLDS_URL,
&dwType,
(PBYTE) pszUrl,
cbNeeded,
&cbNeeded);
if (dwRet == ERROR_SUCCESS && dwType == REG_SZ) {
hr = PublishDsData( pPrintQueue,
SPLDS_URL,
REG_SZ,
(PBYTE) pszUrl);
}
FreeSplMem(pszUrl);
}
}
}
}
error:
FreeSplMem(pInfo2);
return hr;
}
HRESULT
SetDriverProperties(
HANDLE hPrinter,
IADs *pPrintQueue
)
{
DWORD i, cbBytes, dwCount;
LPWSTR pStr;
DWORD dwResult;
LPWSTR pOutput = NULL, pTemp = NULL, pTemp1 = NULL;
DWORD cOutputBytes, cTempBytes;
POINTS point;
WCHAR pBuf[100];
BOOL bInSplSem = TRUE;
DWORD dwTemp, dwPrintRate, dwPrintRateUnit, dwPrintPPM;
HRESULT hr = S_OK;
PPRINTER_INFO_2 pInfo2 = NULL;
PWSTR pszUNCName;
//
// Get UNCName
//
hr = GetPrinterInfo2(hPrinter, &pInfo2);
BAIL_ON_FAILURE(hr);
if (!pInfo2) {
hr = dw2hr(GetLastError());
goto error;
}
pszUNCName = pInfo2->pPrinterName;
//
// DeviceCapability properties
//
pOutput = (PWSTR) AllocSplMem(cOutputBytes = 200);
if (!pOutput) {
hr = dw2hr(GetLastError());
goto error;
}
pTemp = (PWSTR) AllocSplMem(cTempBytes = 200);
if (!pTemp) {
hr = dw2hr(GetLastError());
goto error;
}
//
// printBinNames
//
DevCapMultiSz( pszUNCName,
pPrintQueue,
DC_BINNAMES,
24,
SPLDS_PRINT_BIN_NAMES);
//
// printCollate (awaiting DC_COLLATE)
//
dwResult = DeviceCapabilities( pszUNCName,
NULL,
DC_COLLATE,
NULL,
NULL);
if (dwResult != GDI_ERROR) {
hr = PublishDsData( pPrintQueue,
SPLDS_PRINT_COLLATE,
REG_BINARY,
(PBYTE) &dwResult);
}
//
// printColor
//
dwResult = DeviceCapabilities( pszUNCName,
NULL,
DC_COLORDEVICE,
NULL,
NULL);
if (dwResult == GDI_ERROR) {
//
// Try alternative method
//
dwResult = ThisIsAColorPrinter(pszUNCName);
}
hr = PublishDsData( pPrintQueue,
SPLDS_PRINT_COLOR,
REG_BINARY,
(PBYTE) &dwResult);
//
// printDuplexSupported
//
dwResult = DeviceCapabilities( pszUNCName,
NULL,
DC_DUPLEX,
NULL,
NULL);
if (dwResult != GDI_ERROR) {
hr = PublishDsData( pPrintQueue,
SPLDS_PRINT_DUPLEX_SUPPORTED,
REG_BINARY,
(PBYTE) &dwResult);
}
//
// printStaplingSupported
//
dwResult = DeviceCapabilities( pszUNCName,
NULL,
DC_STAPLE,
NULL,
NULL);
if (dwResult != GDI_ERROR) {
hr = PublishDsData( pPrintQueue,
SPLDS_PRINT_STAPLING_SUPPORTED,
REG_BINARY,
(PBYTE) &dwResult);
}
//
// printMaxXExtent & printMaxYExtent
//
dwResult = DeviceCapabilities( pszUNCName,
NULL,
DC_MAXEXTENT,
NULL,
NULL);
if (dwResult != GDI_ERROR) {
*((DWORD *) &point) = dwResult;
dwTemp = (DWORD) point.x;
hr = PublishDsData( pPrintQueue,
SPLDS_PRINT_MAX_X_EXTENT,
REG_DWORD,
(PBYTE) &dwTemp);
dwTemp = (DWORD) point.y;
hr = PublishDsData( pPrintQueue,
SPLDS_PRINT_MAX_Y_EXTENT,
REG_DWORD,
(PBYTE) &dwTemp);
}
//
// printMinXExtent & printMinYExtent
//
dwResult = DeviceCapabilities( pszUNCName,
NULL,
DC_MINEXTENT,
NULL,
NULL);
if (dwResult != GDI_ERROR) {
*((DWORD *) &point) = dwResult;
dwTemp = (DWORD) point.x;
hr = PublishDsData( pPrintQueue,
SPLDS_PRINT_MIN_X_EXTENT,
REG_DWORD,
(PBYTE) &dwTemp);
dwTemp = (DWORD) point.y;
hr = PublishDsData( pPrintQueue,
SPLDS_PRINT_MIN_Y_EXTENT,
REG_DWORD,
(PBYTE) &dwTemp);
}
//
// printMediaSupported
//
DevCapMultiSz( pszUNCName,
pPrintQueue,
DC_PAPERNAMES,
64,
SPLDS_PRINT_MEDIA_SUPPORTED);
//
// printMediaReady
//
DevCapMultiSz( pszUNCName,
pPrintQueue,
DC_MEDIAREADY,
64,
SPLDS_PRINT_MEDIA_READY);
//
// printNumberUp
//
dwResult = DeviceCapabilities( pszUNCName,
NULL,
DC_NUP,
NULL,
NULL);
if (dwResult != GDI_ERROR) {
//
// DS NUp is boolean
//
dwResult = !!dwResult;
hr = PublishDsData( pPrintQueue,
SPLDS_PRINT_DUPLEX_SUPPORTED,
REG_DWORD,
(PBYTE) &dwResult);
}
//
// printMemory
//
dwResult = DeviceCapabilities( pszUNCName,
NULL,
DC_PRINTERMEM,
NULL,
NULL);
if (dwResult != GDI_ERROR) {
hr = PublishDsData( pPrintQueue,
SPLDS_PRINT_MEMORY,
REG_DWORD,
(PBYTE) &dwResult);
}
//
// printOrientationsSupported
//
dwResult = DeviceCapabilities( pszUNCName,
NULL,
DC_ORIENTATION,
NULL,
NULL);
if (dwResult != GDI_ERROR) {
StringCchCopy(pStr = pBuf, COUNTOF(pBuf), L"PORTRAIT");
if (dwResult == 90 || dwResult == 270) {
ULONG cchBuf = wcslen(pBuf) + 1;
StringCchCopy(pStr = pBuf + cchBuf, COUNTOF(pBuf) - cchBuf, L"LANDSCAPE");
}
else {
pStr = pBuf;
}
pStr += wcslen(pStr) + 1;
*pStr++ = L'\0';
hr = PublishDsData( pPrintQueue,
SPLDS_PRINT_ORIENTATIONS_SUPPORTED,
REG_MULTI_SZ,
(PBYTE) pBuf);
}
//
// printMaxResolutionSupported
//
dwResult = DeviceCapabilities( pszUNCName,
NULL,
DC_ENUMRESOLUTIONS,
NULL,
NULL);
if (dwResult != GDI_ERROR) {
if (cOutputBytes < dwResult*2*sizeof(DWORD)) {
if(!(pTemp1 = (PWSTR) ReallocSplMem(pOutput, 0, cOutputBytes = dwResult*2*sizeof(DWORD))))
goto error;
pOutput = pTemp1;
}
dwResult = DeviceCapabilities( pszUNCName,
NULL,
DC_ENUMRESOLUTIONS,
pOutput,
NULL);
if (dwResult == GDI_ERROR)
goto error;
//
// Find the maximum resolution: we have dwResult*2 resolutions to check
//
for(i = dwTemp = 0 ; i < dwResult*2 ; ++i) {
if (((DWORD *) pOutput)[i] > dwTemp)
dwTemp = ((DWORD *) pOutput)[i];
}
hr = PublishDsData( pPrintQueue,
SPLDS_PRINT_MAX_RESOLUTION_SUPPORTED,
REG_DWORD,
(PBYTE) &dwTemp);
}
//
// printLanguage
//
DevCapMultiSz( pszUNCName,
pPrintQueue,
DC_PERSONALITY,
32,
SPLDS_PRINT_LANGUAGE);
//
// printRate
// NOTE: If PrintRate is 0, no value is published
//
dwResult = DeviceCapabilities( pszUNCName,
NULL,
DC_PRINTRATE,
NULL,
NULL);
dwPrintRate = dwResult ? dwResult : GDI_ERROR;
if (dwPrintRate != GDI_ERROR) {
hr = PublishDsData( pPrintQueue,
SPLDS_PRINT_RATE,
REG_DWORD,
(PBYTE) &dwPrintRate);
}
//
// printRateUnit
//
dwResult = DeviceCapabilities( pszUNCName,
NULL,
DC_PRINTRATEUNIT,
NULL,
NULL);
dwPrintRateUnit = dwResult;
if (dwPrintRateUnit != GDI_ERROR) {
switch (dwPrintRateUnit) {
case PRINTRATEUNIT_PPM:
pStr = L"PagesPerMinute";
break;
case PRINTRATEUNIT_CPS:
pStr = L"CharactersPerSecond";
break;
case PRINTRATEUNIT_LPM:
pStr = L"LinesPerMinute";
break;
case PRINTRATEUNIT_IPM:
pStr = L"InchesPerMinute";
break;
default:
pStr = L"";
break;
}
hr = PublishDsData( pPrintQueue,
SPLDS_PRINT_RATE_UNIT,
REG_SZ,
(PBYTE) pStr);
}
//
// printPagesPerMinute
// DevCap returns 0 if there is no entry in GPD
//
dwResult = DeviceCapabilities( pszUNCName,
NULL,
DC_PRINTRATEPPM,
NULL,
NULL);
if (dwResult == GDI_ERROR)
dwResult = 0;
dwPrintPPM = dwResult;
//
// If dwPrintPPM == 0, then calculate PPM from PrintRate
//
if (dwPrintPPM == 0) {
if (dwPrintRate == GDI_ERROR) {
dwPrintPPM = GDI_ERROR;
} else {
switch (dwPrintRateUnit) {
case PRINTRATEUNIT_PPM:
dwPrintPPM = dwPrintRate;
break;
case PRINTRATEUNIT_CPS:
case PRINTRATEUNIT_LPM:
dwPrintPPM = dwPrintRate/PPM_FACTOR;
if (dwPrintPPM == 0) {
//
// min PPM is 1
//
dwPrintPPM = 1;
}
break;
default:
dwPrintPPM = GDI_ERROR;
break;
}
}
}
if (dwPrintPPM != GDI_ERROR) {
hr = PublishDsData( pPrintQueue,
SPLDS_PRINT_PAGES_PER_MINUTE,
REG_DWORD,
(PBYTE) &dwPrintPPM);
}
//
// printDriverVersion
//
dwResult = DeviceCapabilities( pszUNCName,
NULL,
DC_VERSION,
NULL,
NULL);
if (dwResult != GDI_ERROR) {
hr = PublishDsData( pPrintQueue,
SPLDS_DRIVER_VERSION,
REG_DWORD,
(PBYTE) &dwResult);
}
error:
FreeSplMem(pInfo2);
if (pOutput)
FreeSplMem(pOutput);
if (pTemp)
FreeSplMem(pTemp);
return hr;
}
HRESULT
PublishDsData(
IADs *pADs,
PWSTR pValue,
DWORD dwType,
PBYTE pData
)
{
HRESULT hr;
BOOL bCreated = FALSE;
switch (dwType) {
case REG_SZ:
hr = put_BSTR_Property(pADs, pValue, (LPWSTR) pData);
break;
case REG_MULTI_SZ:
hr = put_MULTISZ_Property(pADs, pValue, (LPWSTR) pData);
break;
case REG_DWORD:
hr = put_DWORD_Property(pADs, pValue, (DWORD *) pData);
break;
case REG_BINARY:
hr = put_BOOL_Property(pADs, pValue, (BOOL *) pData);
break;
default:
hr = dw2hr(ERROR_INVALID_PARAMETER);
}
BAIL_ON_FAILURE(hr);
hr = pADs->SetInfo();
if (FAILED(hr))
pADs->GetInfo();
error:
return hr;
}