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.
 
 
 
 
 
 

664 lines
18 KiB

/**********************************************************************/
/** Microsoft Passport **/
/** Copyright(c) Microsoft Corporation, 1999 - 2001 **/
/**********************************************************************/
/*
ppshadowdocument.cpp
manages a local shadow of the CCD
FILE HISTORY:
*/
#include "precomp.h"
//===========================================================================
//
// PpShadowDocument
//
PpShadowDocument::PpShadowDocument()
{
}
//===========================================================================
//
// PpShadowDocument
//
PpShadowDocument::PpShadowDocument(
tstring& strURL) : m_strURL(strURL)
{
}
//===========================================================================
//
// PpShadowDocument
//
PpShadowDocument::PpShadowDocument(
tstring& strURL,
tstring& strLocalFile) : m_strURL(strURL), m_strLocalFile(strLocalFile)
{
}
//===========================================================================
//
// SetURL -- URL
//
void
PpShadowDocument::SetURL(
tstring& strURL)
{
m_strURL = strURL;
}
//===========================================================================
//
// SetLocalFile -- localfile name
//
void
PpShadowDocument::SetLocalFile(
tstring& strLocalFile)
{
m_strLocalFile = strLocalFile;
}
//===========================================================================
//
// GetDocument -- get CCDs DOM interface
// -- bForceFetch : force an HTTPs, otherwise using local shadow
//
HRESULT
PpShadowDocument::GetDocument(
IXMLDocument** ppiXMLDocument,
BOOL bForceFetch
)
{
HRESULT hr;
PpNexusClient nexusClient;
IPersistStreamInitPtr xmlStream;
IXMLDocumentPtr xmlDoc;
if(ppiXMLDocument == NULL)
{
hr = E_INVALIDARG;
goto Cleanup;
}
*ppiXMLDocument = NULL;
if(bForceFetch)
{
// Fetch the XML document
if(!m_strURL.empty())
hr = nexusClient.FetchCCD(m_strURL, ppiXMLDocument);
else
{
tstring strMsg;
if(!m_strLocalFile.empty())
{
strMsg = TEXT("for ");
strMsg += m_strLocalFile;
}
if (NULL != g_pAlert)
{
g_pAlert->report(PassportAlertInterface::ERROR_TYPE,
NEXUS_EMPTYREMOTENAME,
strMsg.c_str()
);
}
hr = S_FALSE;
}
if(m_strLocalFile.empty())
{
tstring strMsg;
if(!m_strURL.empty())
{
strMsg = TEXT("for ");
strMsg += m_strURL;
}
if (NULL != g_pAlert)
{
g_pAlert->report(PassportAlertInterface::INFORMATION_TYPE,
NEXUS_EMPTYLOCALNAME,
strMsg.c_str()
);
}
goto Cleanup;
}
// If FetchCCD failed and a local file is configured, read from the file.
// If FetchCCD succeeded and a local file is configured, write to the file.
if(hr == S_OK)
{
if(!NoPersist(*ppiXMLDocument))
SaveDocument(*ppiXMLDocument);
else
{
if (NULL != g_pAlert)
{
g_pAlert->report(PassportAlertInterface::INFORMATION_TYPE,
NEXUS_NOTPERSISTING,
m_strURL.c_str());
}
}
}
else
{
// use new hr variable, not to eat the global one
HRESULT hr1 = LoadDocument(ppiXMLDocument);
if (NULL != g_pAlert)
{
if (hr1 != S_OK)
g_pAlert->report(PassportAlertInterface::ERROR_TYPE,
NEXUS_LOADFAILED,
m_strLocalFile.c_str());
else
g_pAlert->report(PassportAlertInterface::INFORMATION_TYPE,
NEXUS_USINGLOCAL,
m_strLocalFile.c_str());
}
}
}
else
{
if(!m_strLocalFile.empty())
{
hr = LoadDocument(ppiXMLDocument);
if(hr == S_OK)
{
// If the file is still valid, then return.
if(IsValidCCD(*ppiXMLDocument))
{
if (NULL != g_pAlert)
{
g_pAlert->report(PassportAlertInterface::INFORMATION_TYPE,
NEXUS_USINGLOCAL,
m_strLocalFile.c_str());
}
goto Cleanup;
}
}
else
{
if (NULL != g_pAlert)
{
g_pAlert->report(PassportAlertInterface::ERROR_TYPE,
NEXUS_LOADFAILED,
m_strLocalFile.c_str());
}
}
}
else
{
tstring strMsg;
if(!m_strURL.empty())
{
strMsg = TEXT("for ");
strMsg += m_strURL;
}
if (NULL != g_pAlert)
{
g_pAlert->report(PassportAlertInterface::INFORMATION_TYPE,
NEXUS_EMPTYLOCALNAME,
strMsg.c_str()
);
}
}
// At this point, we're in one of two states:
// 1. *ppiXMLDocument is NULL
// 2. *ppiXMLDocument is not NULL, but points to a document that is old
// Fetch the XML document, if successful release the document loaded from
// disk (if any).
if(!m_strURL.empty())
hr = nexusClient.FetchCCD(m_strURL, &xmlDoc);
else
{
tstring strMsg;
if(!m_strLocalFile.empty())
{
strMsg = TEXT("for ");
strMsg += m_strLocalFile;
}
if (NULL != g_pAlert)
{
g_pAlert->report(PassportAlertInterface::ERROR_TYPE,
NEXUS_EMPTYREMOTENAME,
strMsg.c_str()
);
}
hr = S_FALSE;
}
if(hr == S_OK)
{
if(*ppiXMLDocument) (*ppiXMLDocument)->Release();
xmlDoc->QueryInterface(IID_IXMLDocument, (void**)ppiXMLDocument);
// If FetchCCD succeeded and a local file is configured, write to the file.
if(!m_strLocalFile.empty())
{
if(!NoPersist(*ppiXMLDocument))
{
HANDLE hToken = NULL;
//
// In certain configurations this code can be run while impersonating a user who
// does not have access to the directory to store the partner2.xml. Therefore
// we revert to self prior to attempting to save the document.
//
if (OpenThreadToken(GetCurrentThread(),
MAXIMUM_ALLOWED,
TRUE,
&hToken))
{
RevertToSelf();
}
SaveDocument(*ppiXMLDocument);
if (hToken)
{
// put the impersonation token back
if (!SetThreadToken(NULL, hToken))
{
hr = E_FAIL;
}
CloseHandle(hToken);
}
}
else
{
if (NULL != g_pAlert)
{
g_pAlert->report(PassportAlertInterface::INFORMATION_TYPE,
NEXUS_NOTPERSISTING,
m_strURL.c_str());
}
}
}
else
{
tstring strMsg;
if(!m_strURL.empty())
{
strMsg = TEXT("for ");
strMsg += m_strURL;
}
if (NULL != g_pAlert)
{
g_pAlert->report(PassportAlertInterface::INFORMATION_TYPE,
NEXUS_EMPTYLOCALNAME,
strMsg.c_str()
);
}
}
}
else if(*ppiXMLDocument)
{
// TODO: the logic is not so clear, on 3.0 timeframe, rewrite this whole func
if (NULL != g_pAlert)
{
g_pAlert->report(PassportAlertInterface::INFORMATION_TYPE,
NEXUS_USINGLOCAL,
m_strLocalFile.c_str());
}
hr = S_OK;
}
else
{
// If we get here it means that the fetch from the nexus failed
// and the load from disk failed. It is sufficient here to simply
// fall through because hr will already contain an error code
// which should indicate to the caller that no document is
// available.
}
}
Cleanup:
return hr;
}
//===========================================================================
//
// IsValidCCD -- check ValidUntil attribute of the CCD
//
BOOL
PpShadowDocument::IsValidCCD(
IXMLDocument* piXMLDocument
)
{
BOOL bReturn;
HRESULT hr;
IXMLElementPtr piRootElement;
SYSTEMTIME sysTime;
DOUBLE dblTime;
VARIANT vAttrValue;
VARIANT vAttrDate;
hr = piXMLDocument->get_root(&piRootElement);
if(hr != S_OK)
{
bReturn = FALSE;
goto Cleanup;
}
VariantInit(&vAttrValue);
hr = piRootElement->getAttribute(L"ValidUntil", &vAttrValue);
if(hr != S_OK)
{
bReturn = FALSE;
goto Cleanup;
}
VariantInit(&vAttrDate);
hr = VariantChangeType(&vAttrDate, &vAttrValue, 0, VT_DATE);
if(hr != S_OK)
{
bReturn = FALSE;
goto Cleanup;
}
GetSystemTime(&sysTime);
SystemTimeToVariantTime(&sysTime, &dblTime);
bReturn = ((long)V_DATE(&vAttrDate) >= (long)dblTime);
Cleanup:
VariantClear(&vAttrValue);
VariantClear(&vAttrDate);
return bReturn;
}
//===========================================================================
//
// NoPersist -- Check no persist attribute of the document
//
BOOL
PpShadowDocument::NoPersist(
IXMLDocument* piXMLDocument
)
{
BOOL bReturn;
HRESULT hr;
IXMLElementPtr piRootElement;
VARIANT vAttrValue;
hr = piXMLDocument->get_root(&piRootElement);
if(hr != S_OK)
{
bReturn = FALSE;
goto Cleanup;
}
VariantInit(&vAttrValue);
hr = piRootElement->getAttribute(L"NoPersist", &vAttrValue);
if(hr != S_OK)
{
bReturn = FALSE;
goto Cleanup;
}
bReturn = (lstrcmpiW(L"true", V_BSTR(&vAttrValue)) == 0);
Cleanup:
VariantClear(&vAttrValue);
return bReturn;
}
//===========================================================================
//
// SaveDocument -- save CCD to local file
//
HRESULT
PpShadowDocument::SaveDocument(
IXMLDocument* piXMLDoc
)
{
HRESULT hr;
HANDLE hFile = INVALID_HANDLE_VALUE;
ULARGE_INTEGER uliSize;
LARGE_INTEGER liZero = {0,0};
IStreamPtr piStream;
IPersistStreamInitPtr piPSI;
LPBYTE lpBuf = NULL;
DWORD dwCurBlock;
DWORD dwBytesWritten;
hr = CreateStreamOnHGlobal(NULL, TRUE, &piStream);
if(hr != S_OK)
goto Cleanup;
hr = piXMLDoc->QueryInterface(IID_IPersistStreamInit, (void**)&piPSI);
if(hr != S_OK)
goto Cleanup;
piPSI->Save(piStream, TRUE);
piStream->Seek(liZero, STREAM_SEEK_CUR, &uliSize);
piStream->Seek(liZero, STREAM_SEEK_SET, NULL);
if(uliSize.HighPart != 0)
{
hr = E_FAIL;
goto Cleanup;
}
lpBuf = new BYTE[uliSize.LowPart];
if(lpBuf == NULL)
{
hr = E_OUTOFMEMORY;
goto Cleanup;
}
hFile = CreateFile(
m_strLocalFile.c_str(),
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(hFile == INVALID_HANDLE_VALUE)
{
hr = GetLastError();
goto Cleanup;
}
for(dwCurBlock = 0; dwCurBlock < uliSize.HighPart; dwCurBlock++)
{
hr = piStream->Read(lpBuf, 0xFFFFFFFF, NULL);
if(!WriteFile(hFile, lpBuf, 0xFFFFFFFF, NULL, NULL))
{
hr = GetLastError();
goto Cleanup;
}
}
hr = piStream->Read(lpBuf, uliSize.LowPart, NULL);
if(hr != S_OK)
goto Cleanup;
if(!WriteFile(hFile, lpBuf, uliSize.LowPart, &dwBytesWritten, NULL))
{
hr = GetLastError();
goto Cleanup;
}
hr = S_OK;
Cleanup:
if(hr != S_OK)
{
TCHAR achErrBuf[1024];
LPCTSTR apszStrings[] = { m_strLocalFile.c_str(), achErrBuf };
LPVOID lpMsgBuf = NULL;
ULONG cchTmp;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_FROM_HMODULE |
FORMAT_MESSAGE_MAX_WIDTH_MASK,
GetModuleHandle(TEXT("wininet.dll")),
hr,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL );
lstrcpy(achErrBuf, TEXT("0x"));
_ultot(hr, &(achErrBuf[2]), 16);
achErrBuf[sizeof(achErrBuf) / sizeof(achErrBuf[0]) - 1] = TEXT('\0');
if(lpMsgBuf != NULL && *(LPTSTR)lpMsgBuf != TEXT('\0'))
{
cchTmp = _tcslen(achErrBuf) + 1;
_tcsncat(achErrBuf, TEXT(" ("), (sizeof(achErrBuf) / sizeof(achErrBuf[0])) - cchTmp);
_tcsncat(achErrBuf, (LPTSTR)lpMsgBuf, (sizeof(achErrBuf) / sizeof(achErrBuf[0])) - (cchTmp + 2));
cchTmp = _tcslen(achErrBuf) + 1;
_tcsncat(achErrBuf, TEXT(") "), (sizeof(achErrBuf) / sizeof(achErrBuf[0])) - cchTmp);
}
lstrcat(achErrBuf, TEXT(" when trying to save the fetched file to disk."));
g_pAlert->report(PassportAlertInterface::ERROR_TYPE,
NEXUS_LOCALSAVEFAILED,
2,
apszStrings,
0,
NULL
);
LocalFree(lpMsgBuf);
hr = E_FAIL;
}
if(lpBuf != NULL)
delete [] lpBuf;
if(hFile != INVALID_HANDLE_VALUE)
CloseHandle(hFile);
return hr;
}
//===========================================================================
//
// LoadDocument -- get CCDs from local
//
HRESULT
PpShadowDocument::LoadDocument(
IXMLDocument** ppiXMLDocument
)
{
HRESULT hr;
HANDLE hFile = INVALID_HANDLE_VALUE;
DWORD dwFileSizeLow;
DWORD dwBytesRead;
LPBYTE lpBuf = NULL;
IStreamPtr piStream;
IPersistStreamInitPtr piPSI;
LARGE_INTEGER liZero = {0,0};
hFile = CreateFile(
m_strLocalFile.c_str(),
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(hFile == INVALID_HANDLE_VALUE)
{
hr = E_FAIL;
goto Cleanup;
}
dwFileSizeLow = GetFileSize(hFile, NULL);
if(dwFileSizeLow == 0xFFFFFFFF)
{
hr = GetLastError();
goto Cleanup;
}
lpBuf = new BYTE[dwFileSizeLow];
if(lpBuf == NULL)
{
hr = E_OUTOFMEMORY;
goto Cleanup;
}
hr = CreateStreamOnHGlobal(NULL, TRUE, &piStream);
if(hr != S_OK)
{
hr = E_FAIL;
goto Cleanup;
}
if(ReadFile(hFile, lpBuf, dwFileSizeLow, &dwBytesRead, NULL) == 0)
{
hr = E_FAIL;
goto Cleanup;
}
try
{
hr = piStream->Write(lpBuf, dwFileSizeLow, NULL);
hr = piStream->Seek(liZero, STREAM_SEEK_SET, NULL);
}
catch(...)
{
hr = E_FAIL;
goto Cleanup;
}
//
// Now create an XML object and initialize it using the stream.
//
hr = CoCreateInstance(__uuidof(XMLDocument), NULL, CLSCTX_ALL, IID_IPersistStreamInit, (void**)&piPSI);
if(hr != S_OK)
goto Cleanup;
hr = piPSI->Load((IStream*)piStream);
if(hr != S_OK)
goto Cleanup;
hr = piPSI->QueryInterface(__uuidof(IXMLDocument), (void**)ppiXMLDocument);
Cleanup:
if(lpBuf != NULL)
delete [] lpBuf;
if(hFile != INVALID_HANDLE_VALUE)
CloseHandle(hFile);
return hr;
}