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.
1361 lines
32 KiB
1361 lines
32 KiB
#include "inspch.h"
|
|
#include <regstr.h>
|
|
#include "resource.h"
|
|
#include "insobj.h"
|
|
|
|
|
|
#define STR_FILELIST "filelist.dat"
|
|
#define GENERAL_SECTION "General"
|
|
#define MIN_SUPPORTED_FILELIST_VER 1
|
|
#define CURRENT_FILELIST_VER "1"
|
|
|
|
HRESULT GetICifFileFromFile(ICifFile **p, LPCSTR pszPath)
|
|
{
|
|
HRESULT hr;
|
|
CCifFile *pcif;
|
|
|
|
*p = 0;
|
|
pcif = new CCifFile();
|
|
if(pcif)
|
|
{
|
|
hr = pcif->SetCifFile(pszPath, FALSE); // FALSE: Read version
|
|
if(FAILED(hr))
|
|
delete pcif;
|
|
else
|
|
{
|
|
pcif->AddRef();
|
|
*p = (ICifFile *)pcif;
|
|
}
|
|
}
|
|
else
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT GetICifRWFileFromFile(ICifRWFile **p, LPCSTR pszPath)
|
|
{
|
|
HRESULT hr;
|
|
CCifRWFile *pcifrw;
|
|
|
|
*p = 0;
|
|
pcifrw = new CCifRWFile();
|
|
if(pcifrw)
|
|
{
|
|
hr = pcifrw->SetCifFile(pszPath, TRUE); // TRUE: ReadWrite version
|
|
if(FAILED(hr))
|
|
delete pcifrw;
|
|
else
|
|
{
|
|
pcifrw->AddRef();
|
|
*p = (ICifRWFile *)pcifrw;
|
|
}
|
|
}
|
|
else
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
CCifFile::CCifFile()
|
|
{
|
|
_cRef = 0;
|
|
_cComp = 0;
|
|
_cGroup = 0;
|
|
_cMode = 0;
|
|
_rpGroup = 0;
|
|
_rpComp = 0;
|
|
_rpMode = 0;
|
|
_rpRWGroup = 0;
|
|
_rpRWComp = 0;
|
|
_rpRWMode = 0;
|
|
_fCleanDir = FALSE;
|
|
_pLastCriticalComp = NULL;
|
|
}
|
|
|
|
CCifFile::~CCifFile()
|
|
{
|
|
UINT i;
|
|
if(_rpGroup)
|
|
{
|
|
CCifGroup *pgrp;
|
|
|
|
i = 0;
|
|
for(pgrp = _rpGroup[i]; pgrp != 0; pgrp = _rpGroup[++i])
|
|
delete pgrp;
|
|
|
|
free(_rpGroup);
|
|
}
|
|
|
|
|
|
if(_rpComp)
|
|
{
|
|
CCifComponent *pcomp;
|
|
|
|
i = 0;
|
|
for(pcomp = _rpComp[i]; pcomp != 0; pcomp = _rpComp[++i])
|
|
delete pcomp;
|
|
|
|
free(_rpComp);
|
|
}
|
|
|
|
if(_rpMode)
|
|
{
|
|
|
|
CCifMode *pmode;
|
|
|
|
i = 0;
|
|
for(pmode = _rpMode[i]; pmode != 0; pmode = _rpMode[++i])
|
|
delete pmode;
|
|
|
|
free(_rpMode);
|
|
}
|
|
|
|
if(_fCleanDir)
|
|
{
|
|
GetParentDir(_szCifPath);
|
|
CleanUpTempDir(_szCifPath);
|
|
}
|
|
|
|
}
|
|
|
|
//************ IUnknown implementation ***************
|
|
|
|
|
|
STDMETHODIMP_(ULONG) CCifFile::AddRef()
|
|
{
|
|
return(_cRef++);
|
|
}
|
|
|
|
|
|
STDMETHODIMP_(ULONG) CCifFile::Release()
|
|
{
|
|
ULONG temp = --_cRef;
|
|
|
|
if(temp == 0)
|
|
delete this;
|
|
return temp;
|
|
}
|
|
|
|
|
|
STDMETHODIMP CCifFile::QueryInterface(REFIID riid, void **ppv)
|
|
{
|
|
*ppv = 0;
|
|
|
|
if((riid == IID_IUnknown) || (riid == IID_ICifFile))
|
|
*ppv = (ICifFile *)this;
|
|
|
|
if(*ppv == NULL)
|
|
return E_NOINTERFACE;
|
|
|
|
AddRef();
|
|
return NOERROR;
|
|
}
|
|
|
|
// ICifFile implementation
|
|
|
|
STDMETHODIMP CCifFile::EnumComponents(IEnumCifComponents **pp, DWORD dwFilter, LPVOID pv)
|
|
{
|
|
CCifComponentEnum *pce;
|
|
HRESULT hr = E_FAIL;
|
|
|
|
*pp = 0;
|
|
|
|
pce = new CCifComponentEnum(_rpComp, dwFilter, PARENTTYPE_CIF, NULL);
|
|
if(pce)
|
|
{
|
|
*pp = (IEnumCifComponents *) pce;
|
|
(*pp)->AddRef();
|
|
hr = NOERROR;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CCifFile::FindComponent(LPCSTR pszID, ICifComponent **p)
|
|
{
|
|
CCifComponent *pcomp;
|
|
UINT i = 0;
|
|
|
|
*p = 0;
|
|
if(_rpComp)
|
|
{
|
|
for(pcomp = _rpComp[i]; pcomp != 0; pcomp = _rpComp[++i])
|
|
if(pcomp->IsID(pszID))
|
|
{
|
|
*p = (ICifComponent *) pcomp;
|
|
return NOERROR;
|
|
}
|
|
}
|
|
|
|
return E_FAIL;
|
|
}
|
|
|
|
STDMETHODIMP CCifFile::EnumGroups(IEnumCifGroups **pp, DWORD dwFilter, LPVOID pv)
|
|
{
|
|
CCifGroupEnum *pge;
|
|
HRESULT hr = E_FAIL;
|
|
|
|
*pp = 0;
|
|
|
|
pge = new CCifGroupEnum(_rpGroup, dwFilter);
|
|
if(pge)
|
|
{
|
|
*pp = (IEnumCifGroups *) pge;
|
|
(*pp)->AddRef();
|
|
hr = NOERROR;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CCifFile::FindGroup(LPCSTR pszID, ICifGroup **p)
|
|
{
|
|
CCifGroup *pgrp;
|
|
UINT i = 0;
|
|
|
|
*p = 0;
|
|
if(_rpGroup)
|
|
{
|
|
for(pgrp = _rpGroup[i]; pgrp != 0; pgrp = _rpGroup[++i])
|
|
if(pgrp->IsID(pszID))
|
|
{
|
|
*p = (ICifGroup *) pgrp;
|
|
return NOERROR;
|
|
}
|
|
}
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
STDMETHODIMP CCifFile::EnumModes(IEnumCifModes **pp, DWORD dwFilter, LPVOID pv)
|
|
{
|
|
CCifModeEnum *pme;
|
|
HRESULT hr = E_FAIL;
|
|
|
|
*pp = 0;
|
|
|
|
pme = new CCifModeEnum(_rpMode, dwFilter);
|
|
if(pme)
|
|
{
|
|
*pp = (IEnumCifModes *) pme;
|
|
(*pp)->AddRef();
|
|
hr = NOERROR;
|
|
}
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
STDMETHODIMP CCifFile::FindMode(LPCSTR pszID, ICifMode **p)
|
|
{
|
|
CCifMode *pmode;
|
|
UINT i = 0;
|
|
|
|
*p = 0;
|
|
if(_rpMode)
|
|
{
|
|
for(pmode = _rpMode[i]; pmode != 0; pmode = _rpMode[++i])
|
|
if(pmode->IsID(pszID))
|
|
{
|
|
*p = (ICifMode *) pmode;
|
|
return NOERROR;
|
|
}
|
|
}
|
|
return E_FAIL;
|
|
}
|
|
|
|
STDMETHODIMP CCifFile::GetDescription(LPSTR pszDesc, DWORD dwSize)
|
|
{
|
|
// Get display title out of version section
|
|
if(FAILED(MyTranslateString(_szCifPath, "Version", DISPLAYNAME_KEY, pszDesc, dwSize)))
|
|
LoadSz(IDS_DEFAULTTITLE, pszDesc, dwSize);
|
|
return NOERROR;
|
|
}
|
|
|
|
STDMETHODIMP CCifFile::GetDetDlls(LPSTR pszDlls, DWORD dwSize)
|
|
{
|
|
return(GetPrivateProfileString("Version", DETDLLS_KEY, "", pszDlls, dwSize, _szCifPath)?NOERROR:E_FAIL);
|
|
}
|
|
|
|
//const char c_gszRegstrPathIExplore[] = REGSTR_PATH_APPPATHS "\\iexplore.exe";
|
|
|
|
HRESULT CCifFile::SetCifFile(LPCSTR pszCifPath, BOOL bRWFlag)
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
UINT i;
|
|
|
|
// if it is not quallified, start from ie
|
|
if(PathIsFileSpec(pszCifPath))
|
|
{
|
|
DWORD dwSize, dwType;
|
|
char szTmp[MAX_PATH];
|
|
|
|
if ( SUCCEEDED(hr=GetIEPath(szTmp, sizeof(szTmp))))
|
|
{
|
|
lstrcpy(_szCifPath, szTmp);
|
|
SafeAddPath(_szCifPath, pszCifPath, sizeof(_szCifPath));
|
|
}
|
|
}
|
|
else // we were given a full path
|
|
lstrcpyn(_szCifPath, pszCifPath, MAX_PATH);
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
if(_rpComp)
|
|
{
|
|
// we already have a cif, so just reset cached stuff, and pray...
|
|
for(i = 0; i < _cComp; i++)
|
|
{
|
|
_rpComp[i]->ClearCachedInfo();
|
|
}
|
|
for(i = 0; i < _cGroup; i++)
|
|
{
|
|
_rpGroup[i]->ClearCachedInfo();
|
|
}
|
|
for(i = 0; i < _cMode; i++)
|
|
{
|
|
_rpMode[i]->ClearCachedInfo();
|
|
}
|
|
|
|
// Sort all again, in case priorities changed
|
|
SortEntries();
|
|
}
|
|
else
|
|
hr = _ParseCifFile(bRWFlag);
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
HRESULT CCifFile::_ParseCifFile(BOOL bRWFlag)
|
|
{
|
|
LPSTR pszSections;
|
|
LPSTR pszSectionsPreFail = NULL;
|
|
DWORD dwSize = ALLOC_CHUNK_SIZE;
|
|
LPSTR pszTemp;
|
|
char szEntryBuf[MAX_DISPLAYNAME_LENGTH];
|
|
|
|
pszSections = (LPSTR) malloc(dwSize);
|
|
// when the buffer is too small, GPPS returns bufsize - 2
|
|
while(pszSections &&
|
|
(GetPrivateProfileStringA(NULL, NULL, "", pszSections, dwSize, _szCifPath) == (dwSize - 2)))
|
|
{
|
|
dwSize += ALLOC_CHUNK_SIZE;
|
|
pszSectionsPreFail = pszSections;
|
|
#pragma prefast(suppress: 308, "PREfast noise - pointer was saved before")
|
|
pszSections = (LPSTR) realloc(pszSections, dwSize);
|
|
}
|
|
|
|
if(!pszSections)
|
|
{
|
|
if(pszSectionsPreFail)
|
|
free(pszSectionsPreFail);
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
if(lstrlen(pszSections) == 0)
|
|
return E_FAIL;
|
|
|
|
// whip thru the sections, and find counts for modes, groups, and components
|
|
_cComp = _cGroup = _cMode = 0;
|
|
|
|
for(pszTemp = pszSections; *pszTemp != 0; pszTemp += (lstrlen(pszTemp) + 1))
|
|
{
|
|
// skip String section and Version section
|
|
if( (lstrcmpi(pszTemp, "Strings") != 0)
|
|
&& (lstrcmpi(pszTemp, "Version") != 0) )
|
|
{
|
|
GetPrivateProfileString(pszTemp, ENTRYTYPE_KEY, ENTRYTYPE_COMP, szEntryBuf, sizeof(szEntryBuf), _szCifPath);
|
|
// see if this is a comp, group, or mode
|
|
if(lstrcmpi(szEntryBuf, ENTRYTYPE_COMP) == 0)
|
|
_cComp++;
|
|
else if(lstrcmpi(szEntryBuf, ENTRYTYPE_GROUP) == 0)
|
|
_cGroup++;
|
|
else if(lstrcmpi(szEntryBuf, ENTRYTYPE_MODE) == 0)
|
|
_cMode++;
|
|
}
|
|
}
|
|
|
|
// alloc arrays to hold each type (1 more than count - last entry null)
|
|
if (bRWFlag)
|
|
{
|
|
_rpRWComp = (CCifRWComponent **) calloc(sizeof(CCifRWComponent *), _cComp + 1);
|
|
_rpRWGroup = (CCifRWGroup **) calloc(sizeof(CCifRWGroup *), _cGroup + 1);
|
|
_rpRWMode = (CCifRWMode **) calloc(sizeof(CCifRWMode *), _cMode + 1);
|
|
}
|
|
else
|
|
{
|
|
_rpComp = (CCifComponent **) calloc(sizeof(CCifComponent *), _cComp + 1);
|
|
_rpGroup = (CCifGroup **) calloc(sizeof(CCifGroup *), _cGroup + 1);
|
|
_rpMode = (CCifMode **) calloc(sizeof(CCifMode *), _cMode + 1);
|
|
}
|
|
_cComp = _cGroup = _cMode = 0;
|
|
|
|
if((!bRWFlag && _rpComp && _rpGroup && _rpMode) || (bRWFlag && _rpRWComp && _rpRWGroup && _rpRWMode))
|
|
{
|
|
// pass thru sections again, adding to lists
|
|
for(pszTemp = pszSections; *pszTemp != 0; pszTemp += (lstrlen(pszTemp) + 1))
|
|
{
|
|
// skip String section and Version section
|
|
if( (lstrcmpi(pszTemp, "Strings") != 0)
|
|
&& (lstrcmpi(pszTemp, "Version") != 0) )
|
|
{
|
|
GetPrivateProfileString(pszTemp, ENTRYTYPE_KEY, ENTRYTYPE_COMP, szEntryBuf, sizeof(szEntryBuf), _szCifPath);
|
|
// see if this is a comp, group, or mode
|
|
if(lstrcmpi(szEntryBuf, ENTRYTYPE_COMP) == 0)
|
|
{
|
|
if (bRWFlag)
|
|
_rpRWComp[_cComp++] = new CCifRWComponent(pszTemp, this);
|
|
else
|
|
_rpComp[_cComp++] = new CCifComponent(pszTemp, this);
|
|
}
|
|
else if(lstrcmpi(szEntryBuf, ENTRYTYPE_GROUP) == 0)
|
|
{
|
|
if (bRWFlag)
|
|
_rpRWGroup[_cGroup++] = new CCifRWGroup(pszTemp, _cGroup, this);
|
|
else
|
|
_rpGroup[_cGroup++] = new CCifGroup(pszTemp, _cGroup, this);
|
|
}
|
|
else if(lstrcmpi(szEntryBuf, ENTRYTYPE_MODE) == 0)
|
|
{
|
|
if (bRWFlag)
|
|
_rpRWMode[_cMode++] = new CCifRWMode(pszTemp, this);
|
|
else
|
|
_rpMode[_cMode++] = new CCifMode(pszTemp, this);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(_cComp) _cComp--;
|
|
if(_cGroup) _cGroup--;
|
|
if(_cMode) _cMode--;
|
|
|
|
|
|
if (!bRWFlag)
|
|
SortEntries();
|
|
free(pszSections);
|
|
return NOERROR;
|
|
}
|
|
|
|
void CCifFile::ReinsertComponent(CCifComponent *pComp)
|
|
{
|
|
int i,j;
|
|
|
|
// find it in list
|
|
for(i = 0; i <= (int) _cComp; i++)
|
|
{
|
|
if(pComp == _rpComp[i])
|
|
{
|
|
// once found, move everything under it up
|
|
for(j = i + 1; j <=(int) (_cComp + 1); j++)
|
|
_rpComp[j-1] = _rpComp[j];
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
// now find where we should insert it
|
|
for(i = 0; _rpComp[i] != 0; i++)
|
|
{
|
|
if(_rpComp[i]->GetCurrentPriority() < pComp->GetCurrentPriority())
|
|
break;
|
|
}
|
|
|
|
// we want to isert new guy at i
|
|
// move everyone down first
|
|
for(j = _cComp; j >= i; j--)
|
|
_rpComp[j+1] = _rpComp[j];
|
|
|
|
// reinsert at i
|
|
_rpComp[i] = pComp;
|
|
|
|
|
|
// Now check that the dependencies are maintained.
|
|
_CheckDependencyPriority();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CCifFile::SortEntries()
|
|
{
|
|
_SortComponents(_rpComp, 0, _cComp);
|
|
_SortGroups(_rpGroup, 0, _cGroup);
|
|
_CheckDependencyPriority();
|
|
}
|
|
|
|
void CCifFile::_CheckDependencyPriority()
|
|
{
|
|
char szCompBuf[MAX_ID_LENGTH];
|
|
CCifComponent *pCompxkokr;
|
|
CCifComponent *pCompxenus;
|
|
DWORD ixkokr = 0xffffffff;
|
|
DWORD ixenus = 0xffffffff;
|
|
|
|
// this is a complete hack for Outlook 98 Korean, which has bugs
|
|
// in prorities.
|
|
|
|
for(int i = 0; _rpComp[i] != 0; i++)
|
|
{
|
|
if(_rpComp[i]->IsID("Outlook98_xkokr"))
|
|
{
|
|
pCompxkokr = _rpComp[i];
|
|
ixkokr = i;
|
|
}
|
|
else if(_rpComp[i]->IsID("Outlook98_xenus"))
|
|
{
|
|
pCompxenus = _rpComp[i];
|
|
ixenus = i;
|
|
}
|
|
}
|
|
if(ixkokr != 0xffffffff && ixenus != 0xffffffff)
|
|
{
|
|
if(ixenus > ixkokr)
|
|
{
|
|
_rpComp[ixenus] = pCompxkokr;
|
|
_rpComp[ixkokr] = pCompxenus;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
void CCifFile::ClearQueueState()
|
|
{
|
|
for(int i = 0; _rpComp[i] != 0; i++)
|
|
{
|
|
_rpComp[i]->ClearQueueState();
|
|
}
|
|
|
|
}
|
|
|
|
void CCifFile::_SortComponents(CCifComponent * a[], UINT p, UINT r)
|
|
{
|
|
UINT i, j, x;
|
|
CCifComponent *t;
|
|
|
|
if(p < r)
|
|
{
|
|
i = p - 1;
|
|
j = r + 1;
|
|
x = a[p]->GetCurrentPriority();
|
|
for(;;)
|
|
{
|
|
while(a[++i]->GetCurrentPriority() > x);
|
|
while(a[--j]->GetCurrentPriority() < x);
|
|
if(i >= j) break;
|
|
t = a[i]; a[i] = a[j]; a[j] = t;
|
|
}
|
|
_SortComponents(a, p, j);
|
|
_SortComponents(a, j + 1, r);
|
|
}
|
|
}
|
|
|
|
void CCifFile::_SortGroups(CCifGroup * a[], UINT p, UINT r)
|
|
{
|
|
UINT i, j, x;
|
|
CCifGroup *t;
|
|
|
|
if(p < r)
|
|
{
|
|
i = p - 1;
|
|
j = r + 1;
|
|
x = a[p]->GetCurrentPriority();
|
|
for(;;)
|
|
{
|
|
while(a[++i]->GetCurrentPriority() > x);
|
|
while(a[--j]->GetCurrentPriority() < x);
|
|
if(i >= j) break;
|
|
t = a[i]; a[i] = a[j]; a[j] = t;
|
|
}
|
|
_SortGroups(a, p, j);
|
|
_SortGroups(a, j + 1, r);
|
|
}
|
|
}
|
|
|
|
|
|
void CCifFile::SetDownloadDir(LPCSTR pszDownloadDir)
|
|
{
|
|
char szBuf[MAX_PATH];
|
|
DWORD dwLen;
|
|
DWORD dwVer;
|
|
|
|
lstrcpyn(_szDLDir, pszDownloadDir, MAX_PATH);
|
|
|
|
if(_szDLDir[0] >= 'a' && _szDLDir[0] <= 'z')
|
|
_szDLDir[0] -= 32;
|
|
|
|
|
|
lstrcpyn(_szFilelist, pszDownloadDir, MAX_PATH);
|
|
SafeAddPath(_szFilelist, STR_FILELIST, MAX_PATH);
|
|
|
|
// check to see if the download list has a version we like
|
|
dwVer = GetPrivateProfileInt(GENERAL_SECTION, VERSION_KEY, 0, _szFilelist);
|
|
if(dwVer < MIN_SUPPORTED_FILELIST_VER)
|
|
DeleteFilelist(_szFilelist);
|
|
|
|
WritePrivateProfileString(GENERAL_SECTION, VERSION_KEY, CURRENT_FILELIST_VER, _szFilelist);
|
|
|
|
// flush due to wierd stacker bug
|
|
WritePrivateProfileString(NULL, NULL, NULL, _szFilelist);
|
|
}
|
|
|
|
HRESULT CCifFile::Download()
|
|
{
|
|
CCifComponent *pcomp;
|
|
UINT i = 0;
|
|
HRESULT hr = NOERROR;
|
|
|
|
for(pcomp = _rpComp[i]; pcomp != 0 && SUCCEEDED(hr); pcomp = _rpComp[++i])
|
|
{
|
|
// if it is queued up and not downloded, download it
|
|
if((pcomp->GetInstallQueueState() == SETACTION_INSTALL) &&
|
|
(pcomp->IsComponentDownloaded() == S_FALSE) )
|
|
{
|
|
hr = pcomp->Download();
|
|
if(FAILED(hr) && _pInsEng->IgnoreDownloadError() && hr != E_ABORT)
|
|
hr = NOERROR;
|
|
|
|
if(SUCCEEDED(hr))
|
|
hr = _pInsEng->CheckForContinue();
|
|
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CCifFile::Install(BOOL *pfOneInstalled)
|
|
{
|
|
CCifComponent *pcomp;
|
|
UINT i = 0;
|
|
*pfOneInstalled = FALSE;
|
|
HRESULT hr = NOERROR;
|
|
|
|
for(pcomp = _rpComp[i]; (pcomp != 0) && SUCCEEDED(hr); pcomp = _rpComp[++i])
|
|
{
|
|
// if it is queued up and not downloded, download it
|
|
if(pcomp->GetInstallQueueState() == SETACTION_INSTALL)
|
|
{
|
|
hr = pcomp->Install();
|
|
|
|
if(SUCCEEDED(hr))
|
|
*pfOneInstalled = TRUE;
|
|
|
|
if(hr != E_ABORT)
|
|
hr = NOERROR;
|
|
|
|
if(SUCCEEDED(hr))
|
|
hr = _pInsEng->CheckForContinue();
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CCifFile::_ExtractDetDlls( LPCSTR pszCab, LPCSTR pszPath )
|
|
{
|
|
char szDetDlls[MAX_PATH];
|
|
char szLogBuf[MAX_PATH*2];
|
|
char szBuf[64];
|
|
UINT i = 0;
|
|
LPSTR pszTmp;
|
|
HRESULT hr = NOERROR;
|
|
|
|
// check if we need to extract & copy the detection dlls
|
|
if (SUCCEEDED(GetDetDlls(szDetDlls, sizeof(szDetDlls))))
|
|
{
|
|
while(SUCCEEDED(hr) && GetStringField(szDetDlls, i++, szBuf, sizeof(szBuf)))
|
|
{
|
|
if(SUCCEEDED(ExtractFiles(pszCab, pszPath, 0, szBuf, NULL, 0)))
|
|
{
|
|
wsprintf(szLogBuf, "Extract DetDll path:%s file:%s\r\n",pszPath, szBuf );
|
|
_pInsEng->WriteToLog(szLogBuf, TRUE);
|
|
}
|
|
else
|
|
{
|
|
wsprintf(szLogBuf, "Extract DetDll:%s from: %s\r\n", szBuf, pszCab);
|
|
_pInsEng->WriteToLog(szLogBuf, TRUE);
|
|
hr = E_FAIL;
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CCifFile::_CopyDetDlls( LPCSTR pszPath )
|
|
{
|
|
char szDetDlls[MAX_PATH];
|
|
char szSrcFile[MAX_PATH];
|
|
char szDestFile[MAX_PATH];
|
|
char szLogBuf[MAX_PATH*2];
|
|
char szBuf[64];
|
|
UINT i = 0;
|
|
LPSTR pszTmp;
|
|
|
|
// check if we need to extract & copy the detection dlls
|
|
if (SUCCEEDED(GetDetDlls(szDetDlls, sizeof(szDetDlls))))
|
|
{
|
|
lstrcpy(szDestFile, _szCifPath);
|
|
GetParentDir(szDestFile);
|
|
pszTmp = szDestFile + lstrlen(szDestFile);
|
|
|
|
while(GetStringField(szDetDlls, i++, szBuf, sizeof(szBuf)))
|
|
{
|
|
lstrcpy(szSrcFile, pszPath);
|
|
AddPath(szSrcFile, szBuf);
|
|
|
|
*pszTmp = 0;
|
|
AddPath(szDestFile, szBuf);
|
|
CopyFile(szSrcFile, szDestFile, FALSE);
|
|
|
|
wsprintf(szLogBuf, "Copy DetDll fr:%s to:%s\r\n", szSrcFile, szDestFile);
|
|
_pInsEng->WriteToLog(szLogBuf, TRUE);
|
|
}
|
|
return NOERROR;
|
|
}
|
|
else
|
|
return E_FAIL;
|
|
}
|
|
|
|
|
|
HRESULT CCifFile::DownloadCifFile(LPCSTR pszUrl, LPCSTR pszCif)
|
|
{
|
|
HRESULT hr;
|
|
char szTempfile[MAX_PATH];
|
|
char szDownldfile[MAX_PATH];
|
|
char szPath[MAX_PATH];
|
|
|
|
_pInsEng->AddRef();
|
|
_pInsEng->OnEngineStatusChange(ENGINESTATUS_LOADING, 0);
|
|
CDownloader *pDL = _pInsEng->GetDownloader();
|
|
if(!pDL)
|
|
return E_UNEXPECTED;
|
|
|
|
hr = pDL->SetupDownload(pszUrl, NULL, 0, NULL);
|
|
|
|
szPath[0] = 0;
|
|
if(SUCCEEDED(hr))
|
|
hr = pDL->DoDownload(szDownldfile, sizeof(szDownldfile));
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = ::CheckTrustEx(pszUrl, szDownldfile, _pInsEng->GetHWND(), FALSE, NULL);
|
|
if (hr == S_FALSE)
|
|
hr = TRUST_E_FAIL;
|
|
|
|
// For compat reasons, we need to copy the cif cab into the download dir
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
lstrcpy(szPath, _szDLDir);
|
|
SafeAddPath(szPath, ParseURLA(pszUrl), sizeof(szPath));
|
|
CopyFile(szDownldfile, szPath, FALSE);
|
|
}
|
|
|
|
lstrcpy(szPath, szDownldfile);
|
|
GetParentDir(szPath);
|
|
}
|
|
|
|
if(SUCCEEDED(hr))
|
|
hr=ExtractFiles(szDownldfile, szPath, 0, pszCif, NULL, 0);
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
//BUGBUG: we should validate cif we got somehow!
|
|
|
|
|
|
// if we already have a cif, copy what we need over old cif, delete temp now
|
|
if(_rpComp)
|
|
{
|
|
// Dest
|
|
lstrcpy(szTempfile, _szCifPath);
|
|
GetParentDir(szTempfile);
|
|
AddPath(szTempfile, pszCif);
|
|
|
|
// source
|
|
SafeAddPath(szPath, pszCif, sizeof(szPath));
|
|
|
|
// copy to old one
|
|
CopyFile(szPath, szTempfile, FALSE);
|
|
hr = SetCifFile(szTempfile, FALSE); // read only version
|
|
|
|
GetParentDir(szPath);
|
|
|
|
// check if we need to extract & copy the detection dlls
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if(SUCCEEDED(hr =_ExtractDetDlls(szDownldfile,szPath)))
|
|
_CopyDetDlls(szPath);
|
|
}
|
|
|
|
DelNode(szPath, 0);
|
|
}
|
|
else
|
|
{
|
|
// new cif, use it in place in temp dir, mark temp dir to clean up
|
|
_fCleanDir = TRUE;
|
|
SafeAddPath(szPath, pszCif, sizeof(szPath));
|
|
hr = SetCifFile(szPath, FALSE); // read only version
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
GetParentDir(szPath);
|
|
hr =_ExtractDetDlls(szDownldfile,szPath);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// cleanup now
|
|
if(szPath[0] != 0)
|
|
DelNode(szPath, 0);
|
|
}
|
|
|
|
_pInsEng->OnEngineStatusChange(SUCCEEDED(hr) ? ENGINESTATUS_READY : ENGINESTATUS_NOTREADY, hr);
|
|
|
|
// we are done; release the install engine
|
|
_pInsEng->Release();
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CCifFile::_FindCifComponent(LPCSTR pszID, CCifComponent **p)
|
|
{
|
|
CCifComponent *pcomp;
|
|
UINT i = 0;
|
|
|
|
*p = 0;
|
|
if(_rpComp)
|
|
{
|
|
for(pcomp = _rpComp[i]; pcomp != 0; pcomp = _rpComp[++i])
|
|
if(pcomp->IsID(pszID))
|
|
{
|
|
*p = pcomp;
|
|
return NOERROR;
|
|
}
|
|
}
|
|
return E_FAIL;
|
|
}
|
|
|
|
void CCifFile::MarkCriticalComponents(CCifComponent *pOwner)
|
|
{
|
|
char szID[MAX_ID_LENGTH];
|
|
UINT j;
|
|
CCifComponent *pComp;
|
|
|
|
for(j = 0;SUCCEEDED(pOwner->GetTreatAsOneComponents(j, szID, sizeof(szID))); j++)
|
|
{
|
|
if(SUCCEEDED(_FindCifComponent(szID, &pComp)))
|
|
{
|
|
if(pComp->GetInstallQueueState() == SETACTION_INSTALL)
|
|
{
|
|
if(_pLastCriticalComp == NULL)
|
|
_pLastCriticalComp = pComp;
|
|
else
|
|
{
|
|
UINT i = 0;
|
|
|
|
CCifComponent *ptemp;
|
|
for(ptemp = _rpComp[i]; ptemp != 0 && ptemp != _pLastCriticalComp && ptemp != pComp ; ptemp = _rpComp[++i]);
|
|
|
|
if(ptemp == _pLastCriticalComp)
|
|
_pLastCriticalComp = pComp;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CCifFile::RemoveFromCriticalComponents(CCifComponent *pComp)
|
|
{
|
|
if(_pLastCriticalComp == pComp)
|
|
_pLastCriticalComp = NULL;
|
|
}
|
|
|
|
|
|
DWORD WINAPI DownloadCifFile(LPVOID pv)
|
|
{
|
|
SETCIFARGS *p = (SETCIFARGS *) pv;
|
|
|
|
p->pCif->DownloadCifFile(p->szUrl, p->szCif);
|
|
|
|
delete p;
|
|
|
|
return 0;
|
|
}
|
|
|
|
CCifRWFile::CCifRWFile() : CCifFile()
|
|
{
|
|
_cCompUnused = 0;
|
|
_cGroupUnused = 0;
|
|
_cModeUnused = 0;
|
|
}
|
|
|
|
CCifRWFile::~CCifRWFile()
|
|
{
|
|
// flus out the cif file
|
|
WritePrivateProfileString( NULL, NULL, NULL, _szCifPath );
|
|
|
|
if(_rpRWGroup)
|
|
{
|
|
for ( UINT i=0; i<=_cGroup; i++)
|
|
delete(_rpRWGroup[i]);
|
|
free(_rpRWGroup);
|
|
}
|
|
|
|
if(_rpRWComp)
|
|
{
|
|
for ( UINT i=0; i<=_cComp; i++)
|
|
delete(_rpRWComp[i]);
|
|
free(_rpRWComp);
|
|
}
|
|
|
|
if(_rpRWMode)
|
|
{
|
|
for ( UINT i=0; i<=_cMode; i++)
|
|
delete(_rpRWMode[i]);
|
|
free(_rpRWMode);
|
|
}
|
|
}
|
|
|
|
|
|
// ICifRWFile implementation
|
|
|
|
// wrapper of the CCifFile functions
|
|
STDMETHODIMP CCifRWFile::QueryInterface(REFIID riid, LPVOID * ppvObj)
|
|
{
|
|
return (CCifFile::QueryInterface(riid, ppvObj));
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CCifRWFile::AddRef()
|
|
{
|
|
return(_cRef++);
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CCifRWFile::Release()
|
|
{
|
|
ULONG temp = --_cRef;
|
|
|
|
if(temp == 0)
|
|
delete this;
|
|
return temp;
|
|
}
|
|
|
|
STDMETHODIMP CCifRWFile::EnumComponents(IEnumCifComponents **pp, DWORD dwFilter, LPVOID pv)
|
|
{
|
|
CCifComponentEnum *pce;
|
|
HRESULT hr = E_FAIL;
|
|
|
|
*pp = 0;
|
|
|
|
pce = new CCifComponentEnum((CCifComponent **)_rpRWComp, dwFilter, PARENTTYPE_CIF, NULL);
|
|
if(pce)
|
|
{
|
|
*pp = (IEnumCifComponents *) pce;
|
|
(*pp)->AddRef();
|
|
hr = NOERROR;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CCifRWFile::FindComponent(LPCSTR pszID, ICifComponent **p)
|
|
{
|
|
CCifRWComponent *pcomp;
|
|
UINT i = 0;
|
|
|
|
*p = 0;
|
|
if(_rpRWComp)
|
|
{
|
|
for(pcomp = _rpRWComp[i]; pcomp != 0; pcomp = _rpRWComp[++i])
|
|
if(pcomp->IsID(pszID))
|
|
{
|
|
CCifComponent *ptmp;
|
|
|
|
ptmp = (CCifComponent *)pcomp;
|
|
*p = (ICifComponent *) ptmp;
|
|
return NOERROR;
|
|
}
|
|
}
|
|
return E_FAIL;
|
|
}
|
|
|
|
STDMETHODIMP CCifRWFile::EnumGroups(IEnumCifGroups **pp, DWORD dwFilter, LPVOID pv)
|
|
{
|
|
CCifGroupEnum *pge;
|
|
HRESULT hr = E_FAIL;
|
|
|
|
*pp = 0;
|
|
|
|
pge = new CCifGroupEnum((CCifGroup **)_rpRWGroup, dwFilter);
|
|
if(pge)
|
|
{
|
|
*pp = (IEnumCifGroups *) pge;
|
|
(*pp)->AddRef();
|
|
hr = NOERROR;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CCifRWFile::FindGroup(LPCSTR pszID, ICifGroup **p)
|
|
{
|
|
CCifRWGroup *pgrp;
|
|
UINT i = 0;
|
|
|
|
*p = 0;
|
|
if(_rpRWGroup)
|
|
{
|
|
for(pgrp = _rpRWGroup[i]; pgrp != 0; pgrp = _rpRWGroup[++i])
|
|
if(pgrp->IsID(pszID))
|
|
{
|
|
CCifGroup *ptmp;
|
|
|
|
ptmp = (CCifGroup *)pgrp;
|
|
|
|
*p = (ICifGroup *) ptmp;
|
|
return NOERROR;
|
|
}
|
|
}
|
|
return E_FAIL;
|
|
|
|
}
|
|
|
|
STDMETHODIMP CCifRWFile::EnumModes(IEnumCifModes **pp, DWORD dwFilter, LPVOID pv)
|
|
{
|
|
CCifModeEnum *pme;
|
|
HRESULT hr = E_FAIL;
|
|
|
|
*pp = 0;
|
|
|
|
pme = new CCifModeEnum((CCifMode **)_rpRWMode, dwFilter);
|
|
if(pme)
|
|
{
|
|
*pp = (IEnumCifModes *) pme;
|
|
(*pp)->AddRef();
|
|
hr = NOERROR;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CCifRWFile::FindMode(LPCSTR pszID, ICifMode **p)
|
|
{
|
|
CCifRWMode *pmode;
|
|
UINT i = 0;
|
|
|
|
*p = 0;
|
|
if(_rpRWMode)
|
|
{
|
|
for(pmode = _rpRWMode[i]; pmode != 0; pmode = _rpRWMode[++i])
|
|
if(pmode->IsID(pszID))
|
|
{
|
|
CCifMode *ptmp;
|
|
|
|
ptmp = (CCifMode *)pmode;
|
|
|
|
*p = (ICifMode *) ptmp;
|
|
return NOERROR;
|
|
}
|
|
}
|
|
|
|
return E_FAIL;
|
|
}
|
|
|
|
STDMETHODIMP CCifRWFile::GetDescription(LPSTR pszDesc, DWORD dwSize)
|
|
{
|
|
return(CCifFile::GetDescription(pszDesc, dwSize));
|
|
}
|
|
|
|
STDMETHODIMP CCifRWFile::GetDetDlls(LPSTR pszDlls, DWORD dwSize)
|
|
{
|
|
return(CCifFile::GetDetDlls(pszDlls, dwSize));
|
|
}
|
|
|
|
|
|
STDMETHODIMP CCifRWFile::SetDescription(LPCSTR pszDesc)
|
|
{
|
|
return(WriteTokenizeString(_szCifPath, "Version", DISPLAYNAME_KEY, pszDesc));
|
|
}
|
|
|
|
STDMETHODIMP CCifRWFile::CreateComponent(LPCSTR pszID, ICifRWComponent **p)
|
|
{
|
|
CCifRWComponent *prwcomp;
|
|
CCifRWComponent **ppRWCompPreFail;
|
|
BOOL bFound = FALSE;
|
|
UINT i = 0;
|
|
|
|
*p = 0;
|
|
for(prwcomp = _rpRWComp[i]; prwcomp != 0; prwcomp = _rpRWComp[++i])
|
|
{
|
|
if(prwcomp->IsID(pszID))
|
|
{
|
|
*p = (ICifRWComponent*)prwcomp;
|
|
bFound = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// create the new component
|
|
if (!bFound)
|
|
{
|
|
prwcomp = new CCifRWComponent(pszID, this);
|
|
if (!prwcomp)
|
|
return E_OUTOFMEMORY;
|
|
|
|
// check to see if we need to grow the array size
|
|
if (_cCompUnused <= 0)
|
|
{
|
|
// growing the array size to acomdate the new component
|
|
ppRWCompPreFail = _rpRWComp;
|
|
#pragma prefast(suppress: 308, "PREfast noise - pointer was saved before")
|
|
_rpRWComp = (CCifRWComponent **) realloc(_rpRWComp, sizeof(CCifRWComponent **)*(i+10));
|
|
if (_rpRWComp)
|
|
{
|
|
_cCompUnused = 9; // terminator used up one slot and the new comp use the one, s
|
|
}
|
|
else
|
|
{
|
|
if(ppRWCompPreFail)
|
|
{
|
|
for ( UINT i=0; i<=_cComp; i++)
|
|
delete(ppRWCompPreFail[i]);
|
|
free(ppRWCompPreFail);
|
|
}
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
_rpRWComp[i] = prwcomp;
|
|
_rpRWComp[i+1] = 0;
|
|
_cCompUnused--;
|
|
_cComp++;
|
|
*p = (ICifRWComponent*)prwcomp;
|
|
WritePrivateProfileString(pszID, ENTRYTYPE_KEY, ENTRYTYPE_COMP, _szCifPath);
|
|
|
|
}
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
STDMETHODIMP CCifRWFile::CreateGroup(LPCSTR pszID, ICifRWGroup **p)
|
|
{
|
|
CCifRWGroup *prwgroup;
|
|
CCifRWGroup **ppwgroupPreFail;
|
|
BOOL bFound = FALSE;
|
|
UINT i = 0;
|
|
|
|
*p = 0;
|
|
for(prwgroup = _rpRWGroup[i]; prwgroup != 0; prwgroup = _rpRWGroup[++i])
|
|
{
|
|
if(prwgroup->IsID(pszID))
|
|
{
|
|
*p = (ICifRWGroup *)prwgroup;
|
|
bFound = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// create the new component
|
|
if (!bFound)
|
|
{
|
|
prwgroup = new CCifRWGroup(pszID, i+1, this);
|
|
if (!prwgroup)
|
|
return E_OUTOFMEMORY;
|
|
|
|
// check to see if we need to grow the array size
|
|
if (_cGroupUnused <= 0)
|
|
{
|
|
ppwgroupPreFail = _rpRWGroup;
|
|
// growing the array size to acomdate the new component
|
|
#pragma prefast(suppress: 308, "PREfast noise - pointer was saved before")
|
|
_rpRWGroup = (CCifRWGroup **) realloc(_rpRWGroup, sizeof(CCifRWGroup **)*(i+10));
|
|
if (_rpRWGroup)
|
|
{
|
|
_cGroupUnused = 9;
|
|
}
|
|
else
|
|
{
|
|
if(ppwgroupPreFail)
|
|
{
|
|
for ( UINT i=0; i<=_cGroup; i++)
|
|
delete(ppwgroupPreFail[i]);
|
|
free(ppwgroupPreFail);
|
|
}
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
_rpRWGroup[i] = prwgroup;
|
|
_rpRWGroup[i+1] = 0;
|
|
_cGroupUnused--;
|
|
_cGroup++;
|
|
*p = (ICifRWGroup *)prwgroup;
|
|
WritePrivateProfileString(pszID, ENTRYTYPE_KEY, ENTRYTYPE_GROUP, _szCifPath);
|
|
|
|
}
|
|
return NOERROR;
|
|
|
|
}
|
|
|
|
STDMETHODIMP CCifRWFile::CreateMode(LPCSTR pszID, ICifRWMode **p)
|
|
{
|
|
CCifRWMode *prwmode;
|
|
CCifRWMode **prwmodePreFail;
|
|
BOOL bFound = FALSE;
|
|
UINT i = 0;
|
|
|
|
*p = 0;
|
|
for(prwmode = _rpRWMode[i]; prwmode != 0; prwmode = _rpRWMode[++i])
|
|
{
|
|
if(prwmode->IsID(pszID))
|
|
{
|
|
*p = (ICifRWMode *)prwmode;
|
|
bFound = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// create the new component
|
|
if (!bFound)
|
|
{
|
|
prwmode = new CCifRWMode(pszID, this);
|
|
if (!prwmode)
|
|
return E_OUTOFMEMORY;
|
|
|
|
// check to see if we need to grow the array size
|
|
if (_cModeUnused <= 0)
|
|
{
|
|
prwmodePreFail = _rpRWMode;
|
|
// growing the array size to acomdate the new component
|
|
#pragma prefast(suppress: 308, "PREfast noise - pointer was saved before")
|
|
_rpRWMode = (CCifRWMode **) realloc(_rpRWMode, sizeof(CCifRWMode **)*(i+10));
|
|
if (_rpRWMode)
|
|
{
|
|
_cModeUnused = 9;
|
|
}
|
|
else
|
|
{
|
|
if(prwmodePreFail)
|
|
{
|
|
for ( UINT i=0; i<=_cMode; i++)
|
|
delete(prwmodePreFail[i]);
|
|
free(prwmodePreFail);
|
|
}
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
_rpRWMode[i] = prwmode;
|
|
_rpRWMode[i+1] = 0;
|
|
_cModeUnused--;
|
|
_cMode++;
|
|
*p = (ICifRWMode *)prwmode;
|
|
WritePrivateProfileString(pszID, ENTRYTYPE_KEY, ENTRYTYPE_MODE, _szCifPath);
|
|
|
|
}
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
STDMETHODIMP CCifRWFile::DeleteComponent(LPCSTR pszID)
|
|
{
|
|
CCifRWComponent *prwcomp;
|
|
BOOL bFound = FALSE;
|
|
UINT i = 0;
|
|
|
|
for(prwcomp = _rpRWComp[i]; prwcomp != 0; prwcomp = _rpRWComp[++i])
|
|
{
|
|
if(prwcomp->IsID(pszID))
|
|
{
|
|
bFound = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Delete the component
|
|
if (bFound)
|
|
{
|
|
delete(prwcomp);
|
|
for ( UINT j=i+1; j<=_cComp; j++)
|
|
{
|
|
_rpRWComp[i] = _rpRWComp[j];
|
|
i= j;
|
|
}
|
|
_rpRWComp[i] = 0;
|
|
_cCompUnused++;
|
|
_cComp--;
|
|
|
|
}
|
|
|
|
return (WritePrivateProfileString(pszID, NULL, NULL, _szCifPath)?NOERROR:E_FAIL);
|
|
}
|
|
|
|
STDMETHODIMP CCifRWFile::DeleteGroup(LPCSTR pszID)
|
|
{
|
|
CCifRWGroup *prwgroup;
|
|
BOOL bFound = FALSE;
|
|
UINT i = 0;
|
|
|
|
for(prwgroup = _rpRWGroup[i]; prwgroup != 0; prwgroup = _rpRWGroup[++i])
|
|
{
|
|
if(prwgroup->IsID(pszID))
|
|
{
|
|
bFound = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Delete the Group
|
|
if (bFound)
|
|
{
|
|
delete(prwgroup);
|
|
for (UINT j=i+1; j<=_cGroup; j++)
|
|
{
|
|
_rpRWGroup[i] = _rpRWGroup[j];
|
|
i= j;
|
|
}
|
|
_rpRWGroup[i] = 0;
|
|
_cGroupUnused++;
|
|
_cGroup--;
|
|
}
|
|
|
|
return (WritePrivateProfileString(pszID, NULL, NULL, _szCifPath)?NOERROR:E_FAIL);
|
|
}
|
|
|
|
STDMETHODIMP CCifRWFile::DeleteMode(LPCSTR pszID)
|
|
{
|
|
CCifRWMode *prwmode;
|
|
BOOL bFound = FALSE;
|
|
UINT i = 0;
|
|
|
|
for(prwmode = _rpRWMode[i]; prwmode != 0; prwmode = _rpRWMode[++i])
|
|
{
|
|
if(prwmode->IsID(pszID))
|
|
{
|
|
bFound = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Delete the Mode
|
|
if (bFound)
|
|
{
|
|
delete(prwmode);
|
|
for (UINT j=i+1; j<=_cMode; j++)
|
|
{
|
|
_rpRWMode[i] = _rpRWMode[j];
|
|
i= j;
|
|
}
|
|
_rpRWMode[i] = 0;
|
|
_cModeUnused++;
|
|
_cMode--;
|
|
}
|
|
|
|
return (WritePrivateProfileString(pszID, NULL, NULL, _szCifPath)?NOERROR:E_FAIL);
|
|
}
|
|
|
|
STDMETHODIMP CCifRWFile::Flush()
|
|
{
|
|
WritePrivateProfileString(NULL, NULL, NULL, _szCifPath);
|
|
return NOERROR;
|
|
}
|