mirror of https://github.com/tongzx/nt5src
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.
226 lines
5.7 KiB
226 lines
5.7 KiB
/*****************************************************************************\
|
|
* 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;
|
|
}
|
|
|