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.
392 lines
10 KiB
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
|
|
|