|
|
//***********************************************************************************
//
// Copyright (c) 2001 Microsoft Corporation. All Rights Reserved.
//
// File: UrlAgent.cpp
//
// Description:
//
// This class encapsulates the logic about where to get the right logic
// for various purposes, including the case of running WU in corporate
// environments.
//
// An object based on this class should be created first, then call
// GetOriginalIdentServer() function to get where to download ident,
// then download ident, then call PopulateData() function to read
// all URL related data.
//
// Created by:
// Charles Ma
//
// Date Creatd:
// Oct 19, 2001
//
//***********************************************************************************
#include <windows.h>
#include <iucommon.h>
#include <osdet.h>
#include <logging.h>
#include <fileUtil.h>
#include <memutil.h>
#include <shlwapi.h>
#include <UrlAgent.h>
#include <MISTSAFE.h>
#include <wusafefn.h>
#ifndef INTERNET_MAX_URL_LENGTH
#define INTERNET_MAX_URL_LENGTH 2200
#endif
//
// starting size of url array
//
const int C_INIT_URL_ARRAY_SIZE = 4; // for time being,we only have this many clients
//
// define the default original ident url
//
const TCHAR C_DEFAULT_IDENT_URL[] = _T("http://windowsupdate.microsoft.com/v4/");
//
// define reg keys to get ident server override for debugging
//
const TCHAR REGKEY_IDENT_SERV[] = _T("IdentServer"); const TCHAR REGKEY_IUCTL[] = _T("Software\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate\\IUControl");
const TCHAR REGVAL_ISBETA[] = _T("IsBeta");
//
// define reg keys used by related policies
//
//
// define policy location
//
const TCHAR REGKEY_CORPWU_POLICY[] = _T("Software\\Policies\\Microsoft\\Windows\\WindowsUpdate");
//
// define ident and selfupdate server, and ping server
//
const TCHAR REGKEY_CORPWU_WUSERVER[] = _T("WUServer"); const TCHAR REGKEY_CORPWU_PINGSERVER[] = _T("WUStatusServer");
//
// define the boolean (DWORD) value under each client
//
const TCHAR REGKEY_USEWUSERVER[] = _T("UseWUServer");
//
// define ident data
//
const TCHAR IDENT_SECTION_PINGSERVER[] = _T("IUPingServer"); // section name in ident
const TCHAR IDENT_ENTRY_SERVERURL[] = _T("ServerUrl"); // ping server entry name
const TCHAR IDENT_SECITON_IUSERVERCACHE[] = _T("IUServerCache"); // query server section
const TCHAR IDENT_ENTRY_QUERYSEVERINDEX[] = _T("QueryServerIndex"); // suffix of client entry
const TCHAR IDENT_ENTRY_BETAQUERYSERVERINDEX[] = _T("BetaQueryServerIndex"); // for beta server
const TCHAR IDENT_ENTRY_SERVER[] = _T("Server"); // prefix of server entry
// main IU selfupdate keys
const TCHAR IDENT_IUSELFUPDATE[] = _T("IUSelfUpdate"); const TCHAR IDENT_IUBETASELFUPDATE[] = _T("IUBetaSelfUpdate"); const TCHAR IDENT_STRUCTUREKEY[] = _T("StructureKey"); // IU selfupdate architecture flags
const TCHAR IDENT_ARCH[] = _T("ARCH"); const TCHAR IDENT_OS[] = _T("OS"); const TCHAR IDENT_LOCALE[] = _T("LOCALE"); const TCHAR IDENT_CHARTYPE[] = _T("CHARTYPE"); // IU selfupdate sections
const TCHAR IDENT_IUARCH[] = _T("IUArch"); const TCHAR IDENT_IUOS[] = _T("IUOS"); const TCHAR IDENT_IULOCALE[] = _T("IULocale"); const TCHAR IDENT_IUCHARTYPE[] = _T("IUCharType"); // IU selfupdate arch keys
const TCHAR IDENT_X86[] = _T("x86"); const TCHAR IDENT_IA64[] = _T("ia64"); // IU selfupdate chartypes
const TCHAR IDENT_ANSI[] = _T("ansi"); const TCHAR IDENT_UNICODE[] = _T("unicode");
const TCHAR SLASHENGINECAB[] = _T("/iuengine.cab");
// AU specific:
const TCHAR CLIENT_AU[] = _T("AU"); const TCHAR CLIENT_AU_DRIVER[] = _T("AUDriver");
// *********************************************************************
//
// begin of class implementation
//
// *********************************************************************
CUrlAgent::CUrlAgent(void) : m_fPopulated(FALSE), m_pszOrigIdentUrl(NULL), m_pszInternetPingUrl(NULL), m_pszIntranetPingUrl(NULL), m_pszWUServer(NULL), m_ArrayUrls(NULL), m_nArrayUrlCount(0), m_nArraySize(0), m_nOrigIdentUrlBufSize(0), m_fIdentFromPolicy(FALSE) {
HKEY hKey = NULL; DWORD dwRegCheckResult = 0; DWORD dwSize = 0, dwType, dwValue;
LOG_Block("CUrlAgent::CUrlAgent()");
//
// always try to get original ident server url
//
m_hProcHeap = GetProcessHeap();
if (NULL != m_hProcHeap) { m_nOrigIdentUrlBufSize = __max( MAX_PATH, // reg based?
sizeof(C_DEFAULT_IDENT_URL)/sizeof(TCHAR)); // default
m_pszOrigIdentUrl = (LPTSTR) HeapAlloc( m_hProcHeap, // allocate from process heap
HEAP_ZERO_MEMORY, sizeof(TCHAR) * m_nOrigIdentUrlBufSize);
if (NULL != m_pszOrigIdentUrl) { //
// first, check to see if there is debug override
//
dwRegCheckResult= RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_IUCTL, 0, KEY_READ, &hKey); if (ERROR_SUCCESS == dwRegCheckResult) { dwSize = sizeof(TCHAR) * m_nOrigIdentUrlBufSize; dwRegCheckResult = RegQueryValueEx(hKey, REGKEY_IDENT_SERV, NULL, &dwType, (LPBYTE)m_pszOrigIdentUrl, &dwSize); if (ERROR_SUCCESS == dwRegCheckResult) { if (REG_SZ == dwType) { LOG_Internet(_T("Found debugging Ident-URL %s"), m_pszOrigIdentUrl); } else { dwRegCheckResult = ERROR_SUCCESS + 1; // any error number will do
} } RegCloseKey(hKey); }
if (ERROR_SUCCESS != dwRegCheckResult) { //
// if there is no debug override, check to see if there is policy define
// ident server for corporate case
//
dwRegCheckResult= RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_CORPWU_POLICY, 0, KEY_READ, &hKey); if (ERROR_SUCCESS == dwRegCheckResult) { dwSize = sizeof(TCHAR) * m_nOrigIdentUrlBufSize; dwRegCheckResult = RegQueryValueEx(hKey, REGKEY_CORPWU_WUSERVER, NULL, &dwType, (LPBYTE)m_pszOrigIdentUrl, &dwSize); if (ERROR_SUCCESS == dwRegCheckResult && REG_SZ == dwType) { m_fIdentFromPolicy = TRUE; //
// for any client that its name appear here as a subkey, and
// has a value "UseWUServer" set to 1 under the subkey, then
// this will also be the base url used to construct the query url
// for that client
//
m_pszWUServer = m_pszOrigIdentUrl;
LOG_Internet(_T("Found corp Ident-URL %s"), m_pszOrigIdentUrl);
//
// since we found wu server, for any client uses this url,
// we can also have an optional ping server
//
m_pszIntranetPingUrl = (LPTSTR) HeapAlloc( m_hProcHeap, HEAP_ZERO_MEMORY, sizeof(TCHAR) * m_nOrigIdentUrlBufSize); dwSize = sizeof(TCHAR) * m_nOrigIdentUrlBufSize; if (NULL != m_pszIntranetPingUrl) { if (ERROR_SUCCESS != (dwRegCheckResult = RegQueryValueEx(hKey, REGKEY_CORPWU_PINGSERVER, NULL, &dwType, (LPBYTE)m_pszIntranetPingUrl, &dwSize)) || REG_SZ != dwType) { StringCchCopyEx(m_pszIntranetPingUrl,m_nOrigIdentUrlBufSize,m_pszOrigIdentUrl,NULL,NULL,MISTSAFE_STRING_FLAGS); dwRegCheckResult = ERROR_SUCCESS; } } } else { dwRegCheckResult = ERROR_SUCCESS + 1; // any error number will do
} RegCloseKey(hKey); } }
if (ERROR_SUCCESS != dwRegCheckResult) { //
// not debugging , neither corporate policy found
//
StringCchCopyEx(m_pszOrigIdentUrl,m_nOrigIdentUrlBufSize,C_DEFAULT_IDENT_URL,NULL,NULL,MISTSAFE_STRING_FLAGS); LOG_Internet(_T("Use default ident URL %s"), m_pszOrigIdentUrl); } } } else { LOG_ErrorMsg(GetLastError()); }
//
// Check IUControl Reg Key for Beta Mode
//
m_fIsBetaMode = FALSE; if (ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, REGKEY_IUCTL, &hKey)) { dwValue = 0; dwSize = sizeof(dwValue); if (ERROR_SUCCESS == RegQueryValueEx(hKey, REGVAL_ISBETA, NULL, NULL, (LPBYTE)&dwValue, &dwSize)) { m_fIsBetaMode = (1 == dwValue); } RegCloseKey(hKey); } }
CUrlAgent::~CUrlAgent(void) { DesertData();
SafeHeapFree(m_pszOrigIdentUrl); SafeHeapFree(m_pszIntranetPingUrl); }
//------------------------------------------------------------------------
//
// this function should be called after you downloaded ident, and get
// a fresh copy of ident text file from the cab, after verifying cab was
// signed properly.
//
// this function reads data from ident and registry
//
//------------------------------------------------------------------------
HRESULT CUrlAgent::PopulateData(void) { LOG_Block("CUrlAgent::PopuldateData");
if (m_fPopulated) return S_OK;
HRESULT hr = S_OK; LPTSTR pszBuffer = NULL; LPTSTR pszCurrentKey = NULL; // ptr only, no memory alloc
LPTSTR pszUrlBuffer = NULL; LPCTSTR pcszSuffix = (m_fIsBetaMode ? IDENT_ENTRY_BETAQUERYSERVERINDEX : IDENT_ENTRY_QUERYSEVERINDEX); HKEY hKey = NULL; DWORD dwRegCheckResult = 0; DWORD dwSize = 0, dwType, dwValue = 0;
int iLen = 0, iLenSuffix = 0; TCHAR szIdentBuffer[MAX_PATH + 1]; TCHAR szIdentFile[MAX_PATH + 1];
if (NULL == m_hProcHeap) { return E_FAIL; }
pszUrlBuffer = (LPTSTR) HeapAlloc(m_hProcHeap, HEAP_ZERO_MEMORY, sizeof(TCHAR)*INTERNET_MAX_URL_LENGTH); CleanUpFailedAllocSetHrMsg(pszUrlBuffer);
GetIndustryUpdateDirectory(szIdentBuffer); hr=PathCchCombine(szIdentFile,ARRAYSIZE(szIdentFile), szIdentBuffer, IDENTTXT);
if(FAILED(hr)) { SafeHeapFree(pszUrlBuffer); LOG_ErrorMsg(hr); return hr; }
//
// make sure we release all data, if any
//
DesertData(); //
// before populate per-client array, we want to find out inter net ping server
//
m_pszInternetPingUrl = RetrieveIdentStrAlloc( IDENT_SECTION_PINGSERVER, IDENT_ENTRY_SERVERURL, NULL, szIdentFile);
//
// allocate array of pointers for storing each server node
//
m_ArrayUrls = (PServerPerClient) HeapAlloc(m_hProcHeap, HEAP_ZERO_MEMORY, C_INIT_URL_ARRAY_SIZE * sizeof(ServerPerClient)); CleanUpFailedAllocSetHrMsg(m_ArrayUrls);
m_nArraySize = C_INIT_URL_ARRAY_SIZE; // now array is this big
//
// try to read data from policy first, if WU server exists
//
if (NULL != m_pszWUServer && ERROR_SUCCESS == (dwRegCheckResult= RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_CORPWU_POLICY, 0, KEY_READ, &hKey))) { //
// the way we find a client name under WU policy is, to open this key, see if it has a value
// called "UseWUServer"
//
DWORD dwSubKeyIndex = 0; TCHAR szKeyName[32]; while (TRUE) { DWORD dwKeyBufLen = ARRAYSIZE(szKeyName); dwRegCheckResult = RegEnumKeyEx( hKey, // handle to key to enumerate
dwSubKeyIndex, // subkey index
szKeyName, // subkey name
&dwKeyBufLen, // size of subkey buffer
NULL, // reserved
NULL, // class string buffer
NULL, // size of class string buffer
NULL // last write time
); if (ERROR_SUCCESS == dwRegCheckResult) { //
// try to open this key
//
HKEY hKeyClient = NULL; dwRegCheckResult= RegOpenKeyEx(hKey, szKeyName, 0, KEY_READ, &hKeyClient); if (ERROR_SUCCESS == dwRegCheckResult) { //
// try to see if it has a value called UseWUServer
//
dwValue = 0; dwType = REG_DWORD; dwSize = sizeof(dwValue); dwRegCheckResult = RegQueryValueEx(hKeyClient, REGKEY_USEWUSERVER, NULL, &dwType, (LPBYTE) &dwValue, &dwSize); if (ERROR_SUCCESS == dwRegCheckResult && REG_DWORD == dwType && 0x1 == dwValue) { LOG_Internet(_T("Found client %s\\UseWUServer=1"), szKeyName);
//
// we want to add this client to our url array
//
CleanUpIfFailedAndSetHrMsg(ExpandArrayIfNeeded());
m_ArrayUrls[m_nArrayUrlCount].pszClientName = (LPTSTR)HeapAllocCopy(szKeyName, sizeof(TCHAR) * (lstrlen(szKeyName) + 1)); CleanUpFailedAllocSetHrMsg(m_ArrayUrls[m_nArrayUrlCount].pszClientName); m_ArrayUrls[m_nArrayUrlCount].pszQueryServer = (LPTSTR) HeapAllocCopy(m_pszOrigIdentUrl, sizeof(TCHAR) * (lstrlen(m_pszOrigIdentUrl) + 1)); CleanUpFailedAllocSetHrMsg(m_ArrayUrls[m_nArrayUrlCount].pszQueryServer); m_ArrayUrls[m_nArrayUrlCount].fInternalServer = TRUE; m_nArrayUrlCount++; // increase counter by 1
//
// BUG 507500 AUDriver Policy -
// map calls with the "AUDriver client to "AU" when checking the policy for usewuserver
//
if (CSTR_EQUAL == WUCompareStringI(szKeyName, CLIENT_AU)) { //
// we want to add client "AUDriver" to our url array
//
CleanUpIfFailedAndSetHrMsg(ExpandArrayIfNeeded());
m_ArrayUrls[m_nArrayUrlCount].pszClientName = (LPTSTR)HeapAllocCopy((LPTSTR)CLIENT_AU_DRIVER, sizeof(TCHAR) * (lstrlen(CLIENT_AU_DRIVER) + 1)); CleanUpFailedAllocSetHrMsg(m_ArrayUrls[m_nArrayUrlCount].pszClientName); m_ArrayUrls[m_nArrayUrlCount].pszQueryServer = (LPTSTR) HeapAllocCopy(m_pszOrigIdentUrl, sizeof(TCHAR) * (lstrlen(m_pszOrigIdentUrl) + 1)); CleanUpFailedAllocSetHrMsg(m_ArrayUrls[m_nArrayUrlCount].pszQueryServer); m_ArrayUrls[m_nArrayUrlCount].fInternalServer = TRUE; m_nArrayUrlCount++; // increase counter by 1
} } } RegCloseKey(hKeyClient); } else { if (ERROR_NO_MORE_ITEMS == dwRegCheckResult) { //
// there is no more sub key to loop through. get out here
//
break; } //
// otherwise, we try next sub key
//
}
dwSubKeyIndex++; // try next sub key
}
RegCloseKey(hKey); // done with policy reg
}
//
// now we should continue to work on internet case
// that is, to retrieve query server(s) from ident
//
dwSize = MAX_PATH; pszBuffer = (LPTSTR) HeapAlloc(m_hProcHeap, HEAP_ZERO_MEMORY, dwSize * sizeof(TCHAR)); while (NULL != pszBuffer && GetPrivateProfileString( IDENT_SECITON_IUSERVERCACHE, NULL, _T(""), pszBuffer, dwSize, szIdentFile) == dwSize-2) { //
// buffer too small?
//
dwSize *= 2;
LPTSTR pszTemp = (LPTSTR) HeapReAlloc(m_hProcHeap, HEAP_ZERO_MEMORY, pszBuffer, dwSize * sizeof(TCHAR)); if (NULL != pszTemp) { pszBuffer = pszTemp; } else { //
// HeapReAlloc failed, bail from while with origional allocation freed
//
SafeHeapFree(pszBuffer); } } CleanUpFailedAllocSetHrMsg(pszBuffer);
//
// loop through each key
//
pszCurrentKey = pszBuffer; while ('\0' != *pszCurrentKey) { //
// for the current key, we first try to see if its index key or server key
// if it's not index key, skip it
//
iLen = lstrlen(pszCurrentKey); iLenSuffix = lstrlen(pcszSuffix); if ((iLen > iLenSuffix) && (0 == StrCmpI((pszCurrentKey + (iLen - iLenSuffix)), pcszSuffix))) { TCHAR szClient[MAX_PATH]; // isn't MAX_PATH big enough?
int nIndex = 0; BOOL fExist = FALSE;
//
// retrieve server index from this key
//
nIndex = GetPrivateProfileInt(IDENT_SECITON_IUSERVERCACHE, pszCurrentKey, 0, szIdentFile);
//
// no use of szIdentBuffer, so utilize it here
//
CleanUpIfFailedAndSetHrMsg(StringCchPrintfEx(szIdentBuffer,ARRAYSIZE(szIdentBuffer),NULL,NULL,MISTSAFE_STRING_FLAGS,_T("%s%d"), IDENT_ENTRY_SERVER, nIndex)); GetPrivateProfileString( IDENT_SECITON_IUSERVERCACHE, szIdentBuffer, // use current str as key
_T(""), pszUrlBuffer, INTERNET_MAX_URL_LENGTH, szIdentFile); if ('0' != *pszUrlBuffer) { //
// this is an index key!
// try to extract client name from this key
//
CleanUpIfFailedAndSetHrMsg(StringCchCopyNEx(szClient,ARRAYSIZE(szClient),pszCurrentKey,iLen - iLenSuffix,NULL,NULL,MISTSAFE_STRING_FLAGS)); //
// find out if this client is already defined in policy and therefore
// arleady got data in the url array
//
for (int i = 0; i < m_nArrayUrlCount && !fExist; i++) { fExist= (StrCmpI(m_ArrayUrls[i].pszClientName, szClient) == 0); }
if (!fExist) { CleanUpIfFailedAndSetHrMsg(ExpandArrayIfNeeded()); m_ArrayUrls[m_nArrayUrlCount].pszClientName = (LPTSTR)HeapAllocCopy(szClient, sizeof(TCHAR) * (lstrlen(szClient) + 1)); CleanUpFailedAllocSetHrMsg(m_ArrayUrls[m_nArrayUrlCount].pszClientName); m_ArrayUrls[m_nArrayUrlCount].pszQueryServer = (LPTSTR) HeapAllocCopy(pszUrlBuffer, sizeof(TCHAR) * (lstrlen(pszUrlBuffer) + 1)); CleanUpFailedAllocSetHrMsg(m_ArrayUrls[m_nArrayUrlCount].pszQueryServer); m_ArrayUrls[m_nArrayUrlCount].fInternalServer = FALSE; m_nArrayUrlCount++; // increase counter by 1
} else { //
// this client is already defined in policy, we just need to append the QueryServer with the
// rest of the url path defined in iuident
//
LPTSTR pszPath = NULL; //
// find "//" in URL retrieved from iuident
//
if (NULL == (pszPath = StrStrI(pszUrlBuffer, _T("//")))) { // unexpected error
hr = E_FAIL; LOG_ErrorMsg(hr); goto CleanUp; } else { //
// find next "/" in URL retrieved from iuident
//
if (NULL != (pszPath = StrStrI(pszPath+2, _T("/")))) { DWORD dwLen = 0; LPTSTR pszTemp = NULL; //
// remove trailing "/" in URL retrieved from policy
//
if (_T('/') == *(m_ArrayUrls[i-1].pszQueryServer + lstrlen(m_ArrayUrls[i-1].pszQueryServer) - 1)) { dwLen = lstrlen(m_ArrayUrls[i-1].pszQueryServer) + lstrlen(pszPath); pszTemp = (LPTSTR)HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, m_ArrayUrls[i-1].pszQueryServer, sizeof(TCHAR) * dwLen); CleanUpFailedAllocSetHrMsg(pszTemp); m_ArrayUrls[i-1].pszQueryServer = pszTemp;
hr=StringCchCatEx(m_ArrayUrls[i-1].pszQueryServer,dwLen,pszPath + 1,NULL,NULL,MISTSAFE_STRING_FLAGS); if(FAILED(hr)) { LOG_ErrorMsg(hr); SafeHeapFree(pszTemp); m_ArrayUrls[i-1].pszQueryServer=NULL; } } else { dwLen = lstrlen(m_ArrayUrls[i-1].pszQueryServer) + lstrlen(pszPath) + 1; pszTemp = (LPTSTR)HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, m_ArrayUrls[i-1].pszQueryServer, sizeof(TCHAR) * dwLen); CleanUpFailedAllocSetHrMsg(pszTemp); m_ArrayUrls[i-1].pszQueryServer = pszTemp; hr=StringCchCatEx(m_ArrayUrls[i-1].pszQueryServer,dwLen,pszPath,NULL,NULL,MISTSAFE_STRING_FLAGS); if(FAILED(hr)) { LOG_ErrorMsg(hr); SafeHeapFree(pszTemp); m_ArrayUrls[i-1].pszQueryServer=NULL; }
} } } } } }
//
// move to next string
//
pszCurrentKey += lstrlen(pszCurrentKey) + 1; }
CleanUp:
if (FAILED(hr)) { //
// clean up half-way populated data
//
DesertData(); } else { m_fPopulated = TRUE; }
SafeHeapFree(pszBuffer); SafeHeapFree(pszUrlBuffer);
return hr; }
//------------------------------------------------------------------------
//
// get the original ident server.
// *** this API should be called before PopulateData() is called ***
// *** this API should be called to retrieve the base URL where you download ident ***
//
//------------------------------------------------------------------------
HRESULT CUrlAgent::GetOriginalIdentServer( LPTSTR lpsBuffer, int nBufferSize, BOOL* pfInternalServer /*= NULL*/) { HRESULT hr=S_OK;
if (NULL == lpsBuffer) { return E_INVALIDARG; }
nBufferSize/=sizeof(TCHAR);
if (nBufferSize <= lstrlen(m_pszOrigIdentUrl)) { return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); }
hr=StringCchCopyEx(lpsBuffer,nBufferSize,m_pszOrigIdentUrl,NULL,NULL,MISTSAFE_STRING_FLAGS); if( FAILED(hr) ) { return hr; }
if (NULL != pfInternalServer) { *pfInternalServer = m_fIdentFromPolicy; }
return S_OK; }
//------------------------------------------------------------------------
//
// get the ping/status server
// *** this API should be called after PopulateData() is called ***
//
//------------------------------------------------------------------------
HRESULT CUrlAgent::GetLivePingServer( LPTSTR lpsBuffer, int nBufferSize) {
HRESULT hr=S_OK;
if (!m_fPopulated) { return HRESULT_FROM_WIN32(ERROR_INVALID_DATA); }
if (NULL == lpsBuffer || 0 >= nBufferSize) { return E_INVALIDARG; }
nBufferSize/=sizeof(TCHAR);
if (NULL != m_pszInternetPingUrl && _T('\0') != *m_pszInternetPingUrl) { if (nBufferSize <= lstrlen(m_pszInternetPingUrl)) { return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); } else { hr=StringCchCopyEx(lpsBuffer,nBufferSize,m_pszInternetPingUrl,NULL,NULL,MISTSAFE_STRING_FLAGS); if(FAILED(hr)) return hr; } } else { *lpsBuffer = _T('\0'); } return S_OK; }
// *** this API can be called before PopulateData() is called ***
HRESULT CUrlAgent::GetCorpPingServer( LPTSTR lpsBuffer, int nBufferSize) { HRESULT hr=S_OK;
if (NULL == m_pszIntranetPingUrl) { return (E_OUTOFMEMORY); }
if (NULL == lpsBuffer || 0 >= nBufferSize) { return E_INVALIDARG; } nBufferSize/=sizeof(TCHAR);
if (NULL != m_pszIntranetPingUrl && _T('\0') != *m_pszIntranetPingUrl) { if (nBufferSize <= lstrlen(m_pszIntranetPingUrl)) { return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); } else {
hr=StringCchCopyEx(lpsBuffer,nBufferSize,m_pszIntranetPingUrl,NULL,NULL,MISTSAFE_STRING_FLAGS); if(FAILED(hr)) return hr; } } else { *lpsBuffer = _T('\0'); } return hr; }
//------------------------------------------------------------------------
//
// get the query server. this is per client based
// *** this API should be called after PopulateData() is called ***
//
//------------------------------------------------------------------------
HRESULT CUrlAgent::GetQueryServer( LPCTSTR lpsClientName, LPTSTR lpsBuffer, int nBufferSize, BOOL* pfInternalServer /*= NULL*/) { HRESULT hr=S_OK;
if (!m_fPopulated) { return HRESULT_FROM_WIN32(ERROR_INVALID_DATA); }
if (NULL == lpsClientName || NULL == lpsBuffer) { return E_INVALIDARG; }
nBufferSize/=sizeof(TCHAR);
for (int i = 0; i < m_nArrayUrlCount; i++) { if (StrCmpI(m_ArrayUrls[i].pszClientName, lpsClientName) == 0) { if (nBufferSize <= lstrlen(m_ArrayUrls[i].pszQueryServer)) { return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); } else { hr=StringCchCopyEx(lpsBuffer,nBufferSize,m_ArrayUrls[i].pszQueryServer,NULL,NULL,MISTSAFE_STRING_FLAGS); if(FAILED(hr)) return hr;
if (NULL != pfInternalServer) { *pfInternalServer = m_ArrayUrls[i].fInternalServer; } } return S_OK; } }
return ERROR_IU_QUERYSERVER_NOT_FOUND; }
//------------------------------------------------------------------------
//
// tell if a particular client is controlled by policy in corporate
// returns:
// S_OK = TRUE
// S_FALSE = FALSE
// other = error, so don't know
//
//------------------------------------------------------------------------
HRESULT CUrlAgent::IsClientSpecifiedByPolicy( LPCTSTR lpsClientName ) {
HRESULT hr=S_OK;
if (!m_fPopulated) { return HRESULT_FROM_WIN32(ERROR_INVALID_DATA); }
if (NULL == lpsClientName) { return E_INVALIDARG; }
for (int i = 0; i < m_nArrayUrlCount; i++) { if (StrCmpI(m_ArrayUrls[i].pszClientName, lpsClientName) == 0) { return (m_ArrayUrls[i].fInternalServer) ? S_OK : S_FALSE; } }
return S_FALSE; }
HRESULT CUrlAgent::IsIdentFromPolicy() { return TRUE == m_fIdentFromPolicy ? S_OK : S_FALSE; }
//------------------------------------------------------------------------
//
// private function, to clean up. called by destructor
//
//------------------------------------------------------------------------
void CUrlAgent::DesertData(void) { LOG_Block("CUrlAgent::DesertData");
if (NULL != m_ArrayUrls && m_nArrayUrlCount > 0) { for (int i = 0; i < m_nArrayUrlCount; i++) { SafeHeapFree(m_ArrayUrls[i].pszClientName); SafeHeapFree(m_ArrayUrls[i].pszQueryServer); } SafeHeapFree(m_ArrayUrls); m_nArrayUrlCount = 0; m_nArraySize = 0; }
SafeHeapFree(m_pszInternetPingUrl);
m_fPopulated = FALSE; }
//------------------------------------------------------------------------
//
// private function, retrieve string from ident
// allocated memory will be multiple of MAX_PATH long.
//
//------------------------------------------------------------------------
LPTSTR CUrlAgent::RetrieveIdentStrAlloc( LPCTSTR pSection, LPCTSTR pEntry, LPDWORD lpdwSizeAllocated, LPCTSTR lpszIdentFile) { LPTSTR pBuffer = NULL; DWORD dwSize = MAX_PATH; DWORD dwRet = 0; TCHAR szIdentFile[MAX_PATH + 1];
if (NULL == pSection || NULL == pEntry || NULL == lpszIdentFile) { return NULL; } //
// try to allocate buffer first
//
while (TRUE) { pBuffer = (LPTSTR) HeapAlloc(m_hProcHeap, HEAP_ZERO_MEMORY, sizeof(TCHAR) * dwSize); if (NULL == pBuffer) { break; }
dwRet = GetPrivateProfileString( pSection, pEntry, _T(""), pBuffer, dwSize, lpszIdentFile); if (dwSize - 1 != dwRet) { if ('\0' == pBuffer) { //
// no such data found from ident!
//
SafeHeapFree(pBuffer); } //
// we are done!
//
break; } //
// assume it's buffer too small
//
SafeHeapFree(pBuffer); dwSize += MAX_PATH; // increase by 255
}
if (NULL != lpdwSizeAllocated) { *lpdwSizeAllocated = dwSize; }
return pBuffer; }
//------------------------------------------------------------------------
//
// helper function
// if there is no empty slot, double the size of url array
//
//------------------------------------------------------------------------
HRESULT CUrlAgent::ExpandArrayIfNeeded(void) { HRESULT hr = S_OK; LOG_Block("CUrlAgent::ExpandArrayIfNeeded()");
if (m_nArrayUrlCount >= m_nArraySize) { //
// we have used up all data slots. need to expand array
//
m_nArraySize *= 2; PServerPerClient pNewArray = (PServerPerClient) HeapAlloc(m_hProcHeap, HEAP_ZERO_MEMORY, m_nArraySize * sizeof(ServerPerClient)); if (NULL == pNewArray) { m_nArraySize /= 2; // shrink it back
SetHrMsgAndGotoCleanUp(E_OUTOFMEMORY); } //
// copy old data to this new array
//
for (int i = 0; i < m_nArrayUrlCount; i++) { pNewArray[i] = m_ArrayUrls[i]; }
HeapFree(m_hProcHeap, 0, m_ArrayUrls); m_ArrayUrls = pNewArray; } CleanUp: return hr; }
// *********************************************************************
//
// begin of derived class implementation
//
// *********************************************************************
CIUUrlAgent::CIUUrlAgent() : m_fIUPopulated(FALSE), m_pszSelfUpdateUrl(NULL) { if (m_fIdentFromPolicy) { //
// since we found wu server, set selfupdate url to it
//
m_pszSelfUpdateUrl = (LPTSTR) HeapAlloc( m_hProcHeap, HEAP_ZERO_MEMORY, sizeof(TCHAR) * m_nOrigIdentUrlBufSize); if (NULL != m_pszSelfUpdateUrl) { //No check is made for the return value since this is a constructor and failure codes cannot be returned
StringCchCopyEx(m_pszSelfUpdateUrl,m_nOrigIdentUrlBufSize,m_pszOrigIdentUrl,NULL,NULL,MISTSAFE_STRING_FLAGS);
} } }
CIUUrlAgent::~CIUUrlAgent() { m_fIUPopulated = FALSE; SafeHeapFree(m_pszSelfUpdateUrl); }
//------------------------------------------------------------------------
//
// PopulateData():
// Do base class PopulateData() and then populate self-update url
//
//------------------------------------------------------------------------
HRESULT CIUUrlAgent::PopulateData(void) { LOG_Block("CIUUrlAgent::PopulateData");
if (m_fIUPopulated) return S_OK;
HRESULT hr = ((CUrlAgent*)this)->PopulateData(); if (FAILED(hr)) return hr;
//
// we need to populate the self-update url from iuident if wu server is not present
//
if (!m_fIdentFromPolicy) { if (NULL == m_hProcHeap) { return E_FAIL; }
TCHAR szBaseServerUrl[INTERNET_MAX_URL_LENGTH]; TCHAR szSelfUpdateStructure[MAX_PATH]; TCHAR szServerDirectory[MAX_PATH] = { '\0' }; TCHAR szLocalPath[MAX_PATH]; TCHAR szValue[MAX_PATH]; LPTSTR pszWalk = NULL, pszDelim = NULL; TCHAR szIdentBuffer[MAX_PATH + 1]; TCHAR szIdentFile[MAX_PATH + 1];
GetIndustryUpdateDirectory(szIdentBuffer);
hr=PathCchCombine(szIdentFile,ARRAYSIZE(szIdentFile),szIdentBuffer, IDENTTXT); if(FAILED(hr)) { LOG_ErrorMsg(hr); return hr; } m_pszSelfUpdateUrl = (LPTSTR) HeapAlloc( m_hProcHeap, HEAP_ZERO_MEMORY, sizeof(TCHAR) * INTERNET_MAX_URL_LENGTH); CleanUpFailedAllocSetHrMsg(m_pszSelfUpdateUrl);
// Get SelfUpdate Server URL
GetPrivateProfileString(m_fIsBetaMode ? IDENT_IUBETASELFUPDATE : IDENT_IUSELFUPDATE, IDENT_ENTRY_SERVERURL, _T(""), szBaseServerUrl, ARRAYSIZE(szBaseServerUrl), szIdentFile);
if ('\0' == szBaseServerUrl[0]) { // no URL specified in iuident..
LOG_ErrorMsg(ERROR_IU_SELFUPDSERVER_NOT_FOUND); hr = ERROR_IU_SELFUPDSERVER_NOT_FOUND; goto CleanUp; }
// Get SelfUpdate Structure Key
// ARCH|LOCALE
GetPrivateProfileString(m_fIsBetaMode ? IDENT_IUBETASELFUPDATE : IDENT_IUSELFUPDATE, IDENT_STRUCTUREKEY, _T(""), szSelfUpdateStructure, ARRAYSIZE(szSelfUpdateStructure), szIdentFile);
if ('\0' == szSelfUpdateStructure[0]) { // no SelfUpdate Structure in iudent
LOG_ErrorMsg(ERROR_IU_SELFUPDSERVER_NOT_FOUND); hr = ERROR_IU_SELFUPDSERVER_NOT_FOUND; goto CleanUp; }
// Parse the SelfUpdate Structure Key for Value Names to Read
// Initially we will only have an ARCH key..
pszWalk = szSelfUpdateStructure; while (NULL != (pszDelim = StrChr(pszWalk, '|'))) { *pszDelim = '\0';
if (0 == StrCmpI(pszWalk, IDENT_ARCH)) { #ifdef _IA64_
GetPrivateProfileString(IDENT_IUARCH, IDENT_IA64, _T(""), szValue, ARRAYSIZE(szValue), szIdentFile); #else
GetPrivateProfileString(IDENT_IUARCH, IDENT_X86, _T(""), szValue, ARRAYSIZE(szValue), szIdentFile); #endif
} else if (0 == StrCmpI(pszWalk, IDENT_OS)) { // Get the Current OS String
GetIdentPlatformString(szLocalPath, ARRAYSIZE(szLocalPath)); if ('\0' == szLocalPath[0]) { LOG_ErrorMsg(ERROR_IU_SELFUPDSERVER_NOT_FOUND); hr = ERROR_IU_SELFUPDSERVER_NOT_FOUND; goto CleanUp; } GetPrivateProfileString(IDENT_IUOS, szLocalPath, _T(""), szValue, ARRAYSIZE(szValue), szIdentFile); } else if (0 == StrCmpI(pszWalk, IDENT_LOCALE)) { // Get the Current Locale String
GetIdentLocaleString(szLocalPath, ARRAYSIZE(szLocalPath)); if ('\0' == szLocalPath[0]) { LOG_ErrorMsg(ERROR_IU_SELFUPDSERVER_NOT_FOUND); hr = ERROR_IU_SELFUPDSERVER_NOT_FOUND; goto CleanUp; } GetPrivateProfileString(IDENT_IULOCALE, szLocalPath, _T(""), szValue, ARRAYSIZE(szValue), szIdentFile); } else if (0 == StrCmpI(pszWalk, IDENT_CHARTYPE)) { #ifdef UNICODE
GetPrivateProfileString(IDENT_IUCHARTYPE, IDENT_UNICODE, _T(""), szValue, ARRAYSIZE(szValue), szIdentFile); #else
GetPrivateProfileString(IDENT_IUCHARTYPE, IDENT_ANSI, _T(""), szValue, ARRAYSIZE(szValue), szIdentFile); #endif
} else { LOG_Internet(_T("Found Unrecognized Token in SelfUpdate Structure String: Token was: %s"), pszWalk); pszWalk += lstrlen(pszWalk) + 1; // skip the previous token, and go to the next one in the string.
*pszDelim = '|'; continue; }
if ('\0' != szValue[0]) {
CleanUpIfFailedAndSetHrMsg(StringCchCatEx(szServerDirectory,ARRAYSIZE(szServerDirectory),szValue,NULL,NULL,MISTSAFE_STRING_FLAGS)); } pszWalk += lstrlen(pszWalk) + 1; // skip the previous token, and go to the next one in the string.
*pszDelim = '|'; }
CleanUpIfFailedAndSetHrMsg(StringCchCatEx(szServerDirectory,ARRAYSIZE(szServerDirectory),SLASHENGINECAB,NULL,NULL,MISTSAFE_STRING_FLAGS));
if ('/' == szServerDirectory[0]) { pszWalk = CharNext(szServerDirectory); } else { pszWalk = szServerDirectory; }
DWORD dwSize = INTERNET_MAX_URL_LENGTH; UrlCombine(szBaseServerUrl, pszWalk, m_pszSelfUpdateUrl, &dwSize, 0); }
CleanUp:
if (SUCCEEDED(hr)) { m_fIUPopulated = TRUE; }
return hr; }
//------------------------------------------------------------------------
//
// get the self-update server.
// *** this API should be called after PopulateData() is called ***
//
//------------------------------------------------------------------------
HRESULT CIUUrlAgent::GetSelfUpdateServer( LPTSTR lpsBuffer, int nBufferSize, BOOL* pfInternalServer /*= NULL*/) {
HRESULT hr=S_OK;
if (!m_fIUPopulated) { return HRESULT_FROM_WIN32(ERROR_INVALID_DATA); }
if (NULL == m_pszSelfUpdateUrl) { return (E_OUTOFMEMORY); }
if (NULL == lpsBuffer) { return E_INVALIDARG; }
nBufferSize/=sizeof(TCHAR); if (nBufferSize <= lstrlen(m_pszSelfUpdateUrl)) { return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); }
hr=StringCchCopyEx(lpsBuffer,nBufferSize,m_pszSelfUpdateUrl,NULL,NULL,MISTSAFE_STRING_FLAGS);
if(FAILED(hr)) return hr;
if (NULL != pfInternalServer) { *pfInternalServer = m_fIdentFromPolicy; } return hr; }
|