windows-nt/Source/XPSP1/NT/printscan/print/spooler/oleprn/util.cpp

227 lines
5.7 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*****************************************************************************\
* MODULE: util.cpp
*
* PURPOSE: Tools for OlePrn project
*
* Copyright (C) 1997-1998 Microsoft Corporation
*
* History:
*
* 08/16/97 paulmo Created
* 09/12/97 weihaic Added more functions
* 10/28/97 keithst Added SetScriptingError
* 11/06/97 keithst Removed Win2ComErr
*
\*****************************************************************************/
#include "stdafx.h"
//---------------------------------------------
// Put an ANSI string into a SAFEARRAY
//
//
// Convert the string into UNICODE
// Make a BSTR out of it
// Add it to the array
//
HRESULT PutString(SAFEARRAY *psa, long *ix, LPSTR sz)
{
LPWSTR lpWstr;
VARIANT var;
HRESULT hr;
VariantInit(&var);
var.vt = VT_BSTR;
if (sz == NULL)
lpWstr = MakeWide("");
else
lpWstr = MakeWide(sz);
if (lpWstr == NULL) return E_OUTOFMEMORY;
var.bstrVal = SysAllocString(lpWstr);
LocalFree(lpWstr);
if (var.bstrVal == NULL)
return E_OUTOFMEMORY;
hr = SafeArrayPutElement(psa, ix, &var);
VariantClear(&var);
return hr;
}
// ---------------------------------------------
// Convert an ANSI string to UNICODE
//
// Note - you must LocalFree the returned string
//
LPWSTR MakeWide(LPSTR psz)
{
LPWSTR buff;
int i;
i = MultiByteToWideChar(CP_ACP, 0, psz, -1, NULL, 0);
buff = (LPWSTR)LocalAlloc(LPTR, i * 2);
if (buff == NULL)
return NULL;
i = MultiByteToWideChar(CP_ACP, 0, psz, -1, buff, i);
return buff;
}
//-------------------------------------------------
// Convert a UNICODE string to ANSI
//
// Note - you must LocalFree the returned string
//
LPSTR MakeNarrow(LPWSTR str)
{
LPSTR buff;
int i;
i = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0, NULL, NULL);
buff = (LPSTR )LocalAlloc(LPTR, i);
if (buff == NULL)
return NULL;
i = WideCharToMultiByte(CP_ACP, 0, str, -1, buff, i, NULL, NULL);
return buff;
}
//-------------------------------------------------
// SetScriptingError
// Takes a Win32 error code and sets the associated string as
// the scripting language error description
//
// Parameters:
// CLSID *pclsid: pointer to Class ID (CLSID) for the class which
// generated the error; passed to AtlReportError
//
// IID *piid: pointer to interface ID (IID) for the interface
// which generated the error; passed to AtlReportError
//
// DWORD dwError: the error code retrieved from GetLastError by
// the caller of this function
//
// Return Value:
// This function uses the HRESULT_FROM_WIN32 macro, which translates
// the Win32 dwError code to a COM error code. This COM error code
// should be returned out as the return value of the failed method.
//
HRESULT SetScriptingError(const CLSID& rclsid, const IID& riid, DWORD dwError)
{
LPTSTR lpMsgBuf = NULL;
DWORD dwRet = 0;
dwRet = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dwError,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0,
NULL);
if (dwRet == 0 || !lpMsgBuf)
{
//
// If FormatMessage fails, it returns 0, but since we can not call
// GetLastError again, we return OUTOFMEMORY instead.
//
return E_OUTOFMEMORY;
}
AtlReportError(rclsid, lpMsgBuf, riid, HRESULT_FROM_WIN32(dwError));
LocalFree(lpMsgBuf);
return (HRESULT_FROM_WIN32(dwError));
}
HANDLE
RevertToPrinterSelf(
VOID)
{
HANDLE NewToken, OldToken;
NTSTATUS Status;
NewToken = NULL;
Status = NtOpenThreadToken(
NtCurrentThread(),
TOKEN_IMPERSONATE,
TRUE,
&OldToken
);
if ( !NT_SUCCESS(Status) ) {
SetLastError(Status);
return FALSE;
}
Status = NtSetInformationThread(
NtCurrentThread(),
ThreadImpersonationToken,
(PVOID)&NewToken,
(ULONG)sizeof(HANDLE)
);
if ( !NT_SUCCESS(Status) ) {
SetLastError(Status);
return FALSE;
}
return OldToken;
}
BOOL
ImpersonatePrinterClient(
HANDLE hToken)
{
NTSTATUS Status;
Status = NtSetInformationThread(
NtCurrentThread(),
ThreadImpersonationToken,
(PVOID)&hToken,
(ULONG)sizeof(HANDLE)
);
if ( !NT_SUCCESS(Status) ) {
SetLastError(Status);
return FALSE;
}
NtClose(hToken);
return TRUE;
}
DWORD MyDeviceCapabilities(
LPCTSTR pDevice, // pointer to a printer-name string
LPCTSTR pPort, // pointer to a port-name string
WORD fwCapability, // device capability to query
LPTSTR pOutput, // pointer to the output
CONST DEVMODE *pDevMode
// pointer to structure with device data
)
{
DWORD dwRet = DWERROR;
HANDLE hToken = NULL;
dwRet = DeviceCapabilities(pDevice, pPort, fwCapability, pOutput, pDevMode);
if (dwRet == DWERROR && GetLastError () == ERROR_ACCESS_DENIED) {
// In a cluster machine, we need to get the local admin previlige to get
// the device capabilities.
if (hToken = RevertToPrinterSelf()) {
dwRet = DeviceCapabilities(pDevice, pPort, fwCapability, pOutput, pDevMode);
ImpersonatePrinterClient(hToken);
}
}
return dwRet;
}