358 lines
9.5 KiB
C++
358 lines
9.5 KiB
C++
//=======================================================================
|
|
//
|
|
// Copyright (c) 2001 Microsoft Corporation. All Rights Reserved.
|
|
//
|
|
// File: AUCatalog.h
|
|
//
|
|
// Creator: PeterWi
|
|
//
|
|
// Purpose: AU Catalog Definitions
|
|
//
|
|
//=======================================================================
|
|
|
|
#pragma once
|
|
#include <stdio.h>
|
|
#include <msxml.h>
|
|
#include <windows.h>
|
|
#include <safefunc.h>
|
|
#include "Loadengine.h"
|
|
#include "iu.h" //for IU engine exported functions' prototype
|
|
#include "iuctl.h" //for definition of UPDATE_COMMAND_CANCEL
|
|
#include "mistsafe.h"
|
|
|
|
class AUCatalogItem;
|
|
|
|
const WCHAR AUCLIENTINFO[] = L"<clientInfo xmlns=\"x-schema:http://schemas.windowsupdate.com/iu/clientInfo.xml\" clientName=\"au\" />";
|
|
const WCHAR AUDRIVERCLIENTINFO[] = L"<clientInfo xmlns=\"x-schema:http://schemas.windowsupdate.com/iu/clientInfo.xml\" clientName=\"audriver\" />";
|
|
|
|
const DWORD AUCATITEM_UNSELECTED = 0;
|
|
const DWORD AUCATITEM_SELECTED = 1;
|
|
const DWORD AUCATITEM_HIDDEN = 2;
|
|
|
|
//global object should not use CAU_BSTR because its constructor and destructor will
|
|
//make API calls which might cause dll loader deadlock
|
|
class CAU_BSTR
|
|
{
|
|
public:
|
|
CAU_BSTR() : m_bstr(NULL){};
|
|
~CAU_BSTR() {SafeFreeBSTR(m_bstr); }
|
|
|
|
operator BSTR() { return m_bstr; }
|
|
|
|
BOOL append(LPCWSTR wszToAppend)
|
|
{
|
|
if (NULL == wszToAppend)
|
|
{
|
|
return FALSE;
|
|
}
|
|
if (NULL == m_bstr)
|
|
{
|
|
m_bstr = SysAllocString(wszToAppend);
|
|
return m_bstr != NULL;
|
|
}
|
|
int ilen = SysStringLen(m_bstr) + lstrlenW(wszToAppend) + 1;
|
|
LPWSTR wszTmp = (LPWSTR) malloc(ilen * sizeof(WCHAR));
|
|
if (NULL == wszTmp)
|
|
{
|
|
return FALSE;
|
|
}
|
|
BOOL fRet =
|
|
SUCCEEDED(StringCchCopyExW(wszTmp, ilen, m_bstr, NULL, NULL, MISTSAFE_STRING_FLAGS)) &&
|
|
SUCCEEDED(StringCchCatExW(wszTmp, ilen, wszToAppend, NULL, NULL, MISTSAFE_STRING_FLAGS)) &&
|
|
SysReAllocString(&m_bstr, wszTmp);
|
|
free(wszTmp);
|
|
return fRet;
|
|
}
|
|
|
|
private:
|
|
BSTR m_bstr;
|
|
};
|
|
|
|
class AU_VARIANT : public ::tagVARIANT
|
|
{
|
|
public:
|
|
AU_VARIANT()
|
|
{
|
|
vt = VT_EMPTY;
|
|
}
|
|
|
|
AU_VARIANT(LPCWSTR wsz)
|
|
{
|
|
vt = VT_BSTR;
|
|
if ( NULL == (bstrVal = SysAllocString(wsz)) )
|
|
{
|
|
vt = VT_EMPTY;
|
|
}
|
|
}
|
|
|
|
AU_VARIANT(long newlVal)
|
|
{
|
|
vt = VT_I4;
|
|
lVal = newlVal;
|
|
}
|
|
|
|
AU_VARIANT(GUID & guid)
|
|
{
|
|
WCHAR wszGUID[40]; // 725e35a2-ee11-4b34-834f-6eaf4bade994
|
|
|
|
vt = VT_BSTR;
|
|
if ( (0 == StringFromGUID2(guid, wszGUID, ARRAYSIZE(wszGUID))) ||
|
|
(NULL == (bstrVal = SysAllocString(wszGUID))) )
|
|
{
|
|
DEBUGMSG("variant with guid failed");
|
|
vt = VT_EMPTY;
|
|
}
|
|
}
|
|
|
|
~AU_VARIANT() { VariantClear(this); }
|
|
|
|
BOOL IsEmpty(void) { return VT_EMPTY == vt; }
|
|
};
|
|
|
|
|
|
class AUCatalogItemList
|
|
{
|
|
public:
|
|
AUCatalogItemList()
|
|
:pList(NULL), uNum(0) {}
|
|
~AUCatalogItemList() { Clear(); }
|
|
UINT Count(void) { return uNum; }
|
|
|
|
AUCatalogItem & operator[] (UINT uIndex) const
|
|
{
|
|
return *pList[uIndex];
|
|
}
|
|
void Clear(void);
|
|
HRESULT Allocate(DWORD cItems);
|
|
HRESULT Allocate(VARIANT & var);
|
|
BOOL Add(AUCatalogItem *pitem);
|
|
void Remove(BSTR bstrItemID);
|
|
INT Contains(BSTR bstrItemID);
|
|
HRESULT Copy( AUCatalogItemList &itemlist2);
|
|
HRESULT BuildIndirectDependency();
|
|
|
|
UINT GetNum(DWORD dwSelectionStatus);
|
|
UINT GetNumSelected(void) { return GetNum(AUCATITEM_SELECTED); }
|
|
UINT GetNumUnselected(void) { return GetNum(AUCATITEM_UNSELECTED); }
|
|
UINT GetNumHidden(void) { return GetNum(AUCATITEM_HIDDEN);}
|
|
|
|
BOOL ItemIsRelevant(UINT index) ;
|
|
|
|
void DbgDump(void);
|
|
|
|
private:
|
|
UINT uNum;
|
|
AUCatalogItem **pList;
|
|
};
|
|
|
|
class AUCatalogItem
|
|
{
|
|
public:
|
|
AUCatalogItem()
|
|
: m_dwStatus(AUCATITEM_SELECTED),
|
|
m_bstrID(NULL),
|
|
m_bstrProviderName(NULL),
|
|
m_bstrTitle(NULL),
|
|
m_bstrDescription(NULL),
|
|
m_bstrRTFPath(NULL),
|
|
m_bstrEULAPath(NULL)
|
|
{}
|
|
|
|
AUCatalogItem(AUCatalogItem & item2)
|
|
{
|
|
m_bstrID = SysAllocString(item2.bstrID());
|
|
m_bstrProviderName = SysAllocString(item2.bstrProviderName());
|
|
m_bstrTitle = SysAllocString(item2.bstrTitle());
|
|
m_bstrDescription = SysAllocString(item2.bstrDescription());
|
|
m_bstrRTFPath = SysAllocString(item2.bstrRTFPath());
|
|
m_bstrEULAPath = SysAllocString(item2.bstrEULAPath());
|
|
m_dwStatus = item2.dwStatus();
|
|
}
|
|
|
|
void Clear()
|
|
{
|
|
SafeFreeBSTRNULL(m_bstrID);
|
|
SafeFreeBSTRNULL(m_bstrTitle);
|
|
SafeFreeBSTRNULL(m_bstrProviderName);
|
|
SafeFreeBSTRNULL(m_bstrDescription);
|
|
SafeFreeBSTRNULL(m_bstrRTFPath);
|
|
SafeFreeBSTRNULL(m_bstrEULAPath);
|
|
}
|
|
|
|
~AUCatalogItem()
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
BOOL fEqual(AUCatalogItem & item2)
|
|
{
|
|
BOOL fRet = FALSE;
|
|
BSTR myValues[] = {m_bstrID,
|
|
m_bstrProviderName,
|
|
m_bstrTitle,
|
|
m_bstrDescription,
|
|
m_bstrRTFPath,
|
|
m_bstrEULAPath };
|
|
BSTR theirValues[] = {item2.bstrID(),
|
|
item2.bstrProviderName(),
|
|
item2.bstrTitle(),
|
|
item2.bstrDescription(),
|
|
item2.bstrRTFPath(),
|
|
item2.bstrEULAPath()};
|
|
if (item2.dwStatus() != m_dwStatus)
|
|
{
|
|
goto done;
|
|
}
|
|
for ( UINT i= 0; i < ARRAYSIZE(myValues); i++ )
|
|
{
|
|
if (NULL != myValues[i] && NULL == theirValues[i]
|
|
|| NULL == myValues[i] && NULL != theirValues[i])
|
|
{
|
|
goto done;
|
|
}
|
|
else if (NULL != myValues[i] && NULL != theirValues[i])
|
|
{
|
|
if (0 != lstrcmpW(myValues[i], theirValues[i]))
|
|
{
|
|
goto done;
|
|
}
|
|
}
|
|
}
|
|
fRet = TRUE;
|
|
done:
|
|
return fRet;
|
|
}
|
|
|
|
|
|
void SetField(LPCSTR szFieldName, BSTR bstrVal)
|
|
{
|
|
BSTR * grValues[] = { &m_bstrID,
|
|
&m_bstrProviderName,
|
|
&m_bstrTitle,
|
|
&m_bstrDescription,
|
|
&m_bstrRTFPath,
|
|
&m_bstrEULAPath };
|
|
|
|
for ( int index = 0; index < ARRAYSIZE(grValues); index++ )
|
|
{
|
|
if ( 0 == _stricmp(szFieldName, m_pFieldNames[index]))
|
|
{
|
|
*grValues[index] = bstrVal;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void dump() //for debug
|
|
{
|
|
DEBUGMSG("dumping item content");
|
|
DEBUGMSG("Item ID= %S", m_bstrID);
|
|
DEBUGMSG("Provider Name= %S", m_bstrProviderName);
|
|
DEBUGMSG("Title= %S", m_bstrTitle);
|
|
DEBUGMSG("Desc= %S", m_bstrDescription);
|
|
DEBUGMSG("RTF Path= %S", m_bstrRTFPath);
|
|
DEBUGMSG("Eula Path= %S", m_bstrEULAPath);
|
|
DEBUGMSG("status = %d", m_dwStatus);
|
|
if (m_DependingItems.Count() == 0)
|
|
{
|
|
DEBUGMSG(" has no depending items");
|
|
}
|
|
else
|
|
{
|
|
DEBUGMSG(" has total %d depending items", m_DependingItems.Count());
|
|
for (UINT i = 0; i < m_DependingItems.Count(); i++)
|
|
{
|
|
DEBUGMSG(" : %S", m_DependingItems[i].bstrID()); //only cares about itemID
|
|
}
|
|
}
|
|
DEBUGMSG("dumping item done");
|
|
}
|
|
|
|
static char * m_pFieldNames[] ;
|
|
|
|
DWORD dwStatus(void) { return m_dwStatus; }
|
|
BSTR bstrID(void) { return (m_bstrID); }
|
|
BSTR bstrProviderName(void) { return (m_bstrProviderName); }
|
|
BSTR bstrTitle(void) { return (m_bstrTitle); }
|
|
BSTR bstrDescription(void) { return (m_bstrDescription); }
|
|
BSTR bstrRTFPath(void) { return (m_bstrRTFPath); }
|
|
BSTR bstrEULAPath(void) { return (m_bstrEULAPath); }
|
|
|
|
void SetStatus(DWORD dwStatus) { m_dwStatus = dwStatus; }
|
|
void SetStatusHidden(void) { m_dwStatus = AUCATITEM_HIDDEN; }
|
|
void SetStatusSelected(void) {m_dwStatus = AUCATITEM_SELECTED;}
|
|
|
|
BOOL fSelected(void) { return (AUCATITEM_SELECTED == m_dwStatus); }
|
|
BOOL fUnselected(void) { return (AUCATITEM_UNSELECTED == m_dwStatus); }
|
|
BOOL fHidden(void) { return (AUCATITEM_HIDDEN == m_dwStatus); }
|
|
|
|
AUCatalogItemList m_DependingItems; //all items that depends on this item, directly and indirectly
|
|
private:
|
|
DWORD m_dwStatus;
|
|
|
|
BSTR m_bstrID;
|
|
BSTR m_bstrProviderName;
|
|
BSTR m_bstrTitle;
|
|
BSTR m_bstrDescription;
|
|
BSTR m_bstrRTFPath;
|
|
BSTR m_bstrEULAPath;
|
|
|
|
|
|
friend HRESULT TransformSafeArrayToItemList(VARIANT & var, AUCatalogItemList & ItemList);
|
|
friend class AUCatalog;
|
|
};
|
|
|
|
|
|
|
|
//wrapper class for AU to do detection using IU
|
|
class AUBaseCatalog
|
|
{
|
|
public:
|
|
AUBaseCatalog()
|
|
{
|
|
Reset();
|
|
}
|
|
~AUBaseCatalog();
|
|
HRESULT PrepareIU(BOOL fOnline = TRUE);
|
|
void FreeIU();
|
|
HRESULT CancelNQuit(void);
|
|
protected:
|
|
HMODULE m_hIUCtl;
|
|
HMODULE m_hIUEng;
|
|
PFN_LoadIUEngine m_pfnCtlLoadIUEngine;
|
|
PFN_UnLoadIUEngine m_pfnCtlUnLoadIUEngine;
|
|
PFN_GetSystemSpec m_pfnGetSystemSpec;
|
|
PFN_GetManifest m_pfnGetManifest;
|
|
PFN_Detect m_pfnDetect;
|
|
PFN_Install m_pfnInstall;
|
|
PFN_SetOperationMode m_pfnSetOperationMode;
|
|
PFN_CtlCancelEngineLoad m_pfnCtlCancelEngineLoad;
|
|
PFN_CreateEngUpdateInstance m_pfnCreateEngUpdateInstance;
|
|
PFN_DeleteEngUpdateInstance m_pfnDeleteEngUpdateInstance;
|
|
BOOL m_fEngineLoaded;
|
|
HIUENGINE m_hIUEngineInst;
|
|
private:
|
|
void Reset()
|
|
{
|
|
m_hIUCtl = NULL;
|
|
m_hIUEng = NULL;
|
|
m_pfnCtlLoadIUEngine = NULL;
|
|
m_pfnCtlUnLoadIUEngine = NULL;
|
|
m_pfnGetSystemSpec = NULL;
|
|
m_pfnGetManifest = NULL;
|
|
m_pfnDetect = NULL;
|
|
m_pfnInstall = NULL;
|
|
m_pfnSetOperationMode = NULL;
|
|
m_pfnCtlCancelEngineLoad = NULL;
|
|
m_pfnCreateEngUpdateInstance = NULL;
|
|
m_pfnDeleteEngUpdateInstance = NULL;
|
|
m_hIUEngineInst = NULL;
|
|
m_fEngineLoaded = FALSE;
|
|
}
|
|
};
|
|
|
|
|
|
extern HANDLE ghMutex; //mutex used to prevent catalog from being destructed while canceling it
|
|
|
|
|