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.
 
 
 
 
 
 

392 lines
10 KiB

/********************************************************************
Copyright (c) 2001 Microsoft Corporation
Module Name:
pcache.cpp
Revision History:
DerekM created 11/26/01
********************************************************************/
#if defined(UNICODE)
#include <windows.h>
#include "dlcache.h"
#include <strsafe.h>
#include <mistsafe.h>
// **************************************************************************
inline
DWORD RolloverSubtract(DWORD dwA, DWORD dwB)
{
return (dwA >= dwB) ? (dwA - dwB) : (dwA + ((DWORD)-1 - dwB));
}
// **************************************************************************
CWUDLProxyCache::CWUDLProxyCache()
{
m_rgpObj = NULL;
}
// **************************************************************************
CWUDLProxyCache::~CWUDLProxyCache()
{
this->Empty();
}
// **************************************************************************
SWUDLProxyCacheObj *CWUDLProxyCache::internalFind(LPCWSTR wszSrv)
{
SWUDLProxyCacheObj *pObj = m_rgpObj;
SWUDLProxyCacheObj **ppNextPtr = &m_rgpObj;
// see if it exists
while(pObj != NULL)
{
if (pObj->wszSrv != NULL && _wcsicmp(pObj->wszSrv, wszSrv) == 0)
{
// detach it from the list
*ppNextPtr = pObj->pNext;
pObj->pNext = NULL;
break;
}
ppNextPtr = &pObj->pNext;
pObj = pObj->pNext;
}
return pObj;
}
// **************************************************************************
BOOL CWUDLProxyCache::Set(LPCWSTR wszSrv, LPCWSTR wszProxy, LPCWSTR wszBypass,
DWORD dwAccessType)
{
SWUDLProxyCacheObj *pObj = NULL;
HRESULT hr = NOERROR;
DWORD cbProxy = 0, cbBypass = 0, cbSrv, cbNeed;
BOOL fRet = FALSE;
if (wszSrv == NULL || *wszSrv == L'\0')
{
SetLastError(ERROR_INVALID_PARAMETER);
goto done;
}
cbSrv = (wcslen(wszSrv) + 1) * sizeof(WCHAR);
cbNeed = cbSrv + sizeof(SWUDLProxyCacheObj);
if (wszProxy != NULL)
{
cbProxy = (wcslen(wszProxy) + 1) * sizeof(WCHAR);
cbNeed += cbProxy;
if (wszBypass != NULL)
{
cbBypass = (wcslen(wszBypass) + 1) * sizeof(WCHAR);
cbNeed += cbBypass;
}
}
// Now, in theory, we should look for an existing object in the list for this
// server, but a couple things make it unnecessary:
// 1. we only use this class in one place
// 2. we will always attempt a find first
// 3. we will only get to this function if find returns NULL
// 4. if one exists, but it's outdated, find will delete it and return NULL
//
// Given the above, there should never be an existing object when Set is
// called.
pObj = (SWUDLProxyCacheObj *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
cbNeed);
if (pObj == NULL)
{
SetLastError(ERROR_OUTOFMEMORY);
goto done;
}
// set up pointers into the blob for the strings & copy the data down
pObj->wszSrv = (LPWSTR)((LPBYTE)pObj + sizeof(SWUDLProxyCacheObj));
hr = StringCbCopyExW(pObj->wszSrv, cbSrv, wszSrv,
NULL, NULL, MISTSAFE_STRING_FLAGS);
if (FAILED(hr))
{
SetLastError(HRESULT_CODE(hr));
goto done;
}
if (wszProxy != NULL)
{
pObj->wszProxy = (LPWSTR)((LPBYTE)pObj->wszSrv + cbSrv);
hr = StringCbCopyExW(pObj->wszProxy, cbProxy, wszProxy,
NULL, NULL, MISTSAFE_STRING_FLAGS);
if (FAILED(hr))
{
SetLastError(HRESULT_CODE(hr));
goto done;
}
if (wszBypass != NULL)
{
pObj->wszBypass = (LPWSTR)((LPBYTE)pObj->wszProxy + cbProxy);
hr = StringCbCopyExW(pObj->wszBypass, cbBypass, wszBypass,
NULL, NULL, MISTSAFE_STRING_FLAGS);
if (FAILED(hr))
{
SetLastError(HRESULT_CODE(hr));
goto done;
}
}
}
pObj->dwLastCacheTime = GetTickCount();
pObj->dwAccessType = dwAccessType;
pObj->cbBypass = cbBypass;
pObj->cbProxy = cbProxy;
pObj->iLastKnownGood = (DWORD)-1;
pObj->pNext = m_rgpObj;
m_rgpObj = pObj;
pObj = NULL;
fRet = TRUE;
done:
if (pObj != NULL)
HeapFree(GetProcessHeap(), 0, pObj);
return fRet;
}
// **************************************************************************
BOOL CWUDLProxyCache::Find(LPCWSTR wszSrv, LPWSTR *pwszProxy, LPWSTR *pwszBypass,
DWORD *pdwAccessType)
{
SWUDLProxyCacheObj *pObj = NULL;
HRESULT hr = NOERROR;
LPWSTR wszProxy = NULL;
LPWSTR wszBypass = NULL;
DWORD dwNow;
BOOL fRet = FALSE, fFreeObjMemory = FALSE;
if (wszSrv == NULL || pwszProxy == NULL || pwszBypass == NULL ||
pdwAccessType == NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
goto done;
}
*pdwAccessType = 0;
*pwszBypass = NULL;
*pwszProxy = NULL;
// does it exist?
pObj = this->internalFind(wszSrv);
if (pObj == NULL)
goto done;
// has the object expired?
dwNow = GetTickCount();
if (RolloverSubtract(dwNow, pObj->dwLastCacheTime) > c_dwProxyCacheTimeLimit)
{
fFreeObjMemory = TRUE;
goto done;
}
// reset object to front of list
pObj->pNext = m_rgpObj;
m_rgpObj = pObj;
// need to use GloablAlloc here cuz that's what WinHttp uses and we need
// to match it
if (pObj->cbBypass > 0 && pObj->wszBypass != NULL)
{
wszBypass = (LPWSTR)GlobalAlloc(GMEM_FIXED, pObj->cbBypass);
if (wszBypass == NULL)
{
SetLastError(ERROR_OUTOFMEMORY);
goto done;
}
hr = StringCbCopyExW(wszBypass, pObj->cbBypass, pObj->wszBypass,
NULL, NULL, MISTSAFE_STRING_FLAGS);
if (FAILED(hr))
{
SetLastError(HRESULT_CODE(hr));
goto done;
}
}
if (pObj->cbProxy > 0 && pObj->wszProxy != NULL)
{
wszProxy = (LPWSTR)GlobalAlloc(GMEM_FIXED, pObj->cbProxy);
if (wszProxy == NULL)
{
SetLastError(ERROR_OUTOFMEMORY);
goto done;
}
hr = StringCbCopyExW(wszProxy, pObj->cbProxy, pObj->wszProxy,
NULL, NULL, MISTSAFE_STRING_FLAGS);
if (FAILED(hr))
{
SetLastError(HRESULT_CODE(hr));
goto done;
}
}
*pdwAccessType = pObj->dwAccessType;
*pwszBypass = wszBypass;
*pwszProxy = wszProxy;
wszBypass = NULL;
wszProxy = NULL;
pObj = NULL;
fRet = TRUE;
done:
if (fFreeObjMemory && pObj != NULL)
HeapFree(GetProcessHeap(), 0, pObj);
if (wszProxy != NULL)
GlobalFree(wszProxy);
if (wszBypass != NULL)
GlobalFree(wszBypass);
return fRet;
}
// **************************************************************************
BOOL CWUDLProxyCache::SetLastGoodProxy(LPCWSTR wszSrv, DWORD iProxy)
{
SWUDLProxyCacheObj *pObj = NULL;
BOOL fRet = FALSE;
// does it exist?
pObj = this->internalFind(wszSrv);
if (pObj == NULL)
goto done;
// reset object to front of list
pObj->pNext = m_rgpObj;
m_rgpObj = pObj;
pObj->iLastKnownGood = iProxy;
fRet = TRUE;
done:
return fRet;
}
// **************************************************************************
BOOL CWUDLProxyCache::GetLastGoodProxy(LPCWSTR wszSrv, SAUProxySettings *paups)
{
SWUDLProxyCacheObj *pObj = NULL;
HRESULT hr = NOERROR;
LPWSTR wszBypass = NULL, wszProxy = NULL;
BOOL fRet = FALSE;
if (wszSrv == NULL || paups == NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
goto done;
}
// does it exist?
pObj = this->internalFind(wszSrv);
if (pObj == NULL)
{
SetLastError(ERROR_FILE_NOT_FOUND);
goto done;
}
// reset object to front of list
pObj->pNext = m_rgpObj;
m_rgpObj = pObj;
// need to use GloablAlloc here cuz that's what WinHttp uses and we need
// to match it
if (pObj->cbBypass > 0 && pObj->wszBypass != NULL)
{
wszBypass = (LPWSTR)GlobalAlloc(GMEM_FIXED, pObj->cbBypass);
if (wszBypass == NULL)
{
SetLastError(ERROR_OUTOFMEMORY);
goto done;
}
hr = StringCbCopyExW(wszBypass, pObj->cbBypass, pObj->wszBypass,
NULL, NULL, MISTSAFE_STRING_FLAGS);
if (FAILED(hr))
{
SetLastError(HRESULT_CODE(hr));
goto done;
}
}
if (pObj->cbProxy > 0 && pObj->wszProxy != NULL)
{
wszProxy = (LPWSTR)GlobalAlloc(GMEM_FIXED, pObj->cbProxy);
if (wszProxy == NULL)
{
SetLastError(ERROR_OUTOFMEMORY);
goto done;
}
hr = StringCbCopyExW(wszProxy, pObj->cbProxy, pObj->wszProxy,
NULL, NULL, MISTSAFE_STRING_FLAGS);
if (FAILED(hr))
{
SetLastError(HRESULT_CODE(hr));
goto done;
}
}
ZeroMemory(paups, sizeof(SAUProxySettings));
paups->dwAccessType = pObj->dwAccessType;
paups->wszBypass = wszBypass;
paups->wszProxyOrig = wszProxy;
paups->iProxy = pObj->iLastKnownGood;
wszBypass = NULL;
wszProxy = NULL;
fRet = TRUE;
done:
if (wszProxy != NULL)
GlobalFree(wszProxy);
if (wszBypass != NULL)
GlobalFree(wszBypass);
return fRet;
}
// **************************************************************************
BOOL CWUDLProxyCache::Empty(void)
{
SWUDLProxyCacheObj *pObj = m_rgpObj;
while (pObj != NULL)
{
m_rgpObj = pObj->pNext;
HeapFree(GetProcessHeap(), 0, pObj);
pObj = m_rgpObj;
}
return TRUE;
}
#endif