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.
 
 
 
 
 
 

873 lines
19 KiB

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
FaxCommon.cpp
Abstract:
Implementation of common Interfaces and Functions.
Author:
Iv Garber (IvG) May, 2000
Revision History:
--*/
#include "StdAfx.h"
#include "resource.h"
#include "FaxComEx.h"
#include "FaxCommon.h"
#include "faxutil.h"
#include "FaxServer.h"
//
//============= GET BSTR FROM DWORDLONG ==========================================
//
HRESULT
GetBstrFromDwordlong(
/*[in]*/ DWORDLONG dwlFrom,
/*[out]*/ BSTR *pbstrTo
)
/*++
Routine name : GetBstrFromDwordlong
Routine description:
Convert DWORDLONG into BSTR. Used in Message, and in Events in Server.
Author:
Iv Garber (IvG), Jul, 2000
Arguments:
dwlFrom [in] - DWORDLONG value to convert to BSTR
pbstrTo [out] - ptr to the BSTR to return
Return Value:
Standard HRESULT code
--*/
{
HRESULT hr = S_OK;
DBG_ENTER(_T("GetBstrFromDwordlong"), hr, _T("DWORDLONG=%ld"), dwlFrom);
//
// Convert DWORDLONG into buffer of TCHARs
//
TCHAR tcBuffer[25];
::_i64tot(dwlFrom, tcBuffer, 16);
//
// Create BSTR from that buffer
//
BSTR bstrTemp;
bstrTemp = ::SysAllocString(tcBuffer);
if (!bstrTemp)
{
//
// Not enough memory
//
hr = E_OUTOFMEMORY;
CALL_FAIL(MEM_ERR, _T("SysAllocString()"), hr);
return hr;
}
//
// Return created BSTR
//
*pbstrTo = bstrTemp;
return hr;
}
//
//===================== GET EXTENSION PROPERTY ===============================================
//
HRESULT
GetExtensionProperty(
/*[in]*/ IFaxServerInner *pServer,
/*[in]*/ long lDeviceId,
/*[in]*/ BSTR bstrGUID,
/*[out, retval]*/ VARIANT *pvProperty
)
/*++
Routine name : GetExtensionProperty
Routine description:
Retrieves the Extension Data by given GUID from the Server.
Used by FaxServer and FaxDevice Classes.
Author:
Iv Garber (IvG), Jun, 2000
Arguments:
pServer [in] -- Ptr to the Fax Server Object
lDeviceId [in] -- Device Id with which the Extension Property is assosiated
bstrGUID [in] -- Extension's Data GUID
pvProperty [out] -- Variant with the Blob to Return
Return Value:
Standard HRESULT code
--*/
{
HRESULT hr = S_OK;
DBG_ENTER(_T("GetExtensionProperty"), hr, _T("GUID=%s"), bstrGUID);
//
// Check the pointer we have got
//
if (!pvProperty)
{
hr = E_POINTER;
CALL_FAIL(GENERAL_ERR, _T("!pvProperty"), hr);
return hr;
}
//
// Get Fax Server Handle
//
HANDLE faxHandle;
hr = pServer->GetHandle(&faxHandle);
ATLASSERT(SUCCEEDED(hr));
if (faxHandle == NULL)
{
//
// Fax Server is not connected
//
hr = Fax_HRESULT_FROM_WIN32(ERROR_NOT_CONNECTED);
CALL_FAIL(GENERAL_ERR, _T("faxHandle == NULL"), hr);
return hr;
}
//
// Ask Server to Get the Extension Property we want
//
CFaxPtrBase<void> pData;
DWORD dwSize = 0;
if (!FaxGetExtensionData(faxHandle, lDeviceId, bstrGUID, &pData, &dwSize))
{
hr = Fax_HRESULT_FROM_WIN32(GetLastError());
CALL_FAIL(GENERAL_ERR, _T("FaxGetExtensionData(faxHandle, m_lID, bstrGUID, &pData, &dwSize)"), hr);
return hr;
}
//
// Create SafeArray to Return to User
//
hr = Binary2VarByteSA(((BYTE *)(pData.p)), pvProperty, dwSize);
SecureZeroMemory(pData, dwSize);
return hr;
};
//
//===================== SET EXTENSION PROPERTY ===============================================
// TODO: should work with empty vProperty
//
HRESULT
SetExtensionProperty(
/*[in]*/ IFaxServerInner *pServer,
/*[in]*/ long lDeviceId,
/*[in]*/ BSTR bstrGUID,
/*[in]*/ VARIANT vProperty
)
/*++
Routine name : SetExtensionProperty
Routine description:
Used by FaxDevice and FaxServer Classes, to Set the Extension Data by given GUID on the Server.
Author:
Iv Garber (IvG), Jun, 2000
Arguments:
pServer [in] -- Ptr to the Fax Server Object
lDeviceId [in] -- Device Id with which the Extension Property is assosiated
bstrGUID [in] -- Extension's Data GUID
vProperty [in] -- Variant with the Blob to Set
Return Value:
Standard HRESULT code
--*/
{
HRESULT hr = S_OK;
DBG_ENTER(_T("SetExtensionProperty"), hr, _T("GUID=%s"), bstrGUID);
//
// Get Fax Server Handle
//
HANDLE faxHandle;
hr = pServer->GetHandle(&faxHandle);
ATLASSERT(SUCCEEDED(hr));
if (faxHandle == NULL)
{
//
// Fax Server is not connected
//
hr = Fax_HRESULT_FROM_WIN32(ERROR_NOT_CONNECTED);
CALL_FAIL(GENERAL_ERR, _T("faxHandle == NULL"), hr);
return hr;
}
//
// check that Variant contains SafeArray
//
if (vProperty.vt != (VT_ARRAY | VT_UI1))
{
hr = E_INVALIDARG;
CALL_FAIL(GENERAL_ERR, _T("(vProperty.vt != VT_ARRAY | VT_BYTE)"), hr);
return hr;
}
//
// Create Binary from the SafeArray we got
//
CFaxPtrLocal<void> pData;
hr = VarByteSA2Binary(vProperty, (BYTE **)&pData);
if (FAILED(hr))
{
return hr;
}
//
// Ask Server to Set the Extension Property we want
//
DWORD dwLength = vProperty.parray->rgsabound[0].cElements;
if (!FaxSetExtensionData(faxHandle, lDeviceId, bstrGUID, pData, dwLength))
{
hr = Fax_HRESULT_FROM_WIN32(GetLastError());
CALL_FAIL(GENERAL_ERR, _T("FaxSetExtensionData(faxHandle, m_lID, bstrGUID, &pData, dwLength)"), hr);
}
SecureZeroMemory(pData, dwLength);
return hr;
};
//
//========================= GET LONG ========================================
//
HRESULT GetLong(
long *plTo,
long lFrom
)
/*++
Routine name : GetLong
Routine description:
Check that plTo is valid
Copy the given lFrom into plTo
Author:
Iv Garber (IvG), Jun, 2000
Arguments:
plTo [out] - Ptr to put the value
lFrom [in] - value to put
Return Value:
Standard HRESULT code
--*/
{
HRESULT hr = S_OK;
DBG_ENTER (TEXT("GetLong"), hr, _T("lFrom=%d"), lFrom);
//
// Check that we have got good Ptr
//
if (::IsBadWritePtr(plTo, sizeof(long)))
{
hr = E_POINTER;
CALL_FAIL(GENERAL_ERR, _T("::IsBadWritePtr(plTo, sizeof(long))"), hr);
return hr;
}
*plTo = lFrom;
return hr;
}
//
//========================= GET VARIANT BOOL ========================================
//
HRESULT GetVariantBool(
VARIANT_BOOL *pbTo,
VARIANT_BOOL bFrom
)
/*++
Routine name : GetVariantBool
Routine description:
Check that pbTo is valid
Copy the given bFrom into pbTo
Author:
Iv Garber (IvG), Jun, 2000
Arguments:
pbTo [out] - Ptr to put the value
bFrom [in] - value to put
Return Value:
Standard HRESULT code
--*/
{
HRESULT hr = S_OK;
DBG_ENTER (TEXT("GetVariantBool"), hr, _T("bFrom=%d"), bFrom);
//
// Check that we have got good Ptr
//
if (::IsBadWritePtr(pbTo, sizeof(VARIANT_BOOL)))
{
hr = E_POINTER;
CALL_FAIL(GENERAL_ERR, _T("::IsBadWritePtr(pbTo, sizeof(VARIANT_BOOL))"), hr);
return hr;
}
*pbTo = bFrom;
return hr;
}
//
//========================= GET BSTR ========================================
//
HRESULT GetBstr(
BSTR *pbstrTo,
BSTR bstrFrom
)
/*++
Routine name : GetBstr
Routine description:
Check that pbstTo is valid
SysAllocString for bstrFrom
Copy the newly created string into pbstrTo
Author:
Iv Garber (IvG), Jun, 2000
Arguments:
pbstrTo [out] - Ptr to put the value
bstrFrom [in] - Ptr to the string to return
Return Value:
Standard HRESULT code
--*/
{
HRESULT hr = S_OK;
DBG_ENTER (TEXT("GetBstr"), hr, _T("String=%s"), bstrFrom);
//
// Check that we have got good Ptr
//
if (::IsBadWritePtr(pbstrTo, sizeof(BSTR)))
{
hr = E_POINTER;
CALL_FAIL(GENERAL_ERR, _T("::IsBadWritePtr(pbstrTo, sizeof(BSTR))"), hr);
return hr;
}
//
// First copy the string locally
//
BSTR bstrTemp;
bstrTemp = ::SysAllocString(bstrFrom);
if (!bstrTemp && bstrFrom)
{
hr = E_OUTOFMEMORY;
CALL_FAIL(MEM_ERR, _T("::SysAllocString(bstrFrom)"), hr);
return hr;
}
*pbstrTo = bstrTemp;
return hr;
}
//
//======= CONVERNT BYTE BLOB INTO VARIANT CONTAINING BYTE SAFE ARRAY ============
//
HRESULT Binary2VarByteSA(
BYTE *pbDataFrom,
VARIANT *pvarTo,
DWORD dwLength
)
{
HRESULT hr = S_OK;
DBG_ENTER(_T("Binary2VarByteSA"), hr, _T("Size=%d"), dwLength);
//
// Allocate the safe array : vector of Unsigned Chars
//
SAFEARRAY *pSafeArray;
pSafeArray = ::SafeArrayCreateVector(VT_UI1, 0, dwLength);
if (pSafeArray == NULL)
{
//
// Not Enough Memory
//
hr = E_OUTOFMEMORY;
CALL_FAIL(MEM_ERR, _T("::SafeArrayCreateVector(VT_UI1, 0, dwLength)"), hr);
return hr;
}
//
// get Access to the elements of the Safe Array
//
BYTE *pbElement;
hr = ::SafeArrayAccessData(pSafeArray, (void **) &pbElement);
if (FAILED(hr))
{
//
// Failed to access safearray
//
hr = E_FAIL;
CALL_FAIL(GENERAL_ERR, _T("::SafeArrayAccessData(pSafeArray, &pbElement)"), hr);
SafeArrayDestroy(pSafeArray);
return hr;
}
//
// Fill the Safe Array with the bytes from pbDataFrom
//
memcpy(pbElement, pbDataFrom, dwLength);
hr = ::SafeArrayUnaccessData(pSafeArray);
if (FAILED(hr))
{
CALL_FAIL(GENERAL_ERR, _T("::SafeArrayUnaccessData(pSafeArray)"), hr);
}
//
// Return the Safe Array inside the VARIANT we got
//
VariantInit(pvarTo);
pvarTo->vt = VT_UI1 | VT_ARRAY;
pvarTo->parray = pSafeArray;
return hr;
}
//
//======= CONVERNT VARIANT CONTAINING BYTE SAFE ARRAY INTO POINTER TO BYTES BLOB =========
//
HRESULT
VarByteSA2Binary(
VARIANT varFrom,
BYTE **ppbData
)
{
HRESULT hr = S_OK;
DBG_ENTER(_T("VarByteSA2Binary"), hr);
//
// Check that Variant has right type
//
if ((varFrom.vt != VT_UI1) && (varFrom.vt != (VT_UI1 | VT_ARRAY)))
{
hr = E_INVALIDARG;
CALL_FAIL(GENERAL_ERR, _T("pVarFrom->vt not VT_UI1 or VT_UI1 | VT_ARRAY"), hr);
return hr;
}
ULONG ulNum = 0;
SAFEARRAY *pSafeArray = NULL;
//
// Is there is only one member ?
//
if (varFrom.vt == VT_UI1)
{
ulNum = 1;
}
else
{
//
// Get safe array values
//
pSafeArray = varFrom.parray;
if (!pSafeArray)
{
hr = E_INVALIDARG;
CALL_FAIL(GENERAL_ERR, _T("!pSafeArray ( = varFrom.parray )"), hr);
return hr;
}
if (SafeArrayGetDim(pSafeArray) != 1)
{
hr = E_INVALIDARG;
CALL_FAIL(GENERAL_ERR, _T("SafeArrayGetDim(pSafeArray) != 1"), hr);
return hr;
}
if (pSafeArray->rgsabound[0].lLbound != 0)
{
hr = E_INVALIDARG;
CALL_FAIL(GENERAL_ERR, _T("pSafeArray->rgsabound[0].lLbound != 0"), hr);
return hr;
}
ulNum = pSafeArray->rgsabound[0].cElements;
}
//
// Allocate memory for the safearray
//
*ppbData = (BYTE *)MemAlloc(ulNum);
if (!*ppbData)
{
//
// Not enough memory
//
hr = E_OUTOFMEMORY;
CALL_FAIL(MEM_ERR, _T("MemAlloc(sizeof(ulNum)"), hr);
return hr;
}
ZeroMemory(*ppbData, ulNum);
//
// Fill pbData with the values from the pSafeArray
//
if (!pSafeArray)
{
*ppbData[0] = varFrom.bVal;
}
else
{
//
// Get Access to the Safe Array
//
BYTE *pbElement;
hr = ::SafeArrayAccessData(pSafeArray, (void **) &pbElement);
if (FAILED(hr))
{
hr = E_FAIL;
MemFree (*ppbData);
CALL_FAIL(GENERAL_ERR, _T("::SafeArrayAccessData(pSafeArray, &pbElement)"), hr);
return hr;
}
//
// Fill pbData with the values from the Safe Array
//
memcpy(*ppbData, pbElement, ulNum);
hr = ::SafeArrayUnaccessData(pSafeArray);
if (FAILED(hr))
{
CALL_FAIL(GENERAL_ERR, _T("::SafeArrayUnaccessData(pSafeArray)"), hr);
}
}
return hr;
} // VarByteSA2Binary
//
//======================= INIT ============================================
//
STDMETHODIMP
CFaxInitInner::Init(
/*[in]*/ IFaxServerInner* pServer
)
/*++
Routine name : CFaxInitInner::Init
Routine description:
Store Ptr to the Fax Server. Used in most of the objects
Author:
Iv Garber (IvG), Apr, 2000
Arguments:
pServer [in] - Ptr to the Fax Server
Return Value:
Standard HRESULT code
--*/
{
HRESULT hr = S_OK;
DBG_ENTER (TEXT("CFaxInitInner::Init"), hr);
m_pIFaxServerInner = pServer;
return hr;
}
//
//======================= GET FAX HANDLE ============================================
//
STDMETHODIMP
CFaxInitInner::GetFaxHandle(
/*[in]*/ HANDLE* pFaxHandle
)
/*++
Routine name : CFaxInitInner::GetFaxHandle
Routine description:
Ask m_pIServerInner for handle to the fax server and handle error
Author:
Iv Garber (IvG), May, 2000
Arguments:
pFaxHandle [out] - Ptr to the returned Fax Handle
Return Value:
Standard HRESULT code
--*/
{
HRESULT hr = S_OK;
DBG_ENTER (TEXT("CFaxInitInner::GetFaxHandle"), hr);
//
// Get Fax Server Handle
//
hr = m_pIFaxServerInner->GetHandle(pFaxHandle);
ATLASSERT(SUCCEEDED(hr));
if (*pFaxHandle == NULL)
{
//
// Fax Server is not connected
//
hr = Fax_HRESULT_FROM_WIN32(ERROR_NOT_CONNECTED);
CALL_FAIL(GENERAL_ERR, _T("hFaxHandle==NULL"), hr);
return hr;
}
return hr;
}
//
//======================= GET ERROR MESSAGE ID ================================
//
LPCTSTR
GetErrorMsgId(
HRESULT hRes
)
/*++
Routine name : GetErrorMsgId
Routine description:
Return IDS of the Message according to the given result of the RPC call
and not only RPC
Author:
Iv Garber (IvG), May, 2000
Arguments:
hRes [in] - the RPC call result
Return Value:
UINT IDS of the Message to show to the User
--*/
{
switch(hRes)
{
case E_POINTER:
case HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER):
return IDS_ERROR_INVALID_ARGUMENT;
case E_OUTOFMEMORY:
case HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY):
return IDS_ERROR_OUTOFMEMORY;
case HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED):
return IDS_ERROR_ACCESSDENIED;
case E_HANDLE:
case HRESULT_FROM_WIN32(ERROR_NOT_CONNECTED):
return IDS_ERROR_SERVER_NOT_CONNECTED;
case HRESULT_FROM_WIN32(ERROR_UNSUPPORTED_TYPE):
return IDS_ERROR_UNSUPPORTED_RECEIPT_TYPE;
case HRESULT_FROM_WIN32(RPC_S_INVALID_BINDING):
case HRESULT_FROM_WIN32(EPT_S_CANT_PERFORM_OP):
case HRESULT_FROM_WIN32(RPC_S_ADDRESS_ERROR):
case HRESULT_FROM_WIN32(RPC_S_CALL_CANCELLED):
case HRESULT_FROM_WIN32(RPC_S_CALL_FAILED):
case HRESULT_FROM_WIN32(RPC_S_CALL_FAILED_DNE):
case HRESULT_FROM_WIN32(RPC_S_COMM_FAILURE):
case HRESULT_FROM_WIN32(RPC_S_NO_BINDINGS):
case HRESULT_FROM_WIN32(RPC_S_SERVER_TOO_BUSY):
case HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE):
return IDS_ERROR_CONNECTION_FAILED;
case HRESULT_FROM_WIN32(ERROR_WRITE_PROTECT):
return IDS_ERROR_QUEUE_BLOCKED;
case FAX_E_FILE_ACCESS_DENIED:
return IDS_ERROR_FILE_ACCESS_DENIED;
case FAX_E_SRV_OUTOFMEMORY:
return IDS_ERROR_SRV_OUTOFMEMORY;
case FAX_E_GROUP_NOT_FOUND:
return IDS_ERROR_GROUP_NOT_FOUND;
case FAX_E_BAD_GROUP_CONFIGURATION:
return IDS_ERROR_BAD_GROUP_CONFIGURATION;
case FAX_E_GROUP_IN_USE:
return IDS_ERROR_GROUP_IN_USE;
case FAX_E_RULE_NOT_FOUND:
return IDS_ERROR_RULE_NOT_FOUND;
case FAX_E_NOT_NTFS:
return IDS_ERROR_NOT_NTFS;
case FAX_E_DIRECTORY_IN_USE:
return IDS_ERROR_DIRECTORY_IN_USE;
case FAX_E_MESSAGE_NOT_FOUND:
return IDS_ERROR_MESSAGE_NOT_FOUND;
case FAX_E_DEVICE_NUM_LIMIT_EXCEEDED:
return IDS_ERROR_DEVICE_NUM_LIMIT_EXCEEDED;
case FAX_E_NOT_SUPPORTED_ON_THIS_SKU:
return IDS_ERROR_NOT_SUPPORTED_ON_THIS_SKU;
case FAX_E_VERSION_MISMATCH:
return IDS_ERROR_VERSION_MISMATCH;
case FAX_E_RECIPIENTS_LIMIT:
return IDS_ERROR_RECIPIENTS_LIMIT;
default:
return IDS_ERROR_OPERATION_FAILED;
}
}
//
//====================== SYSTEM TIME TO LOCAL DATE ============================================
//
HRESULT
SystemTime2LocalDate(
SYSTEMTIME sysTimeFrom,
DATE *pdtTo
)
/*++
Routine name : SystemTime2LocalDate
Routine description:
Convert the System Time stored in FAX_MESSAGE struct to the DATE understood by client
Author:
Iv Garber (IvG), May, 2000
Arguments:
tmFrom [in] - the System time to convert
pdtTo [out] - the Date to return
Return Value:
Standard HRESULT code
--*/
{
HRESULT hr = S_OK;
DBG_ENTER (TEXT("SystemTime2LocalDate"), hr);
//
// convert System Time to File Time
//
FILETIME fileSysTime;
if(!SystemTimeToFileTime(&sysTimeFrom, &fileSysTime))
{
hr = Fax_HRESULT_FROM_WIN32(GetLastError());
CALL_FAIL (GENERAL_ERR, _T("SystemTimeToFileTime"), hr);
return hr;
}
//
// convert File Time to Local File Time
//
FILETIME fileLocalTime;
if(!FileTimeToLocalFileTime(&fileSysTime, &fileLocalTime))
{
hr = Fax_HRESULT_FROM_WIN32(GetLastError());
CALL_FAIL (GENERAL_ERR, _T("FileTimeToLocalFileTime"), hr);
return hr;
}
//
// convert Local File Time back to System Time
//
if(!FileTimeToSystemTime(&fileLocalTime, &sysTimeFrom))
{
hr = Fax_HRESULT_FROM_WIN32(GetLastError());
CALL_FAIL (GENERAL_ERR, _T("FileTimeToSystemTime"), hr);
return hr;
}
//
// finally, convert now local System Time to Variant Time
//
if (!SystemTimeToVariantTime(&sysTimeFrom, pdtTo))
{
hr = Fax_HRESULT_FROM_WIN32(GetLastError());
CALL_FAIL (GENERAL_ERR, _T("SystemTimeToVariantTime"), hr);
return hr;
}
return hr;
}