Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

1126 lines
36 KiB

#include "wsdueng.h"
#define IDENT_SECTION_CABPOOL "cabpools"
#define IDENT_SECTION_CONTENT31 "content31"
#define IDENT_KEYNAME_DEFAULT "default"
#define IDENT_KEYNAME_ROOT "root"
CV31Server::CV31Server(CDynamicUpdate *pDu) : m_puidConsumerCatalog(0),
m_puidSetupCatalog(0),
m_dwPlatformID(0),
m_lcidLocaleID(0),
m_dwConsumerItemCount(0),
m_pConsumerCatalog(NULL),
m_dwSetupItemCount(0),
m_pSetupCatalog(NULL),
m_dwGlobalExclusionItemCount(0),
m_pDu(pDu)
{
// set the initial state
m_dwPlatformID = (DWORD)m_pDu->m_iPlatformID;
m_lcidLocaleID = m_pDu->m_lcidLocaleID;
if (0 == m_pDu->m_wPlatformSKU) // Professional
{
m_enumPlatformSKU = enWhistlerProfessional;
}
else if (m_pDu->m_wPlatformSKU & VER_SUITE_DATACENTER) // DataCenter
{
m_enumPlatformSKU = enWhistlerDataCenter;
}
else if (m_pDu->m_wPlatformSKU & VER_SUITE_PERSONAL) // Personal
{
m_enumPlatformSKU = enWhistlerConsumer;
}
else if (m_pDu->m_wPlatformSKU & VER_SUITE_ENTERPRISE) // Advanced Server
{
m_enumPlatformSKU = enWhistlerAdvancedServer;
}
else if (m_pDu->m_wPlatformSKU & VER_SUITE_SMALLBUSINESS) // Server
{
m_enumPlatformSKU = enWhistlerServer;
}
// RogerJ October 25th, 2000
m_pValidDependentPUIDArray = NULL;
m_nNumOfValidDependentPUID = 0;
m_pBitMaskAS = m_pBitMaskCDM = NULL;
m_fHasDriver = FALSE;
m_pszExcludedDriver = NULL;
}
CV31Server::~CV31Server()
{
FreeCatalogs(); // clears the m_pConsumerItems and m_pSetupItems Varrays.
SafeGlobalFree(m_pConsumerCatalog);
SafeGlobalFree(m_pSetupCatalog);
// RogerJ, October 25th, 2000
SafeGlobalFree(m_pValidDependentPUIDArray);
SafeGlobalFree(m_pBitMaskAS);
SafeGlobalFree(m_pBitMaskCDM);
SafeGlobalFree(m_pszExcludedDriver);
}
// ----------------------------------------------------------------------------------
// V3.1 Backend Server Apis
//
//
BOOL CV31Server::ReadIdentInfo()
{
// ident.cab should already be downloaded at this point. Get the path to it and read the fields we care about
char szIdent[MAX_PATH];
char szValueName[32];
int iServerNumber;
char szUrl[INTERNET_MAX_URL_LENGTH + 1];
PathCombine(szIdent, m_pDu->GetDuTempPath(), "ident.txt");
// --------------------
// Get the CABPOOL URL
// --------------------
iServerNumber = GetPrivateProfileInt(IDENT_SECTION_CABPOOL, IDENT_KEYNAME_DEFAULT, 1, szIdent);
wsprintf(szValueName, "Server%d", iServerNumber);
GetPrivateProfileString(IDENT_SECTION_CABPOOL, szValueName, "", szUrl, sizeof(szUrl), szIdent);
if ('\0' == szUrl[0])
{
// No Server Value was found in the ident. Cannot continue;
SetLastError(ERROR_FILE_NOT_FOUND);
return FALSE;
}
// The cabpool URL is the string in the Ident + 'cabpool'
m_pDu->DuUrlCombine(m_szCabPoolUrl, szUrl, "CabPool");
// --------------------
// Get the CONTENT URL
// --------------------
iServerNumber = GetPrivateProfileInt(IDENT_SECTION_CONTENT31, IDENT_KEYNAME_DEFAULT, 1, szIdent);
wsprintf(szValueName, "Server%d", iServerNumber);
GetPrivateProfileString(IDENT_SECTION_CONTENT31, szValueName, "", szUrl, sizeof(szUrl), szIdent);
if ('\0' == szUrl[0])
{
// No Server Value
SetLastError(ERROR_FILE_NOT_FOUND);
return FALSE;
}
lstrcpy(m_szV31ContentUrl, szUrl);
// -------------------------
// Get the CONTENT ROOT URL
// -------------------------
iServerNumber = GetPrivateProfileInt(IDENT_SECTION_CONTENT31, IDENT_KEYNAME_ROOT, 2, szIdent);
wsprintf(szValueName, "Server%d", iServerNumber);
GetPrivateProfileString(IDENT_SECTION_CONTENT31, szValueName, "", szUrl, sizeof(szUrl), szIdent);
if ('\0' == szUrl[0])
{
// No Root Server Value
SetLastError(ERROR_FILE_NOT_FOUND);
return FALSE;
}
lstrcpy(m_szV31RootUrl, szUrl);
return TRUE;
}
BOOL CV31Server::ReadCatalogINI()
{
LOG_block("CV31Server::ReadCatalogINI()");
char szServerFile[INTERNET_MAX_URL_LENGTH + 1];
char szLocalFile[MAX_PATH];
char szValue[1024];
// Now read the Catalog.ini file to find out if any of these items needs to be turned off
m_pDu->DuUrlCombine(szServerFile, m_szV31ContentUrl, CATALOGINIFN);
PathCombineA(szLocalFile, m_pDu->GetDuTempPath(), CATALOGINIFN);
if (ERROR_SUCCESS != m_pDu->DownloadFile(szServerFile, szLocalFile, FALSE, FALSE))
{
LOG_out("No catalog.ini found");
return TRUE;
}
if (0 != (GetPrivateProfileStringA("exclude", "puids", "", szValue, sizeof(szValue), szLocalFile)))
{
LPCSTR pszNext = szValue;
char szPuid[128];
while (NULL != pszNext)
{
pszNext = strcpystr(pszNext, ",", szPuid);
if ('\0' != szPuid[0])
{
m_GlobalExclusionArray[m_dwGlobalExclusionItemCount] = StrToIntA(szPuid);
LOG_out("Excluded puid --- %d", m_GlobalExclusionArray[m_dwGlobalExclusionItemCount]);
m_dwGlobalExclusionItemCount++;
}
}
}
else
LOG_out("No Excluded puid");
return TRUE;
}
BOOL CV31Server::GetCatalogPUIDs()
{
LOG_block("CV31Server::GetCatalogPUIDs()");
// There are two v3 catalogs that we will be looking for the PUID's for..
// One is the Consumer Catalog for the target platform
// The other is the Setup Catalog for the target platform
char szServerFile[INTERNET_MAX_URL_LENGTH];
PBYTE pCatalogList = NULL;
PBYTE pInventoryList = NULL;
PBYTE pWalkList = NULL;
DWORD dwLength;
m_puidConsumerCatalog = 0;
m_puidSetupCatalog = 0;
// Download the Catalog Inventory List
m_pDu->DuUrlCombine(szServerFile, m_szV31ContentUrl, "inventory.plt");
m_pDu->DownloadFileToMem(szServerFile, &pInventoryList, &dwLength, TRUE, "inventory.plt", NULL);
if (NULL == pInventoryList)
{
// error out of memory
return FALSE;
}
// Download the CatalogList
m_pDu->DuUrlCombine(szServerFile, m_szV31ContentUrl, "inventory.cat");
m_pDu->DownloadFileToMem(szServerFile, &pCatalogList, &dwLength, TRUE, "inventory.cat", NULL);
if (NULL == pCatalogList)
{
// error out of memory
SafeGlobalFree(pInventoryList);
return FALSE;
}
// Now Parse the Inventory List to Find out how many catalogs there are.
int i;
WU_CATALOG_HEADER hdr;
memcpy(&hdr, pInventoryList, sizeof(hdr));
pWalkList = pCatalogList;
CATALOGLIST catListElem;
for (i = 0; i < hdr.totalItems; i++)
{
memcpy(&catListElem, pWalkList, sizeof(catListElem));
if (catListElem.dwPlatform == m_dwPlatformID)
{
// standard catalog is 0, thus, standard catalog with driver will have same value as driver only
if ((CATLIST_DRIVERSPRESENT == catListElem.dwFlags) || (catListElem.dwFlags == (CATLIST_DRIVERSPRESENT | CATLIST_64BIT)))
{
// consumer catalog for this platform
m_puidConsumerCatalog = catListElem.dwCatPuid;
}
else if (catListElem.dwFlags & CATLIST_SETUP)
{
// setup catalog for this platform
m_puidSetupCatalog = catListElem.dwCatPuid;
if (0 == m_puidConsumerCatalog && (catListElem.dwFlags & CATLIST_DRIVERSPRESENT))
m_puidConsumerCatalog = catListElem.dwCatPuid;
}
}
pWalkList += sizeof(catListElem);
}
if (!m_puidConsumerCatalog && ! m_puidSetupCatalog)
{
SetLastError(ERROR_INTERNET_NO_CONTEXT);
SafeGlobalFree(pInventoryList);
SafeGlobalFree(pCatalogList);
return FALSE; // this technically is an error.. wrong server was pointed to? Catalogs weren't on the server
}
SafeGlobalFree(pInventoryList);
SafeGlobalFree(pCatalogList);
LOG_out("Consumer catalog %d, Setup catalog %d", m_puidConsumerCatalog, m_puidSetupCatalog);
return TRUE;
}
BOOL CV31Server::GetCatalogs()
{
// This will download the two Catalogs (Setup and Consumer) and the InventoryItem Arrays
LOG_block("CV31Server::GetCatalogs()");
DWORD dwRet;
int i;
char szServerFile[INTERNET_MAX_URL_LENGTH];
char szLocalFile[MAX_PATH];
char szCatalog[MAX_PATH];
char szInvCRC[64];
char szBmCRC[64];
char szLocale[32];
PBYTE pWalkCatalog = NULL;
WU_CATALOG_HEADER hdr;
PINVENTORY_ITEM pItem;
BOOL fDriversAvailable = FALSE;
DWORD dwLength;
wsprintf(szLocale, "0x%8.8x", m_lcidLocaleID);
FreeCatalogs(); // free any previously allocated catalog lists
SafeGlobalFree(m_pValidDependentPUIDArray); // free any previously determined dependency list
m_pValidDependentPUIDArray = NULL;
m_nNumOfValidDependentPUID = 0;
// Read the Catalog.INI to get a list of Globally Excluded Items
if (0 != m_puidConsumerCatalog)
{
// Download the Consumer Catalog for this Platform
// first we need to download the redirect file to get the CRC value of the catalog
wsprintf(szCatalog, "%d/%s.as", m_puidConsumerCatalog, szLocale);
m_pDu->DuUrlCombine(szServerFile, m_szV31ContentUrl, szCatalog);
wsprintf(szCatalog, "%d_%s.as", m_puidConsumerCatalog, szLocale);
PathCombine(szLocalFile, m_pDu->GetDuTempPath(), szCatalog);
m_pDu->DownloadFile(szServerFile, szLocalFile, TRUE, FALSE);
if (GetPrivateProfileString("redir", "invCRC", "", szInvCRC, sizeof(szInvCRC), szLocalFile) == 0)
{
LOG_error("Unable to Read Inventory CRC value from Consumer Catalog");
return FALSE;
}
// does not need this for consumer catalog
/*if (GetPrivateProfileString("redir", "bmCRC", "", szBmCRC, sizeof(szBmCRC), szLocalFile) == 0)
{
LOG_error("Unable to Read Bitmask CRC value for Consumer Catalog");
return FALSE;
}*/
if (!GetBitMask("bitmask.cdm", m_puidConsumerCatalog, &m_pBitMaskCDM, "bitmask.cdm"))
{
LOG_error("Unable to get bitmask for CDM");
return FALSE;
}
// now download the real catalog
wsprintf(szCatalog, "%d/%s.inv", m_puidConsumerCatalog, szInvCRC);
m_pDu->DuUrlCombine(szServerFile, m_szV31ContentUrl, szCatalog);
SafeGlobalFree(m_pConsumerCatalog);
wsprintf(szCatalog, "%s.inv", szInvCRC);
m_pDu->DownloadFileToMem(szServerFile, &m_pConsumerCatalog, &dwLength, TRUE, szCatalog, "inventory.as");
if (NULL == m_pConsumerCatalog)
{
LOG_error("Failed to download Consumer Catalog, %d", m_puidConsumerCatalog);
return FALSE;
}
pWalkCatalog = m_pConsumerCatalog;
// Read the Catalog Header
ZeroMemory(&hdr, sizeof(hdr));
memcpy(&hdr, pWalkCatalog, sizeof(hdr));
m_pConsumerItems[hdr.totalItems] = NULL; // just to preinitialize the array.
pWalkCatalog += sizeof(hdr);
// walk the list and read the items.
for (i = 0; i < hdr.totalItems; i++)
{
pItem = (PINVENTORY_ITEM) GlobalAlloc(GMEM_ZEROINIT, sizeof(INVENTORY_ITEM));
if (NULL == pItem)
{
dwRet = GetLastError();
LOG_error("Failed to Alloc Memory for Inventory Item, Error %d", dwRet);
return FALSE;
}
pWalkCatalog = GetNextRecord(pWalkCatalog, i, pItem);
if (!pWalkCatalog)
{
LOG_error("Failed to Alloc Memory for InventoryI Item State, Error %d", GetLastError());
return FALSE;
}
m_pConsumerItems[i] = pItem;
if ( WU_TYPE_CDM_RECORD_PLACE_HOLDER == pItem->recordType) m_fHasDriver = TRUE;
m_dwConsumerItemCount++;
}
}
if (0 != m_puidSetupCatalog)
{
// Download the Setup Catalog for this Platform
// first we need to download the redirect file to get the CRC value of the catalog
wsprintf(szCatalog, "%d/%s.as", m_puidSetupCatalog, szLocale);
m_pDu->DuUrlCombine(szServerFile, m_szV31ContentUrl, szCatalog);
wsprintf(szCatalog, "%d_%s.as", m_puidSetupCatalog, szLocale);
PathCombine(szLocalFile, m_pDu->GetDuTempPath(), szCatalog);
dwRet = m_pDu->DownloadFile(szServerFile, szLocalFile, TRUE, FALSE);
if (ERROR_SUCCESS != dwRet)
{
SetLastError(dwRet);
return FALSE;
}
if (GetPrivateProfileString("redir", "invCRC", "", szInvCRC, sizeof(szInvCRC), szLocalFile) == 0)
{
LOG_error("Unable to Read Inventory CRC value from Setup Catalog");
return FALSE;
}
if (GetPrivateProfileString("redir", "bmCRC", "", szBmCRC, sizeof(szBmCRC), szLocalFile) == 0)
{
LOG_error("Unable to Read Bitmask CRC value for Setup Catalog");
return FALSE;
}
char szBMCRCFileName[MAX_PATH];
wsprintf(szBMCRCFileName, "%s.bm", szBmCRC);
if (!GetBitMask(szBMCRCFileName, m_puidSetupCatalog, &m_pBitMaskAS, "bitmask.as"))
{
LOG_error("Unable to Read Bitmask File for AS");
return FALSE;
}
// now download the real catalog
wsprintf(szCatalog, "%d/%s.inv", m_puidSetupCatalog, szInvCRC);
m_pDu->DuUrlCombine(szServerFile, m_szV31ContentUrl, szCatalog);
SafeGlobalFree(m_pSetupCatalog);
wsprintf(szCatalog, "%s.inv", szInvCRC);
m_pDu->DownloadFileToMem(szServerFile, &m_pSetupCatalog, &dwLength, TRUE, szCatalog, "inventory.as");
if (NULL == m_pSetupCatalog)
{
LOG_error("Failed to download Consumer Catalog, %d", m_puidSetupCatalog);
return FALSE;
}
pWalkCatalog = m_pSetupCatalog;
// Read the Catalog Header
ZeroMemory(&hdr, sizeof(hdr));
memcpy(&hdr, pWalkCatalog, sizeof(hdr));
m_pSetupItems[hdr.totalItems] = NULL; // just to preinitialize the array.
pWalkCatalog += sizeof(hdr);
// walk the list and read the items.
for (i = 0; i < hdr.totalItems; i++)
{
pItem = (PINVENTORY_ITEM) GlobalAlloc(GMEM_ZEROINIT, sizeof(INVENTORY_ITEM));
if (NULL == pItem)
{
dwRet = GetLastError();
LOG_error("Failed to Alloc Memory for Inventory Item, Error %d", dwRet);
return FALSE;
}
pWalkCatalog = GetNextRecord(pWalkCatalog, i, pItem);
if (!pWalkCatalog)
{
LOG_error("Failed to Alloc Memory for InventoryI Item State, Error %d", GetLastError());
return FALSE;
}
if (!pItem->ps->bHidden && !GETBIT(m_pBitMaskAS, i))
{
// this item is masked out
LOG_out("Item %d is masked out", i);
pItem->ps->bHidden = TRUE;
pItem->ps->state = WU_ITEM_STATE_PRUNED;
pItem->ps->dwReason = WU_STATE_REASON_BITMASK;
}
m_pSetupItems[i] = pItem;
m_dwSetupItemCount++;
}
}
return TRUE;
}
PBYTE CV31Server::GetNextRecord(PBYTE pRecord, int iBitmaskIndex, PINVENTORY_ITEM pItem)
{
//first get the fixed length part of the record
pItem->pf = (PWU_INV_FIXED)pRecord;
//process the variable part of the record
pRecord = pRecord + sizeof(WU_INV_FIXED);
pItem->pv = (PWU_VARIABLE_FIELD)pRecord;
//since there is no state information create an empty structure
pItem->ps = (PWU_INV_STATE)GlobalAlloc(GMEM_ZEROINIT, sizeof(WU_INV_STATE));
if (!pItem->ps) return NULL;
//new item is unknown detection, not selected and shown to user.
pItem->ps->state = WU_ITEM_STATE_UNKNOWN;
pItem->ps->bChecked = FALSE;
// RogerJ, to support versioning, we will use the bHidden flag
pItem->ps->bHidden = pItem->pf->a.flags & WU_HIDDEN_ITEM_FLAG;
if (pItem->ps->bHidden) m_nNumOfValidDependentPUID++;
pItem->ps->dwReason = WU_STATE_REASON_NONE;
//There is no description yet
pItem->pd = (PWU_DESCRIPTION)NULL;
//we need to store the bitmap index (which is the sequential record index)
//since this information will be lost when we add the driver records.
// YanL: is not being used
// pItem->bitmaskIndex = iBitmaskIndex;
//Get record type
pItem->recordType = (BYTE)GetRecordType(pItem);
pItem->ndxLinkInstall = (PUID) pItem->pf->a.installLink;
//set record pointer to the beginning of the next record
pRecord += pItem->pv->GetSize();
return pRecord;
}
int CV31Server::GetRecordType(PINVENTORY_ITEM pItem)
{
GUID driverRecordId = WU_GUID_DRIVER_RECORD;
int iRecordType = 0;
if ( memcmp((void *)&pItem->pf->d.g, (void *)&driverRecordId, sizeof(WU_GUID_DRIVER_RECORD)) )
{
//if the GUID field is not 0 then we have an active setup record.
iRecordType = WU_TYPE_ACTIVE_SETUP_RECORD;//active setup record type
}
else
{
//else this is either a driver record place holder or a section - sub section
//record. So we need to check the type field
if ( pItem->pf->d.type == SECTION_RECORD_TYPE_DEVICE_DRIVER_INSERTION )
{
//cdm driver place holder record
iRecordType = WU_TYPE_CDM_RECORD_PLACE_HOLDER; //cdm code download manager place holder record
}
else if ( pItem->pf->d.type == SECTION_RECORD_TYPE_PRINTER )
{
//Note: We may need to use this to support printers on win 98.
iRecordType = WU_TYPE_RECORD_TYPE_PRINTER; //printer record
}
else if ( pItem->pf->d.type == SECTION_RECORD_TYPE_DRIVER_RECORD )
{
iRecordType = WU_TYPE_CDM_RECORD; //Corporate catalog device driver
}
else if ( pItem->pf->s.type == SECTION_RECORD_TYPE_CATALOG_RECORD )
{
iRecordType = WU_TYPE_CATALOG_RECORD;
}
else
{
//we have either a section, sub section or sub sub section record
switch ( pItem->pf->s.level )
{
case 0:
iRecordType = WU_TYPE_SECTION_RECORD;
break;
case 1:
iRecordType = WU_TYPE_SUBSECTION_RECORD;
break;
case 2:
iRecordType = WU_TYPE_SUBSUBSECTION_RECORD;
break;
}
}
}
return iRecordType;
}
// --------------------------------------------------------------------------
// CV31Server::UpdateDownloadItemList()
//
// Parses the Catalogs and gets a list of Items in the Correct Platform SKU
// section to download.
//
//
// --------------------------------------------------------------------------
BOOL CV31Server::UpdateDownloadItemList(OSVERSIONINFOEX& VersionInfo)
{
LOG_block("CV31Server::UpdateDownloadItemList()");
ULONG ulItem = 0;
int iRecordType = 0;
BOOL fFound = FALSE, fRet;
char szServerFile[INTERNET_MAX_URL_LENGTH + 1];
char szMapFileName[MAX_PATH];
char szLocale[32];
DWORD dwLength;
PBYTE pMapMem = NULL;
PWU_VARIABLE_FIELD pvCabs;
PWU_VARIABLE_FIELD pvCRCs;
int iCabNum = 0;
BOOL fRetValue = TRUE;
wsprintf(szLocale, "0x%8.8x", m_lcidLocaleID);
wsprintf(szMapFileName, "%d_%s.des", m_dwPlatformID, szLocale);
m_pDu->DuUrlCombine(szServerFile, m_szV31ContentUrl, szMapFileName);
m_pDu->DownloadFileToMem(szServerFile, &pMapMem, &dwLength, TRUE, szMapFileName, NULL);
if (NULL == pMapMem)
{
LOG_error("Failed to Download CRC Map File %s", szServerFile);
return FALSE;
}
CCRCMapFile DescMap(pMapMem, dwLength);
// Before we add any items to the download list we need to clear the download list
// from any previous calls to DoDetection.
m_pDu->EnterDownloadListCriticalSection(); // if we're downloading we don't want to allow the download list to change
m_pDu->ClearDownloadItemList();
if (0 != m_dwSetupItemCount)
{
// We have a valid Setup Catalog, find the Correct Section based on SKU
// ROGERJ, october 24, 2000
// we need to make a list of valid dependency item first
if (!MakeDependentList(VersionInfo, &DescMap))
{
// last error will be set by MakeDependentList() function
fRetValue = FALSE;
goto ReturnPoint;
}
// We want to walk the Catalog Looking for the Section PUID that matches our requested Platform SKU
for (ulItem = 0; ulItem < m_dwSetupItemCount; ulItem++)
{
if (WU_TYPE_SECTION_RECORD == m_pSetupItems[ulItem]->recordType)
{
if (m_pSetupItems[ulItem]->pf->s.puid == m_enumPlatformSKU)
{
// found the correct section
fFound = TRUE;
break;
}
}
}
if (fFound)
{
ulItem++; // advance to the next item
// until we find the next section, or the end of the catalog
while ((ulItem < m_dwSetupItemCount) && (WU_TYPE_SECTION_RECORD != GetRecordType(m_pSetupItems[ulItem])))
{
PINVENTORY_ITEM pItem = m_pSetupItems[ulItem];
// ROGERJ, October 24th, 2000 --- determine if the item is applied to this version
// skip hidden item
if (pItem->ps->bHidden)
{
ulItem++;
continue;
}
// determine if this item valid on this build
if ( 0 != pItem->pf->a.installLink && // has dependency
!IsDependencyApply(pItem->pf->a.installLink)) // dependency not apply to this version
{
// if the dependency item is not valid in this version, skip
ulItem++;
continue;
}
char szServerCab[128];
char szLocalCab[128];
// The next section record marks the end of the items valid for this SKU
fRet = ReadDescription(pItem, &DescMap);
if (!fRet)
{
// failed to read description file for this item, skip it.
ulItem++;
continue;
}
pvCabs = pItem->pd->pv->Find(WU_DESCRIPTION_CABFILENAME);
pvCRCs = pItem->pd->pv->Find(WU_DESC_CRC_ARRAY);
if ((NULL == pvCabs) || (NULL == pvCRCs))
{
// no cab list or CRC list in the description file
ulItem++;
continue;
}
DOWNLOADITEM *pDownloadItem = (DOWNLOADITEM *)GlobalAlloc(GMEM_ZEROINIT, sizeof(DOWNLOADITEM));
if (NULL == pDownloadItem)
{
LOG_error("Error Allocating Memory for new Download Item");
fRetValue = FALSE;
goto ReturnPoint;
}
pDownloadItem->dwTotalFileSize = pItem->pd->size * 1024; // Estimated Size in Bytes
pDownloadItem->puid = pItem->pf->a.puid;
LPSTR pszCabName = pDownloadItem->mszFileList;
iCabNum = 0;
for (;;)
{
if (FAILED(GetCRCNameFromList(iCabNum, pvCabs->pData, pvCRCs->pData, szServerCab, sizeof(szServerCab), szLocalCab)))
{
break; // no more cabs
}
pDownloadItem->iNumberOfCabs++;
lstrcpy(pszCabName, szServerCab);
pszCabName += lstrlen(pszCabName) + 1;
*pszCabName = '\0'; // double null terminate
pszCabName++; // next cab
iCabNum++;
}
// don't add the item unless there are cabs for it.
if (pDownloadItem->iNumberOfCabs > 0 && !IsPUIDExcluded(pItem->pf->a.puid))
// before adding this item to the list, check to see if it should be excluded based
// on the Catalog.INI
m_pDu->AddDownloadItemToList(pDownloadItem);
SafeGlobalFree(pItem->pd);
ulItem++;
}
}
}
ReturnPoint:
m_pDu->LeaveDownloadListCriticalSection();
SafeGlobalFree(pMapMem);
return fRetValue;
}
BOOL CV31Server::ReadDescription(PINVENTORY_ITEM pItem, CCRCMapFile *pMapFile)
{
if ((NULL == pItem) || (NULL == pMapFile))
{
return FALSE;
}
LOG_block("CV31Server::ReadDescription()");
char szServerFile[INTERNET_MAX_URL_LENGTH + 1];
char szDownloadFile[MAX_PATH];
PWU_DESCRIPTION pd;
DWORD dwLength;
char szBase[64];
char szCRCName[64];
HRESULT hr = S_OK;
wsprintf(szBase, "%d.des", pItem->GetPuid());
hr = pMapFile->GetCRCName((DWORD)pItem->GetPuid(), szBase, szCRCName, sizeof(szCRCName));
if (FAILED(hr))
{
LOG_error("Failed to get CRC Description Value for Item %d", pItem->GetPuid());
return FALSE;
}
wsprintf(szDownloadFile, "CRCDesc/%s", szCRCName);
m_pDu->DuUrlCombine(szServerFile, m_szV31RootUrl, szDownloadFile);
m_pDu->DownloadFileToMem(szServerFile, (PBYTE *)&pd, &dwLength, TRUE, szCRCName, "desc.as");
if (NULL == pd)
{
LOG_error("Failed to download Description File %s", szServerFile);
return FALSE;
}
// for 64 bit, the description is off by size of DWORD
//if (19 == m_pDu->m_iPlatformID)
// 64 bit
// pd->pv = (PWU_VARIABLE_FIELD)(((PBYTE)pd) + sizeof(WU_DESCRIPTION) + sizeof(DWORD));
//else
// 32 bit
pd->pv = (PWU_VARIABLE_FIELD)(((PBYTE)pd) + sizeof(WU_DESCRIPTION));
pItem->pd = pd;
return TRUE;
}
void CV31Server::FreeCatalogs()
{
for (DWORD dwcnt = 0; dwcnt < m_dwSetupItemCount; dwcnt++)
{
if (m_pSetupItems[dwcnt])
{
SafeGlobalFree(m_pSetupItems[dwcnt]->ps);
SafeGlobalFree(m_pSetupItems[dwcnt]->pd);
SafeGlobalFree(m_pSetupItems[dwcnt]);
}
}
for (dwcnt = 0; dwcnt < m_dwConsumerItemCount; dwcnt++)
{
if (m_pConsumerItems[dwcnt])
{
SafeGlobalFree(m_pConsumerItems[dwcnt]->ps);
SafeGlobalFree(m_pConsumerItems[dwcnt]->pd);
SafeGlobalFree(m_pConsumerItems[dwcnt]);
}
}
m_dwSetupItemCount = 0;
m_dwConsumerItemCount = 0;
}
BOOL CV31Server::MakeDependentList(OSVERSIONINFOEX &VersionInfo, CCRCMapFile *pMapFile)
{
// Log
LOG_block("CV31Server::MakeDependentList()");
// make sure the array is empty
SafeGlobalFree(m_pValidDependentPUIDArray);
// no dependency item
if (!m_nNumOfValidDependentPUID) return TRUE;
int nPUIDIndex = 0;
// allocate the memory
m_pValidDependentPUIDArray = (PUID*) GlobalAlloc(GMEM_ZEROINIT, sizeof(PUID)*m_nNumOfValidDependentPUID);
if (!m_pValidDependentPUIDArray)
{
LOG_error("Out of memory");
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
ULONG ulItem;
for (ulItem = 0; ulItem < m_dwSetupItemCount && nPUIDIndex < m_nNumOfValidDependentPUID; ulItem++)
{
if (WU_TYPE_ACTIVE_SETUP_RECORD != GetRecordType(m_pSetupItems[ulItem]) ||
!m_pSetupItems[ulItem]->ps->bHidden || m_pSetupItems[ulItem]->ps->state == WU_ITEM_STATE_PRUNED)
continue;
PINVENTORY_ITEM pItem = m_pSetupItems[ulItem];
// get a hidden setup dependency item record
BOOL fRet = ReadDescription(pItem, pMapFile);
if (!fRet)
// failed to read description file for this item, assume this dependency does not apply
// this way, we will not download any item not apply, but may miss some items that apply
continue;
// Title is composed as BuildMin.BuildMax.SPMajor.SPMinor
PWU_VARIABLE_FIELD pvField = pItem->pd->pv->Find(WU_DESCRIPTION_TITLE);
if (!pvField)
{
// title is NULL, error, ignore this item
LOG_error("Title is NULL");
continue;
}
wchar_t * pvTitle = (wchar_t*) pvField->pData;
DWORD dwBuild[4];
dwBuild[0]=0;
dwBuild[1]=99999;
dwBuild[2]=0;
dwBuild[3]=0;
int nBuildIndex = 0;
int nTemp = 0;
BOOL fBreak = FALSE;
while (nBuildIndex<4 && !fBreak)
{
if (*pvTitle != L'.' && *pvTitle != NULL )
{
if (*pvTitle > L'9' || *pvTitle < '0')
{
// illegal use of this title
LOG_error("Illegal character '%c' found in the title",(char)*pvTitle);
SetLastError(ERROR_INVALID_DATA);
return FALSE;
}
else
{
nTemp *=10;
nTemp += (*pvTitle - L'0');
}
}
else
{
if (!*pvTitle) fBreak = TRUE;
dwBuild[nBuildIndex++] = nTemp;
nTemp = 0;
}
pvTitle++;
}
LOG_out("Title is %d.%d.%d.%d\n", dwBuild[0], dwBuild[1], dwBuild[2], dwBuild[3]);
// determine if this item apply
if (dwBuild[0] <= VersionInfo.dwBuildNumber &&
dwBuild[1] >= VersionInfo.dwBuildNumber &&
dwBuild[2] == VersionInfo.wServicePackMajor&&
dwBuild[3] == VersionInfo.wServicePackMinor)
{
// applys, add this to the list
LOG_out("This dependency item applied");
m_pValidDependentPUIDArray[nPUIDIndex++] = pItem->GetPuid();
}
else
LOG_out("This dependency item NOT applied");
}
return TRUE;
}
BOOL CV31Server::IsDependencyApply(PUID puid)
{
LOG_block("CV31Server::IsDependencyApply()");
LOG_out("puid(%d)", (long)puid);
// handle no link
if (WU_NO_LINK == puid) return TRUE;
// no depend item is valid
if (!m_nNumOfValidDependentPUID)
{
LOG_out("No dependecy item");
return FALSE;
}
for (int nItem = 0; nItem < m_nNumOfValidDependentPUID; nItem ++)
{
if (m_pValidDependentPUIDArray[nItem] == puid)
{
LOG_out ("puid(%d) applies", (long)puid);
return TRUE;
}
if (m_pValidDependentPUIDArray[nItem] == 0) break; // 0 mark the end of valid puid
}
LOG_out("puid(%d) does not apply", (long)puid);
return FALSE;
}
BOOL CV31Server::GetBitMask(LPSTR szBitmapLocalFileName, PUID nDirectoryPuid, PBYTE* pByte, LPSTR szDecompressedName)
{
LOG_block("CV31Server::GetBitMask()");
LOG_out("Parameters --- %s",szBitmapLocalFileName);
SetLastError(0);
// Parameter validation
if (!szBitmapLocalFileName)
{
LOG_error("Invalid Parameter");
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
SafeGlobalFree(*pByte);
PBITMASK pBitMask = NULL;
DWORD dwLength = 0;
DWORD dwError = 0;
BOOL fRetVal = FALSE;
// log parameter
LOG_out("szBitmapLocalFileName(%s)",szBitmapLocalFileName);
char szBitmapServerFileName[INTERNET_MAX_URL_LENGTH];
ZeroMemory(szBitmapServerFileName, INTERNET_MAX_URL_LENGTH*sizeof(char));
char szBitmapFileWithDir[MAX_PATH];
wsprintf(szBitmapFileWithDir, "%d/%s", nDirectoryPuid, szBitmapLocalFileName);
m_pDu->DuUrlCombine(szBitmapServerFileName, m_szV31ContentUrl, szBitmapFileWithDir);
dwError = m_pDu->DownloadFileToMem(szBitmapServerFileName,
(PBYTE*)&pBitMask, &dwLength, TRUE, szBitmapLocalFileName, szDecompressedName);
if (ERROR_SUCCESS != dwError)
{
LOG_error("Failed to download %s --- %d", szBitmapServerFileName, dwError);
return FALSE;
}
int iMaskByteSize = ((pBitMask->iRecordSize+7)/8);
int nIndex = 0;
for (int nItem =0; nItem < pBitMask->iLocaleCount; nItem ++)
{
nIndex = pBitMask->iOemCount + nItem;
if (pBitMask->bmID[nIndex] == m_pDu->m_lcidLocaleID) break;
}
if (nItem >= pBitMask->iLocaleCount)
{
// not found
// bad locale ? or missing locale info?
LOG_error("LCID %d is not found in %s", m_pDu->m_lcidLocaleID, szBitmapLocalFileName);
SetLastError(ERROR_UNSUPPORTED_TYPE);
goto ErrorReturn;
}
*pByte =(PBYTE) GlobalAlloc(GMEM_ZEROINIT, iMaskByteSize);
if (!pByte)
{
LOG_error("Out of memory");
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto ErrorReturn;
}
CopyMemory((PVOID)*pByte, (const PVOID) pBitMask->GetBitMaskPtr(nIndex+2), iMaskByteSize);
fRetVal = TRUE;
/* The next part of the code can be used to print of bitmask.as
if (lstrcmp (szBitmapLocalFileName, "bitmask.cdm") == 0) goto ErrorReturn;
for (nIndex = 0; nIndex < pBitMask->iLocaleCount; nIndex ++)
{
char szTTT [MAX_PATH];
ZeroMemory(szTTT, MAX_PATH);
wsprintf(szTTT, "%d --- ", pBitMask->bmID[nIndex +2 + pBitMask->iOemCount]);
PBYTE pTep = (PBYTE) pBitMask->GetBitMaskPtr(nIndex +2 + pBitMask->iOemCount);
for (nItem = 0; nItem < iMaskByteSize; nItem ++)
{
char szTTTTT [MAX_PATH];
wsprintf(szTTTTT, "%d, ", pTep[nItem]);
lstrcat(szTTT, szTTTTT);
}
LOG_out("%s", szTTT);
}*/
ErrorReturn:
SafeGlobalFree(pBitMask);
return fRetVal;
}
BOOL CV31Server::ReadGuidrvINF()
{
LOG_block("CV31Server::ReadGuidrvINF()");
char szServerFile[INTERNET_MAX_URL_LENGTH + 1];
char szLocalFile[MAX_PATH];
char szValue[1024];
int nDefaultBufferLength = 512;
SafeGlobalFree(m_pszExcludedDriver);
// Now read the Catalog.ini file to find out if any of these items needs to be turned off
m_pDu->DuUrlCombine(szServerFile, m_szV31ContentUrl, GUIDRVINF);
PathCombineA(szLocalFile, m_pDu->GetDuDownloadPath(), GUIDRVINF);
if (ERROR_SUCCESS!=m_pDu->DownloadFile(szServerFile, szLocalFile, FALSE, FALSE))
{
LOG_out("No guidrv.inf found");
return TRUE;
}
int nReadLength;
do
{
nDefaultBufferLength <<=1;
SafeGlobalFree(m_pszExcludedDriver);
m_pszExcludedDriver = (LPSTR) GlobalAlloc(GPTR, nDefaultBufferLength * sizeof(char));
if (!m_pszExcludedDriver)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
LOG_error("Out of memory");
return FALSE;
}
nReadLength = GetPrivateProfileSectionA("ExcludedDrivers", m_pszExcludedDriver, nDefaultBufferLength, szLocalFile);
} while ( nDefaultBufferLength-2 == nReadLength);
if (!lstrlenA(m_pszExcludedDriver))
{
SafeGlobalFree(m_pszExcludedDriver);
m_pszExcludedDriver = NULL;
}
return TRUE;
}
BOOL CV31Server::IsPUIDExcluded(PUID nPuid)
{
if (m_dwGlobalExclusionItemCount > 0)
{
for (DWORD dwCnt = 0; dwCnt < m_dwGlobalExclusionItemCount; dwCnt++)
{
if (nPuid == m_GlobalExclusionArray[dwCnt])
return TRUE;
}
}
return FALSE;
}
BOOL CV31Server::IsDriverExcluded(LPCSTR szWHQLId, LPCSTR szHardwareId)
{
LOG_block("CV31Server::IsDriverExcluded()");
LOG_out("%s %s", szWHQLId, szHardwareId);
if(m_pszExcludedDriver)
{
char* pTemp = m_pszExcludedDriver;
while (*pTemp)
{
// try to find if the driver is excluded
char* pCharEnd = pTemp;
char* pCharBegin = pTemp;
// first one is the id for the cab
while (*pCharEnd != ',' && *pCharEnd != '\0') pCharEnd++;
if (NULL == *pCharEnd)
{
LOG_error("guidrvs.inf corruption --- %s", pTemp);
return TRUE; // guidrvs.inf corrupted, assume excluded
}
if (lstrlenA(szWHQLId) == (int)(pCharEnd - pCharBegin)
&& !StrCmpNI(szWHQLId, pCharBegin, (int)(pCharEnd-pCharBegin)))
{
// cab name matches, try to match hardware id
// ignore second and third one
for (int i=0; i<2; i++)
{
pCharBegin = pCharEnd + 1;
pCharEnd = pCharBegin;
while (*pCharEnd != ',' && *pCharEnd != '\0') pCharEnd++;
if (NULL == *pCharEnd)
{
LOG_error("guidrvs.inf corruption --- %s", pTemp);
return TRUE; // guidrv.inf corrupted, assume excluded
}
}
// the forth one should be the hardware id
pCharBegin = pCharEnd + 1;
if (!lstrcmpi(szHardwareId, pCharBegin) || ('*' == *pCharBegin && !*(pCharBegin+1)))
{
LOG_out("Found match in guidrvs.inf, excluded --- %s", pTemp);
return TRUE;
}
}
// move to next string
pTemp += lstrlenA(pTemp) + 1;
}
}
return FALSE;
}
BOOL CV31Server::GetAltName(LPCSTR szCabName, LPSTR szAltName, int nSize)
{
if (!szCabName || !szAltName) return FALSE;
char* pTemp = const_cast<char*>(szCabName);
while (*pTemp && *pTemp != '_') pTemp++;
int nTempSize = (int)(pTemp-szCabName);
if (nTempSize >= nSize) return FALSE;
lstrcpynA(szAltName, szCabName, nTempSize+1);
return TRUE;
}