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.
 
 
 
 
 
 

4507 lines
128 KiB

//////////////////////////////////////////////////////////////////////////////////////////////
//
// ApplicationEntry.cpp
//
// Copyright (C) 1998, 1999 Microsoft Corporation. All rights reserved.
//
// Abstract :
//
// This is the implementation of IApplicationEntry
//
// History :
//
// 05/06/1999 luish Created
//
//////////////////////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <string.h>
#include "Resource.h"
#include "AppMan.h"
#include "Win32API.h"
#include "ApplicationManager.h"
#include "ExceptionHandler.h"
#include "Lock.h"
#include "AppManDebug.h"
#include "StructIdentifiers.h"
#include "Global.h"
//To flag as DBG_APPENTRY
#ifdef DBG_MODULE
#undef DBG_MODULE
#endif
#define DBG_MODULE DBG_APPENTRY
//
// Macro definition used within this source file only
//
#define VALIDATE_PROPERTY(a) m_InformationManager.ValidateApplicationPropertyWithIndex((a), &m_sApplicationData)
#define INVALIDATE_PROPERTY(a) m_InformationManager.InvalidateApplicationPropertyWithIndex((a), &m_sApplicationData)
#define RESET_ACTIONSTATE(a) m_dwCurrentAction = (a)
#define SET_ACTIONSTATE(a) m_dwCurrentAction = (a)
#define CHECK_ACTIONSTATE(a) ((a) == m_dwCurrentAction)
#define GET_ACTIONSTATE(a) (m_dwCurrentAction)
#define CLEAR_ACTIONSTATE(a) m_dwCurrentAction = CURRENT_ACTION_NONE
#define VALIDATE_STATE_FIELD() if (0 != m_sApplicationData.sBaseInfo.dwState) { VALIDATE_PROPERTY(IDX_PROPERTY_STATE); m_InformationManager.SetApplicationState(&m_sApplicationData, &m_sInstanceGuid); } else { INVALIDATE_PROPERTY(IDX_PROPERTY_STATE); }
#define CHECK_APPLICATIONSTATE(a) (m_sApplicationData.sBaseInfo.dwState & (a))
#define RESET_APPLICATIONSTATE(a) m_sApplicationData.sBaseInfo.dwState = (a); VALIDATE_STATE_FIELD()
#define SET_APPLICATIONSTATE(a) m_sApplicationData.sBaseInfo.dwState = (a); VALIDATE_STATE_FIELD()
#define GET_APPLICATIONSTATE() (m_sApplicationData.sBaseInfo.dwState)
#define CLEAR_APPLICATIONSTATE() m_sApplicationData.sBaseInfo.dwState = 0; VALIDATE_STATE_FIELD()
#define VALIDATE_CATEGORY_FIELD() if (APP_CATEGORY_NONE != m_sApplicationData.sBaseInfo.dwCategory) { VALIDATE_PROPERTY(IDX_PROPERTY_CATEGORY); } else { INVALIDATE_PROPERTY(IDX_PROPERTY_CATEGORY); }
#define CHECK_APPLICATIONCATEGORY(a) ((a) == (m_sApplicationData.sBaseInfo.dwCategory & (a)))
#define RESET_APPLICATIONCATEGORY(a) m_sApplicationData.sBaseInfo.dwCategory = (a); VALIDATE_CATEGORY_FIELD()
#define SET_APPLICATIONCATEGORY(a) m_sApplicationData.sBaseInfo.dwCategory |= (a); VALIDATE_CATEGORY_FIELD()
#define GET_APPLICATIONCATEGORY() (m_sApplicationData.sBaseInfo.dwCategory)
#define CLEAR_APPLICATIONCATEGORY() m_sApplicationData.sBaseInfo.dwCategory = APP_CATEGORY_NONE; VALIDATE_CATEGORY_FIELD()
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
CApplicationEntry::CApplicationEntry(void)
{
FUNCTION("CApplicationEntry::CApplicationEntry (void)");
m_dwLockCount = 0;
m_fIsInitialized = FALSE;
m_dwCurrentAction = CURRENT_ACTION_NONE;
m_lReferenceCount = 1;
m_hInstanceMutex = NULL;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
CApplicationEntry::~CApplicationEntry(void)
{
FUNCTION("CApplicationEntry::~CApplicationEntry (void)");
if (CURRENT_ACTION_NONE != m_dwCurrentAction)
{
APPLICATION_DATA sApplicationData;
ASSOCIATION_INFO sAssociationInfo;
DWORD dwIndex;
//
// We need to force a leave event
//
switch(m_dwCurrentAction)
{
case CURRENT_ACTION_DOWNSIZING
: m_InformationManager.LeaveWaitEvent(&m_sApplicationData, WAIT_FINALIZE_DOWNSIZE);
break;
case CURRENT_ACTION_REINSTALLING
: m_InformationManager.LeaveWaitEvent(&m_sApplicationData, WAIT_FINALIZE_REINSTALL);
break;
case CURRENT_ACTION_UNINSTALLING
: m_InformationManager.LeaveWaitEvent(&m_sApplicationData, WAIT_FINALIZE_UNINSTALL);
break;
case CURRENT_ACTION_SELFTESTING
: m_InformationManager.LeaveWaitEvent(&m_sApplicationData, WAIT_FINALIZE_SELFTEST);
break;
case (CURRENT_ACTION_SELFTESTING | CURRENT_ACTION_REINSTALLING)
: m_InformationManager.LeaveWaitEvent(&m_sApplicationData, WAIT_FINALIZE_REINSTALL);
m_InformationManager.LeaveWaitEvent(&m_sApplicationData, WAIT_FINALIZE_SELFTEST);
break;
}
//
// Before we do anything, make sure to unlock the parent apps
//
ZeroMemory(&sAssociationInfo, sizeof(sAssociationInfo));
dwIndex = 0;
while (S_OK == m_InformationManager.EnumAssociations(dwIndex, &sAssociationInfo))
{
if (0 == memcmp((LPVOID) &(sAssociationInfo.sChildGuid), (LPVOID) &(m_sApplicationData.sBaseInfo.sApplicationGuid), sizeof(GUID)))
{
//
// Get the associated application
//
ZeroMemory(&sApplicationData, sizeof(sApplicationData));
memcpy((LPVOID) &sApplicationData.sBaseInfo.sApplicationGuid, (LPVOID) &sAssociationInfo.sParentGuid, sizeof(GUID));
m_InformationManager.ValidateApplicationPropertyWithIndex(IDX_PROPERTY_GUID, &sApplicationData);
if (SUCCEEDED(m_InformationManager.GetApplicationData(&sApplicationData)))
{
//
// Unlock the parent applications
//
m_InformationManager.UnlockParentApplications(&sApplicationData, &m_sInstanceGuid);
}
}
dwIndex++;
}
//
// If the application was doing an initial install, abort will cause the application
// entry to be removed from the system
//
UnLockApplication();
}
// 4/12/2000(RichGr): If we've got a mutex, release and close it. We were leaking handles
// when swopping between AppManDiagTool tabs.
if (NULL != m_hInstanceMutex)
{
ReleaseMutex(m_hInstanceMutex);
CloseHandle(m_hInstanceMutex);
m_hInstanceMutex = NULL;
}
if (TRUE == m_fIsInitialized)
{
m_InformationManager.ForceUnlockApplicationData(&m_sApplicationData, &m_sInstanceGuid);
}
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
// TODO : the constructor requires that the incoming parameter
// be a const, we cannot lock the source object by calling Lock() (which is not
// a const method. So, when the copying occurs, the source object will not be locked
//
//////////////////////////////////////////////////////////////////////////////////////////////
CApplicationEntry::CApplicationEntry(const CApplicationEntry & /*refSourceObject*/) // Get rid of /W4 warnings.
{
FUNCTION("CApplicationEntry::CApplicationEntry (const CApplicationEntry &refSourceObject)");
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
CApplicationEntry & CApplicationEntry::operator = (const CApplicationEntry & /*refSourceObject*/)
{
return * this;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
// IUnknown interface implementation
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CApplicationEntry::QueryInterface(REFIID RefIID, LPVOID * ppVoidObject)
{
FUNCTION("CAppEntry::QueryInterface ()");
HRESULT hResult = S_OK;
///////////////////////////////////////////////////////////////////////////////////////
try
{
if (NULL == &RefIID)
{
THROW(E_UNEXPECTED);
}
if (NULL == ppVoidObject)
{
THROW(E_UNEXPECTED);
}
*ppVoidObject = NULL;
if ((RefIID == IID_IUnknown)||(RefIID == IID_ApplicationEntry))
{
*ppVoidObject = (LPVOID) this;
}
if (*ppVoidObject)
{
((LPUNKNOWN)*ppVoidObject)->AddRef();
}
else
{
hResult = E_NOINTERFACE;
}
}
///////////////////////////////////////////////////////////////////////////////////////
catch(CAppManExceptionHandler * pException)
{
hResult = pException->GetResultCode();
delete pException;
}
catch(...)
{
if ((NULL == &RefIID)||(NULL == ppVoidObject)||(IsBadWritePtr(ppVoidObject, sizeof(LPVOID))))
{
hResult = E_INVALIDARG;
}
else
{
hResult = E_UNEXPECTED;
}
}
///////////////////////////////////////////////////////////////////////////////////////
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
// IUnknown interface implementation
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG) CApplicationEntry::AddRef(void)
{
FUNCTION("CAppEntry::AddRef ()");
return InterlockedIncrement(&m_lReferenceCount);
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
// IUnknown interface implementation
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG) CApplicationEntry::Release(void)
{
FUNCTION("CAppEntry::Release ()");
DWORD dwReferenceCount;
dwReferenceCount = InterlockedDecrement(&m_lReferenceCount);
if (0 == dwReferenceCount)
{
delete this;
}
return dwReferenceCount;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CApplicationEntry::Initialize(void)
{
FUNCTION("CAppEntry::Initialize ()");
HRESULT hResult;
hResult = m_sCriticalSection.Initialize();
if (SUCCEEDED(hResult))
{
hResult = m_InformationManager.Initialize();
if (SUCCEEDED(hResult))
{
hResult = Clear();
if (SUCCEEDED(hResult))
{
m_fIsInitialized = TRUE;
}
}
}
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CApplicationEntry::SetInitializationLevel(DWORD dwInitializationLevel)
{
FUNCTION("CAppEntry::SetInitializationLevel ()");
m_dwInitializationLevel = dwInitializationLevel;
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_(DWORD) CApplicationEntry::GetActionState(void)
{
FUNCTION("CAppEntry::GetActionState ()");
return m_dwCurrentAction;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CApplicationEntry::LockApplication(void)
{
FUNCTION("CAppEntry::LockApplication ()");
HRESULT hResult;
hResult = m_InformationManager.LockApplicationData(&m_sApplicationData, &m_sInstanceGuid);
if (SUCCEEDED(hResult))
{
m_dwLockCount++;
}
else
{
THROW(APPMAN_E_APPLICATIONALREADYLOCKED);
}
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CApplicationEntry::UnLockApplication(void)
{
FUNCTION("CAppEntry::UnLockApplication ()");
HRESULT hResult;
hResult = m_InformationManager.UnlockApplicationData(&m_sApplicationData, &m_sInstanceGuid);
if (SUCCEEDED(hResult))
{
if (0 < m_dwLockCount)
{
m_dwLockCount--;
}
}
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CApplicationEntry::Clear(void)
{
FUNCTION("CAppEntry::Clear ()");
HRESULT hResult = S_OK;
///////////////////////////////////////////////////////////////////////////////////////
try
{
CLock sLock(&m_sCriticalSection);
DWORD dwIndex;
CHAR szString[MAX_PATH];
sLock.Lock();
//
// Make sure we are not in the middle of an action
//
if (CURRENT_ACTION_NONE != m_dwCurrentAction)
{
THROW(APPMAN_E_ACTIONINPROGRESS);
}
//
// Make sure this application instance is not locked
//
if (0 != m_dwLockCount)
{
THROW(APPMAN_E_APPLICATIONALREADYLOCKED);
}
//
// Ok, let's wipe the object
//
m_dwInitializationLevel = INIT_LEVEL_NONE;
ZeroMemory(&m_sApplicationData, sizeof(m_sApplicationData));
//
// Initialize the structure headers
//
m_sApplicationData.sAgingInfo.dwSize = sizeof(m_sApplicationData.sAgingInfo);
m_sApplicationData.sAgingInfo.dwStructId = AGING_STRUCT;
m_sApplicationData.sBaseInfo.dwSize = sizeof(m_sApplicationData.sBaseInfo);
m_sApplicationData.sBaseInfo.dwStructId = BASIC_APPINFO_STRUCT;
m_sApplicationData.sAssociation.dwSize = sizeof(m_sApplicationData.sAssociation);
m_sApplicationData.sAssociation.dwStructId = ASSOCIATION_STRUCT;
//
// Since this is a new object, let's initialize the crypto string
//
RandomInit();
for (dwIndex = 0; dwIndex < MAX_PATH_CHARCOUNT + 1; dwIndex++)
{
m_sApplicationData.wszStringProperty[APP_STRING_CRYPTO][dwIndex] = RandomWORD();
}
//
// If the object was assigned a mutex, kill the mutex
//
if (NULL != m_hInstanceMutex)
{
ReleaseMutex(m_hInstanceMutex);
CloseHandle(m_hInstanceMutex);
m_hInstanceMutex = NULL;
}
//
// Create the instance info and constructs
//
if (FAILED(CoCreateGuid(&m_sInstanceGuid)))
{
THROW(E_UNEXPECTED);
}
sprintf(szString, "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", m_sInstanceGuid.Data1, m_sInstanceGuid.Data2, m_sInstanceGuid.Data3, m_sInstanceGuid.Data4[0], m_sInstanceGuid.Data4[1], m_sInstanceGuid.Data4[2], m_sInstanceGuid.Data4[3], m_sInstanceGuid.Data4[4], m_sInstanceGuid.Data4[5], m_sInstanceGuid.Data4[6], m_sInstanceGuid.Data4[7]);
m_hInstanceMutex = CreateMutex(NULL, TRUE, szString);
sLock.UnLock();
}
///////////////////////////////////////////////////////////////////////////////////////
catch(CAppManExceptionHandler * pException)
{
hResult = pException->GetResultCode();
delete pException;
}
catch(...)
{
hResult = E_UNEXPECTED;
}
///////////////////////////////////////////////////////////////////////////////////////
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CApplicationEntry::ValidateGetPropertyParameters(const DWORD dwPropertyIndex, const DWORD dwPropertyModifiers, LPVOID lpData, const DWORD dwDataLen)
{
FUNCTION("CApplicationInfo::ValidateGetPropertyParameters (const DWORD dwPropertyIndex, const DWORD dwPropertyModifiers, LPVOID lpData, const DWORD dwDataLen)");
//
// Is the property currently initialized
//
if (S_OK != m_InformationManager.IsApplicationPropertyInitializedWithIndex(dwPropertyIndex, &m_sApplicationData))
{
THROW(APPMAN_E_PROPERTYNOTSET);
}
//
// Are we actually allowed to read this property
//
if (!(m_dwInitializationLevel & gPropertyInfo[dwPropertyIndex].dwReadMask))
{
THROW(APPMAN_E_PROPERTYNOTSET);
}
//
// The property being passed in is either a GUID, a DWORD or a string
//
if (APP_STRING_NONE == gPropertyInfo[dwPropertyIndex].dwStringId)
{
//
// dwPropertyModifers should be 0
//
if (0 != dwPropertyModifiers)
{
THROW(APPMAN_E_INVALIDPROPERTY);
}
//
// Make sure dwDataLen is correct
//
if (gPropertyInfo[dwPropertyIndex].dwMaxLen != dwDataLen)
{
THROW(APPMAN_E_INVALIDPROPERTYSIZE);
}
//
// Since the property is a GUID or a DWORD, the dwDatalen should be fixed
//
if ((NULL == lpData)||(IsBadWritePtr(lpData, dwDataLen)))
{
THROW(APPMAN_E_INVALIDPARAMETERS);
}
}
else
{
//
// Make sure dwDataLen is correct
//
if (0 == dwDataLen)
{
THROW(APPMAN_E_INVALIDPROPERTYSIZE);
}
//
// Determine the character count in the incoming string
//
if ((APP_PROPERTY_STR_ANSI != dwPropertyModifiers)&&(APP_PROPERTY_STR_UNICODE != dwPropertyModifiers)&&(0 != dwPropertyModifiers))
{
THROW(APPMAN_E_INVALIDPROPERTYVALUE);
}
//
// The property is a string
//
if ((NULL == lpData)||(IsBadWritePtr(lpData, dwDataLen)))
{
THROW(APPMAN_E_INVALIDPARAMETERS);
}
}
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CApplicationEntry::ValidateStringProperty(const DWORD dwPropertyIndex, const DWORD /*dwPropertyModifiers*/, LPCWSTR wszStringProperty)
{
FUNCTION("CAppEntry::ValidateStringProperty ()");
CWin32API sWin32API;
if ((IDX_PROPERTY_COMPANYNAME == dwPropertyIndex)||(IDX_PROPERTY_SIGNATURE == dwPropertyIndex))
{
//
// First we make sure that this is even a valid path
//
if (!sWin32API.IsValidFilename(wszStringProperty))
{
THROW(APPMAN_E_INVALIDPARAMETERS);
}
}
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CApplicationEntry::ValidateSetPropertyParameters(const DWORD dwPropertyIndex, const DWORD dwPropertyModifiers, LPCVOID lpData, const DWORD dwDataLen)
{
FUNCTION("CApplicationInfo::ValidateSetPropertyParameters (const DWORD dwPropertyIndex, const DWORD dwPropertyModifiers, LPCVOID lpData, const DWORD dwDataLen)");
DWORD dwCharCount = 0;
//
// Determine whether or not we are allowed to set this property at this time
//
if (!(m_dwCurrentAction & gPropertyInfo[dwPropertyIndex].dwWriteMask))
{
THROW(APPMAN_E_READONLYPROPERTY);
}
//
// This is a special case when APP_PROPERTY_EXECUTECMDLINE is used. If the category has the
// APP_CATEGORY_PATCH or APP_CATEGORY_DATA, then the APP_PROPERTY_EXECUTECMDLINE is
// not setable
//
if (((APP_CATEGORY_PATCH | APP_CATEGORY_DATA) & m_sApplicationData.sBaseInfo.dwCategory)&&(IDX_PROPERTY_EXECUTECMDLINE == dwPropertyIndex))
{
THROW(APPMAN_E_READONLYPROPERTY);
}
//
// The property being passed in is either a GUID/DWORD or a string
//
if (APP_STRING_NONE == gPropertyInfo[dwPropertyIndex].dwStringId)
{
//
// dwPropertyModifers should be 0
//
if (0 != dwPropertyModifiers)
{
THROW(APPMAN_E_INVALIDPROPERTY);
}
//
// Make sure dwDataLen is correct
//
if (gPropertyInfo[dwPropertyIndex].dwMaxLen != dwDataLen)
{
THROW(APPMAN_E_INVALIDPROPERTYSIZE);
}
//
// Since the property is a GUID or a DWORD, the dwDatalen should be fixed
//
if ((NULL == lpData)||(IsBadReadPtr(lpData, dwDataLen)))
{
THROW(APPMAN_E_INVALIDPARAMETERS);
}
}
else
{
//
// The property is a string.
//
if (NULL != lpData)
{
if (0 == dwDataLen)
{
THROW(APPMAN_E_INVALIDPROPERTYSIZE);
}
//
// First determine whether or not we can actual read the incoming string
//
if (IsBadReadPtr(lpData, dwDataLen))
{
THROW(APPMAN_E_INVALIDPARAMETERS);
}
//
// Determine the character count in the incoming string
//
if (APP_PROPERTY_STR_ANSI == dwPropertyModifiers)
{
dwCharCount = StrLenA((LPSTR) lpData);
}
else
{
if ((APP_PROPERTY_STR_UNICODE == dwPropertyModifiers)||(0 == dwPropertyModifiers))
{
dwCharCount = StrLenW((LPWSTR) lpData);
}
else
{
THROW(APPMAN_E_INVALIDPROPERTYVALUE);
}
}
//
// Determine whether or not the storage buffer are big enough for the incoming string
//
if (gPropertyInfo[dwPropertyIndex].dwMaxLen < dwCharCount)
{
THROW(APPMAN_E_OVERFLOW);
}
}
}
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CApplicationEntry::ValidateCommandLine(LPCWSTR wszRootPath, LPCWSTR wszCommandLine)
{
FUNCTION("CAppEntry::ValidateCommandLine ()");
CWin32API Win32API;
BOOL fApplicationExists = FALSE;
DWORD dwIndex, dwRootPathLen, dwCommandLineLen;
WCHAR wszTempPath[MAX_PATH_CHARCOUNT+1];
dwRootPathLen = wcslen(wszRootPath);
dwCommandLineLen = wcslen(wszCommandLine);
ZeroMemory(wszTempPath, sizeof(wszTempPath));
wcscpy(wszTempPath, wszCommandLine);
//
// Make sure that wszRootPath is the subpath of wszCommandLine
//
if (0 != _wcsnicmp(wszRootPath, wszCommandLine, dwRootPathLen))
{
return E_FAIL;
}
//
// At this point we go looking for .exe/.bat/.com and try to findfirstfile on the string
//
dwIndex = dwRootPathLen;
while ((FALSE == fApplicationExists)&&(dwIndex <= dwCommandLineLen))
{
//
// Slowly increment the wszTempPath string
//
wszTempPath[dwIndex] = wszCommandLine[dwIndex];
dwIndex++;
wszTempPath[dwIndex] = 0;
if (4 < dwIndex)
{
//
// Are the last 4 characters of wszTEmpPath ".EXE"
//
if (!_wcsnicmp(&wszTempPath[dwIndex-4], L".EXE", 4))
{
if (Win32API.FileExists(wszTempPath))
{
if (!(FILE_ATTRIBUTE_DIRECTORY & Win32API.FileAttributes(wszTempPath)))
{
fApplicationExists = TRUE;
}
}
}
//
// Are the last 4 characters of wszTEmpPath ".BAT"
//
if (!_wcsnicmp(&wszTempPath[dwIndex-4], L".BAT", 4))
{
if (Win32API.FileExists(wszTempPath))
{
if (!(FILE_ATTRIBUTE_DIRECTORY & Win32API.FileAttributes(wszTempPath)))
{
fApplicationExists = TRUE;
}
}
}
//
// Are the last 4 characters of wszTEmpPath ".COM"
//
if (!_wcsnicmp(&wszTempPath[dwIndex-4], L".COM", 4))
{
if (Win32API.FileExists(wszTempPath))
{
if (!(FILE_ATTRIBUTE_DIRECTORY & Win32API.FileAttributes(wszTempPath)))
{
fApplicationExists = TRUE;
}
}
}
//
// Are the last 4 characters of wszTEmpPath ".CMD"
//
if (!_wcsnicmp(&wszTempPath[dwIndex-4], L".CMD", 4))
{
if (Win32API.FileExists(wszTempPath))
{
if (!(FILE_ATTRIBUTE_DIRECTORY & Win32API.FileAttributes(wszTempPath)))
{
fApplicationExists = TRUE;
}
}
}
}
}
if (FALSE == fApplicationExists)
{
return S_FALSE;
}
else
{
return S_OK;
}
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
// TODO : Insert checking to make sure properties are not set at a bad time
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CApplicationEntry::SetProperty(const DWORD dwProperty, LPCVOID lpData, const DWORD dwDataLen)
{
FUNCTION("CAppEntry::SetProperty ()");
DPFMSG(MakeString("dwProperty = 0x%08x", dwProperty));
HRESULT hResult = S_OK;
///////////////////////////////////////////////////////////////////////////////////////
try
{
CLock sLock(&m_sCriticalSection);
DWORD dwFilteredProperty, dwPropertyModifiers, dwPropertyIndex;
DWORD dwStringIndex, dwCharCount;
if (FALSE == m_fIsInitialized)
{
THROW(APPMAN_E_NOTINITIALIZED);
}
sLock.Lock();
//
// Extract the filtered property value and the property modifier value
//
dwFilteredProperty = dwProperty & 0x0000ffff;
dwPropertyModifiers = dwProperty & 0xffff0000;
//
// Was the property passed in a valid property value
//
if (S_OK != m_InformationManager.IsValidApplicationProperty(dwFilteredProperty))
{
THROW(APPMAN_E_INVALIDPROPERTY);
}
//
// Get the internal property index for dwProperty
//
dwPropertyIndex = m_InformationManager.GetPropertyIndex(dwFilteredProperty);
//
// Are the dwProperty/lpData/dwDataLen parameters valid and properly sized
//
ValidateSetPropertyParameters(dwPropertyIndex, dwPropertyModifiers, lpData, dwDataLen);
//
// Get the property
//
dwStringIndex = gPropertyInfo[dwPropertyIndex].dwStringId;
if (APP_STRING_NONE == dwStringIndex)
{
switch(dwPropertyIndex)
{
case IDX_PROPERTY_GUID
: memcpy(&m_sApplicationData.sBaseInfo.sApplicationGuid, lpData, sizeof(GUID));
break;
case IDX_PROPERTY_STATE
: m_sApplicationData.sBaseInfo.dwState = *((LPDWORD) lpData);
if (APP_STATE_DOWNSIZED != m_sApplicationData.sBaseInfo.dwState)
{
THROW(APPMAN_E_INVALIDPROPERTYVALUE);
}
break;
case IDX_PROPERTY_CATEGORY
: m_sApplicationData.sBaseInfo.dwCategory = *((LPDWORD) lpData);
if (((~APP_CATEGORY_ALL) & m_sApplicationData.sBaseInfo.dwCategory)||(!(0x0000ffff & m_sApplicationData.sBaseInfo.dwCategory)))
{
THROW(APPMAN_E_INVALIDPROPERTYVALUE);
}
break;
case IDX_PROPERTY_ESTIMATEDINSTALLKILOBYTES
: m_sApplicationData.sBaseInfo.dwReservedKilobytes = *((LPDWORD) lpData);
break;
case IDX_PROPERTY_NONREMOVABLEKILOBYTES
:
break;
case IDX_PROPERTY_REMOVABLEKILOBYTES
:
break;
case IDX_PROPERTY_INSTALLDATE:
case IDX_PROPERTY_LASTUSEDDATE
: THROW(APPMAN_E_READONLYPROPERTY);
break;
default
: THROW(E_UNEXPECTED);
break;
}
}
else
{
//
// Are we dealing with the APP_PROPERTY_ROOTPATH
//
if (IDX_PROPERTY_ROOTPATH == dwPropertyIndex)
{
DWORD dwAdvancedMode = 0;
m_InformationManager.GetAdvancedMode(&dwAdvancedMode);
if (0 == dwAdvancedMode)
{
THROW(APPMAN_E_READONLYPROPERTY);
}
else
{
if (0 != m_sApplicationData.sAssociation.dwAssociationType)
{
THROW(APPMAN_E_READONLYPROPERTY);
}
}
}
//
// Make ANSI into UNICODE string if required
//
if (APP_PROPERTY_STR_ANSI & dwProperty)
{
dwCharCount = StrLenA((LPSTR) lpData);
CWin32API::MultiByteToWideChar((LPCSTR) lpData, dwDataLen, m_sApplicationData.wszStringProperty[dwStringIndex], MAX_PATH_CHARCOUNT);
}
else
{
dwCharCount = StrLenW((LPWSTR) lpData);
memcpy((LPVOID) m_sApplicationData.wszStringProperty[dwStringIndex], (LPVOID) lpData, dwDataLen);
}
//
// Make sure that the value we have just set is a valid string
//
ValidateStringProperty(dwPropertyIndex, dwPropertyModifiers, m_sApplicationData.wszStringProperty[dwStringIndex]);
}
//
// Make sure the validate the newly set property
//
m_InformationManager.ValidateApplicationPropertyWithIndex(dwPropertyIndex, &m_sApplicationData);
sLock.UnLock();
}
///////////////////////////////////////////////////////////////////////////////////////
catch(CAppManExceptionHandler * pException)
{
hResult = pException->GetResultCode();
delete pException;
}
catch(...)
{
hResult = E_UNEXPECTED;
}
///////////////////////////////////////////////////////////////////////////////////////
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CApplicationEntry::GetProperty(const DWORD dwProperty, LPVOID lpData, const DWORD dwDataLen)
{
FUNCTION("CAppEntry::GetProperty ()");
DPFMSG(MakeString("dwProperty = 0x%08x", dwProperty));
HRESULT hResult = S_OK;
///////////////////////////////////////////////////////////////////////////////////////
try
{
CLock sLock(&m_sCriticalSection);
DWORD dwFilteredProperty, dwPropertyModifiers, dwPropertyIndex, dwCharCount, dwStringIndex;
if (FALSE == m_fIsInitialized)
{
THROW(APPMAN_E_NOTINITIALIZED);
}
sLock.Lock();
//
// Extract the filtered property value and the property modifier value
//
dwFilteredProperty = dwProperty & 0x0000ffff;
dwPropertyModifiers = dwProperty & 0xffff0000;
//
// Was the property passed in a valid property value
//
if (S_OK != m_InformationManager.IsValidApplicationProperty(dwFilteredProperty))
{
THROW(APPMAN_E_INVALIDPROPERTY);
}
//
// Get the internal property index for dwProperty
//
dwPropertyIndex = m_InformationManager.GetPropertyIndex(dwFilteredProperty);
//
// Are the dwProperty/lpData/dwDataLen parameters valid and properly sized
//
ValidateGetPropertyParameters(dwPropertyIndex, dwPropertyModifiers, lpData, dwDataLen);
//
// Get the property
//
dwStringIndex = gPropertyInfo[dwPropertyIndex].dwStringId;
if (APP_STRING_NONE == dwStringIndex)
{
switch(dwPropertyIndex)
{
case IDX_PROPERTY_GUID
: memcpy((LPVOID) lpData, (LPVOID) &m_sApplicationData.sBaseInfo.sApplicationGuid, sizeof(GUID));
break;
case IDX_PROPERTY_STATE
: *(LPDWORD)lpData = m_sApplicationData.sBaseInfo.dwState;
break;
case IDX_PROPERTY_CATEGORY
: *(LPDWORD)lpData = m_sApplicationData.sBaseInfo.dwCategory;
break;
case IDX_PROPERTY_ESTIMATEDINSTALLKILOBYTES
: *(LPDWORD)lpData = m_sApplicationData.sBaseInfo.dwReservedKilobytes;
break;
case IDX_PROPERTY_NONREMOVABLEKILOBYTES
: *(LPDWORD)lpData = m_sApplicationData.sBaseInfo.dwNonRemovableKilobytes;
break;
case IDX_PROPERTY_REMOVABLEKILOBYTES
: *(LPDWORD)lpData = m_sApplicationData.sBaseInfo.dwRemovableKilobytes;
break;
case IDX_PROPERTY_INSTALLDATE
: memcpy((LPVOID) lpData, (LPVOID) &m_sApplicationData.sAgingInfo.stInstallDate, sizeof(SYSTEMTIME));
break;
case IDX_PROPERTY_LASTUSEDDATE
: memcpy((LPVOID) lpData, (LPVOID) &m_sApplicationData.sAgingInfo.stLastUsedDate, sizeof(SYSTEMTIME));
break;
case IDX_PROPERTY_PIN
: *(LPDWORD)lpData = m_sApplicationData.sBaseInfo.dwPinState;
break;
default
: THROW(E_UNEXPECTED);
break;
}
}
else
{
if (APP_PROPERTY_STR_ANSI == dwPropertyModifiers)
{
dwCharCount = StrLenW((LPWSTR) m_sApplicationData.wszStringProperty[dwStringIndex]);
if (dwDataLen < dwCharCount)
{
THROW(APPMAN_E_OVERFLOW);
}
CWin32API::WideCharToMultiByte((LPCWSTR) m_sApplicationData.wszStringProperty[dwStringIndex], MAX_PATH_CHARCOUNT, (LPSTR) lpData, dwDataLen);
}
else
{
dwCharCount = StrLenW((LPWSTR) m_sApplicationData.wszStringProperty[dwStringIndex]);
if (dwDataLen < (dwCharCount*2))
{
THROW(APPMAN_E_OVERFLOW);
}
memcpy((LPVOID) lpData, (LPVOID) m_sApplicationData.wszStringProperty[dwStringIndex], dwCharCount*2);
}
}
sLock.UnLock();
}
///////////////////////////////////////////////////////////////////////////////////////
catch(CAppManExceptionHandler * pException)
{
hResult = pException->GetResultCode();
delete pException;
}
catch(...)
{
hResult = E_UNEXPECTED;
}
///////////////////////////////////////////////////////////////////////////////////////
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
// The InitializeInstall() method will do the following actions before successfully returning.
// If any of these steps fail, the method will return a failure.
//
// (1) Make sure the application object is not undergoing any other action
// (2) Make sure that APP_PROPERTY_TYPE is set
// (3) Make sure that APP_PROPERTY_SIGNATURE is set
// (4) Make sure that APP_PROPERTY_ESTIMATED_INSTALL_SIZE is set
// (5) Make sure that the application is not already installed
// (6) Make sure to set the state of the application to APP_STATE_INSTALLING
// (7) Explicitly call m_InformationManager.SetApplicationInfo() in order to prevent
// step (8) from happening in case of a failure
// (8) Make sure to set the state of the m_dwCurrentAction
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CApplicationEntry::InitializeInstall(void)
{
FUNCTION("CAppEntry::InitializeInstall ()");
HRESULT hResult = S_OK;
BOOL fParentLocked = FALSE;
///////////////////////////////////////////////////////////////////////////////////////
try
{
CWin32API Win32API;
DWORD dwIndex, dwReservedKilobytes, dwAdvancedMode;
BOOL fApplicationRootExists;
APPLICATION_DATA sApplicationData;
DEVICE_RECORD sDeviceRecord;
WCHAR wszRootPath[5];
GUID sPathGuid;
//
// Make sure this object is not currently being used in another action
//
if (!CHECK_ACTIONSTATE(CURRENT_ACTION_NONE))
{
THROW(APPMAN_E_ACTIONINPROGRESS);
}
//
// Get the advanced mode
//
m_InformationManager.GetAdvancedMode(&dwAdvancedMode);
//
// Make sure the required fields are present
//
if (S_OK != m_InformationManager.IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_COMPANYNAME, &m_sApplicationData))
{
THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
}
if (S_OK != m_InformationManager.IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_SIGNATURE, &m_sApplicationData))
{
THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
}
if (S_OK != m_InformationManager.IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_CATEGORY, &m_sApplicationData))
{
THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
}
if (S_OK != m_InformationManager.IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_ESTIMATEDINSTALLKILOBYTES, &m_sApplicationData))
{
THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
}
if ((0 < dwAdvancedMode)&&(0 == m_sApplicationData.sAssociation.dwAssociationType))
{
if (S_OK != m_InformationManager.IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_ROOTPATH, &m_sApplicationData))
{
THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
}
else
{
if (FALSE == Win32API.FileExists(m_sApplicationData.wszStringProperty[APP_STRING_APPROOTPATH]))
{
//
// We want to see if we can even create this directory. If we can, delete it right
// away in order to make sure that an empty directory is not created until we absolutely
// have to
//
if (!Win32API.CreateDirectory(m_sApplicationData.wszStringProperty[APP_STRING_APPROOTPATH], TRUE))
{
THROW(APPMAN_E_INVALIDROOTPATH);
}
else
{
Win32API.RemoveDirectory(m_sApplicationData.wszStringProperty[APP_STRING_APPROOTPATH]);
}
}
}
}
//
// Since this should be a new application
//
m_sApplicationData.sBaseInfo.dwPinState = FALSE;
VALIDATE_PROPERTY(IDX_PROPERTY_PIN);
//
// Is this is a brand new application entry
//
if (S_FALSE == m_InformationManager.CheckApplicationExistance(&m_sApplicationData))
{
DWORD dwDeviceIndex;
WCHAR wszAppManRoot[MAX_PATH_CHARCOUNT];
WCHAR wszAppManSetup[MAX_PATH_CHARCOUNT];
WCHAR wszCategory[MAX_PATH_CHARCOUNT];
//
// Initialize the path substrings
//
(OS_VERSION_9x & Win32API.GetOSVersion()) ? GetResourceStringW(IDS_APPMAN9x, wszAppManRoot, MAX_PATH_CHARCOUNT): GetResourceStringW(IDS_APPMANNT, wszAppManRoot, MAX_PATH_CHARCOUNT);
GetResourceStringW(IDS_APPMAN, wszAppManSetup, MAX_PATH_CHARCOUNT);
switch(GET_APPLICATIONCATEGORY())
{
case APP_CATEGORY_MISC:
case APP_CATEGORY_NONE
: ZeroMemory(wszCategory, sizeof(wszCategory));
break;
case APP_CATEGORY_ENTERTAINMENT
: GetResourceStringW(IDS_ENTERTAINMENT, wszCategory, MAX_PATH_CHARCOUNT);
break;
case APP_CATEGORY_PRODUCTIVITY
: GetResourceStringW(IDS_PRODUCTIVITY, wszCategory, MAX_PATH_CHARCOUNT);
break;
case APP_CATEGORY_PUBLISHING
: GetResourceStringW(IDS_PUBLISHING, wszCategory, MAX_PATH_CHARCOUNT);
break;
case APP_CATEGORY_SCIENTIFIC
: GetResourceStringW(IDS_SCIENTIFIC, wszCategory, MAX_PATH_CHARCOUNT);
break;
case APP_CATEGORY_AUTHORING
: GetResourceStringW(IDS_AUTHORING, wszCategory, MAX_PATH_CHARCOUNT);
break;
case APP_CATEGORY_MEDICAL
: GetResourceStringW(IDS_MEDICAL, wszCategory, MAX_PATH_CHARCOUNT);
break;
case APP_CATEGORY_BUSINESS
: GetResourceStringW(IDS_BUSINESS, wszCategory, MAX_PATH_CHARCOUNT);
break;
case APP_CATEGORY_FINANCIAL
: GetResourceStringW(IDS_FINANCIAL, wszCategory, MAX_PATH_CHARCOUNT);
break;
case APP_CATEGORY_EDUCATIONAL
: GetResourceStringW(IDS_EDUCATIONAL, wszCategory, MAX_PATH_CHARCOUNT);
break;
case APP_CATEGORY_REFERENCE
: GetResourceStringW(IDS_REFERENCE, wszCategory, MAX_PATH_CHARCOUNT);
break;
case APP_CATEGORY_WEB
: GetResourceStringW(IDS_WEB, wszCategory, MAX_PATH_CHARCOUNT);
break;
case APP_CATEGORY_DEVELOPMENTTOOL
: GetResourceStringW(IDS_DEVTOOL, wszCategory, MAX_PATH_CHARCOUNT);
break;
case APP_CATEGORY_MULTIMEDIA
: GetResourceStringW(IDS_MULTIMEDIA, wszCategory, MAX_PATH_CHARCOUNT);
break;
case APP_CATEGORY_VIRUSCLEANER
: GetResourceStringW(IDS_VIRUSCLEANER, wszCategory, MAX_PATH_CHARCOUNT);
break;
case APP_CATEGORY_CONNECTIVITY
: GetResourceStringW(IDS_CONNECTIVITY, wszCategory, MAX_PATH_CHARCOUNT);
break;
}
//
// Initialize the aging information
//
m_sApplicationData.sAgingInfo.dwInstallCost = 0;
m_sApplicationData.sAgingInfo.dwReInstallCount = 0;
m_sApplicationData.sAgingInfo.dwUsageCount = 0;
GetLocalTime(&(m_sApplicationData.sAgingInfo.stInstallDate));
VALIDATE_PROPERTY(IDX_PROPERTY_INSTALLDATE);
GetLocalTime(&(m_sApplicationData.sAgingInfo.stLastUsedDate));
VALIDATE_PROPERTY(IDX_PROPERTY_LASTUSEDDATE);
//
// Is this application associated with anything at all
//
if (0 != m_sApplicationData.sAssociation.dwAssociationType)
{
//
// Go get the application data of the associated application
//
memcpy((LPVOID) &sApplicationData.sBaseInfo.sApplicationGuid, (LPVOID) &m_sApplicationData.sAssociation.sParentGuid, sizeof(GUID));
m_InformationManager.ValidateApplicationPropertyWithIndex(IDX_PROPERTY_GUID, &sApplicationData);
hResult = m_InformationManager.GetApplicationData(&sApplicationData);
if (FAILED(hResult))
{
THROW(APPMAN_E_INVALIDASSOCIATION);
}
//
// Make sure the parent is in a ready state
//
hResult = m_InformationManager.ReadyApplication(&sApplicationData);
if (FAILED(hResult))
{
THROW(APPMAN_E_APPLICATIONREQUIRED);
}
//
// Lock the parent applications
//
hResult = m_InformationManager.LockParentApplications(&sApplicationData, &m_sInstanceGuid);
if (FAILED(hResult))
{
THROW(hResult);
}
else
{
fParentLocked = TRUE;
}
//
// Go get the device index of the associated applications
//
memcpy((LPVOID) &sDeviceRecord.sDeviceGuid, (LPVOID) &sApplicationData.sBaseInfo.sDeviceGuid, sizeof(GUID));
hResult = m_InformationManager.GetDeviceInfo(&sDeviceRecord);
if (FAILED(hResult))
{
THROW(E_UNEXPECTED);
}
dwDeviceIndex = sDeviceRecord.sDeviceInfo.dwDeviceIndex;
//
// Go get the space required to install the application on the device
//
hResult = m_InformationManager.FreeSpaceOnDevice(&sDeviceRecord.sDeviceGuid, m_sApplicationData.sBaseInfo.dwReservedKilobytes);
if (FAILED(hResult))
{
THROW(APPMAN_E_NODISKSPACEAVAILABLE);
}
//
// Add the application to the database and then assign it a device. Note that we do
// not have to check for success code since these methods throw exceptions on error
//
m_InformationManager.AddApplicationData(&m_sApplicationData, &m_sInstanceGuid);
m_InformationManager.AssignDeviceToApplication(dwDeviceIndex, &m_sApplicationData);
//
// Lock the application
//
LockApplication();
//
// Setup the root paths and setup root paths depending on association type
//
switch(m_sApplicationData.sAssociation.dwAssociationType)
{
case APP_ASSOCIATION_INHERITBOTHPATHS // inherits both setup and application root paths
: memcpy((LPVOID) m_sApplicationData.wszStringProperty[APP_STRING_APPROOTPATH], sApplicationData.wszStringProperty[APP_STRING_APPROOTPATH], MAX_PATH_CHARCOUNT+1);
memcpy((LPVOID) m_sApplicationData.wszStringProperty[APP_STRING_SETUPROOTPATH], sApplicationData.wszStringProperty[APP_STRING_SETUPROOTPATH], MAX_PATH_CHARCOUNT+1);
VALIDATE_PROPERTY(IDX_PROPERTY_ROOTPATH);
VALIDATE_PROPERTY(IDX_PROPERTY_SETUPROOTPATH);
break;
case APP_ASSOCIATION_INHERITAPPROOTPATH // inherits application root path
: memcpy((LPVOID) m_sApplicationData.wszStringProperty[APP_STRING_APPROOTPATH], sApplicationData.wszStringProperty[APP_STRING_APPROOTPATH], MAX_PATH_CHARCOUNT+1);
if (FAILED(CoCreateGuid(&sPathGuid)))
{
THROW(E_UNEXPECTED);
}
swprintf(m_sApplicationData.wszStringProperty[APP_STRING_SETUPROOTPATH], L"%c:\\%s\\%s\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", dwDeviceIndex + 65, wszAppManRoot, wszAppManSetup, sPathGuid.Data1, sPathGuid.Data2, sPathGuid.Data3, sPathGuid.Data4[0], sPathGuid.Data4[1], sPathGuid.Data4[2], sPathGuid.Data4[3], sPathGuid.Data4[4], sPathGuid.Data4[5], sPathGuid.Data4[6], sPathGuid.Data4[7]);
VALIDATE_PROPERTY(IDX_PROPERTY_ROOTPATH);
VALIDATE_PROPERTY(IDX_PROPERTY_SETUPROOTPATH);
break;
case APP_ASSOCIATION_INHERITSETUPROOTPATH // inherits setup root path and is rooted within application root path
: swprintf(m_sApplicationData.wszStringProperty[APP_STRING_APPROOTPATH], L"%s\\%s", sApplicationData.wszStringProperty[APP_STRING_APPROOTPATH], m_sApplicationData.wszStringProperty[APP_STRING_SIGNATURE]);
VALIDATE_PROPERTY(IDX_PROPERTY_ROOTPATH);
memcpy((LPVOID) m_sApplicationData.wszStringProperty[APP_STRING_SETUPROOTPATH], sApplicationData.wszStringProperty[APP_STRING_SETUPROOTPATH], MAX_PATH_CHARCOUNT+1);
VALIDATE_PROPERTY(IDX_PROPERTY_SETUPROOTPATH);
break;
default
: THROW(APPMAN_E_INVALIDASSOCIATION);
break;
}
//
// Record the application guid within the association
//
memcpy((LPVOID) &m_sApplicationData.sAssociation.sChildGuid, (LPVOID) &m_sApplicationData.sBaseInfo.sApplicationGuid, sizeof(GUID));
//
// Set the application data into the registry
//
m_InformationManager.SetApplicationData(&m_sApplicationData, &m_sInstanceGuid);
//
// Add the association
//
m_InformationManager.AddAssociation(&m_sApplicationData.sAssociation);
}
else
{
//
// Are we in advanced mode
//
if (0 != dwAdvancedMode)
{
DWORD dwBaseIndex;
//
// Figure out where the first legal character is in the root path
//
dwBaseIndex = 0;
while ((dwBaseIndex < StrLenW(m_sApplicationData.wszStringProperty[APP_STRING_APPROOTPATH]))&&(!((65 <= m_sApplicationData.wszStringProperty[APP_STRING_APPROOTPATH][dwBaseIndex])&&(90 >= m_sApplicationData.wszStringProperty[APP_STRING_APPROOTPATH][dwBaseIndex]))&&(!((97 <= m_sApplicationData.wszStringProperty[APP_STRING_APPROOTPATH][dwBaseIndex])&&(122 >= m_sApplicationData.wszStringProperty[APP_STRING_APPROOTPATH][dwBaseIndex])))))
{
dwBaseIndex++;
}
if (!(dwBaseIndex < StrLenW(m_sApplicationData.wszStringProperty[APP_STRING_APPROOTPATH])))
{
THROW(APPMAN_E_INVALIDROOTPATH);
}
//
// Figure out which drive it is supposed to be in
//
dwIndex = 0;
do
{
dwDeviceIndex = dwIndex;
swprintf(wszRootPath, L"%c:\\", dwDeviceIndex + 65);
dwIndex++;
} while ((26 > dwIndex)&&(0 != _wcsnicmp(wszRootPath, &(m_sApplicationData.wszStringProperty[APP_STRING_APPROOTPATH][dwBaseIndex]), 3)));
//
// Did we fail to find a matching device string
//
if (26 <= dwIndex)
{
THROW(APPMAN_E_INVALIDROOTPATH);
}
//
// Go get the device index of the associated applications
//
hResult = m_InformationManager.GetDeviceInfoWithIndex(dwDeviceIndex, &sDeviceRecord);
if (FAILED(hResult))
{
THROW(E_UNEXPECTED);
}
//
// Go get the space required to install the application on the device
//
hResult = m_InformationManager.FreeSpaceOnDevice(&sDeviceRecord.sDeviceGuid, m_sApplicationData.sBaseInfo.dwReservedKilobytes);
if (FAILED(hResult))
{
THROW(APPMAN_E_NODISKSPACEAVAILABLE);
}
//
// Add the application to the database and then assign it a device. Note that we do
// not have to check for success code since these methods throw exceptions on error
//
m_InformationManager.AddApplicationData(&m_sApplicationData, &m_sInstanceGuid);
m_InformationManager.AssignDeviceToApplication(dwDeviceIndex, &m_sApplicationData);
//
// Lock the application
//
LockApplication();
//
// Setup the setup root paths depending on association type
//
if (FAILED(CoCreateGuid(&sPathGuid)))
{
THROW(E_UNEXPECTED);
}
swprintf(m_sApplicationData.wszStringProperty[APP_STRING_SETUPROOTPATH], L"%c:\\%s\\%s\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", dwDeviceIndex + 65, wszAppManRoot, wszAppManSetup, sPathGuid.Data1, sPathGuid.Data2, sPathGuid.Data3, sPathGuid.Data4[0], sPathGuid.Data4[1], sPathGuid.Data4[2], sPathGuid.Data4[3], sPathGuid.Data4[4], sPathGuid.Data4[5], sPathGuid.Data4[6], sPathGuid.Data4[7]);
VALIDATE_PROPERTY(IDX_PROPERTY_SETUPROOTPATH);
//
// Set the application data into the registry
//
m_InformationManager.SetApplicationData(&m_sApplicationData, &m_sInstanceGuid);
}
else
{
//
// Check to see if the application root path already exists on a device and if so,
// attempt to install the application on that device
//
fApplicationRootExists = FALSE;
dwDeviceIndex = 0xffffffff;
dwIndex = 2;
do
{
//
// Build the application root path
//
if (1 == StrLenW(wszCategory))
{
swprintf(m_sApplicationData.wszStringProperty[APP_STRING_APPROOTPATH], L"%c:\\%s\\%s\\%s", dwIndex + 65, wszAppManRoot, m_sApplicationData.wszStringProperty[APP_STRING_COMPANYNAME], m_sApplicationData.wszStringProperty[APP_STRING_SIGNATURE]);
}
else
{
swprintf(m_sApplicationData.wszStringProperty[APP_STRING_APPROOTPATH], L"%c:\\%s\\%s\\%s\\%s", dwIndex + 65, wszAppManRoot, wszCategory, m_sApplicationData.wszStringProperty[APP_STRING_COMPANYNAME], m_sApplicationData.wszStringProperty[APP_STRING_SIGNATURE]);
}
//
// Check to see whether or not it exists
//
swprintf(wszRootPath, L"%c:\\", dwIndex + 65);
if (DRIVE_FIXED == Win32API.GetDriveType(wszRootPath))
{
fApplicationRootExists = Win32API.FileExists(m_sApplicationData.wszStringProperty[APP_STRING_APPROOTPATH]);
if (TRUE == fApplicationRootExists)
{
dwDeviceIndex = dwIndex;
}
}
dwIndex++;
}
while ((FALSE == fApplicationRootExists)&&(26 > dwIndex));
//
// Go get the space
//
hResult = APPMAN_E_NODISKSPACEAVAILABLE;
if (0xffffffff != dwDeviceIndex)
{
//
// The root path of the application was found on device dwDeviceIndex. Is this
// device excluded
//
m_InformationManager.GetDeviceInfoWithIndex(dwDeviceIndex, &sDeviceRecord);
if (0 == (m_sApplicationData.sBaseInfo.dwCategory & sDeviceRecord.sDeviceInfo.dwApplicationCategoryExclusionMask))
{
hResult = m_InformationManager.FreeSpaceOnDevice(&sDeviceRecord.sDeviceGuid, m_sApplicationData.sBaseInfo.dwReservedKilobytes);
}
}
if (FAILED(hResult))
{
//
// We failed to get space on the device that contained the legacy application
// root path. Therefore, we fall back
//
hResult = m_InformationManager.GetSpace(m_sApplicationData.sBaseInfo.dwCategory, m_sApplicationData.sBaseInfo.dwReservedKilobytes, &dwDeviceIndex);
}
//
// Go get the space
//
if (SUCCEEDED(hResult))
{
//
// Add the application to the database and then assign it a device. Note that we do
// not have to check for success code since these methods throw exceptions on error
//
m_InformationManager.AddApplicationData(&m_sApplicationData, &m_sInstanceGuid);
m_InformationManager.AssignDeviceToApplication(dwDeviceIndex, &m_sApplicationData);
//
// Lock the application
//
LockApplication();
//
// Create the root paths
//
if (1 == StrLenW(wszCategory))
{
swprintf(m_sApplicationData.wszStringProperty[APP_STRING_APPROOTPATH], L"%c:\\%s\\%s\\%s", dwDeviceIndex + 65, wszAppManRoot, m_sApplicationData.wszStringProperty[APP_STRING_COMPANYNAME], m_sApplicationData.wszStringProperty[APP_STRING_SIGNATURE]);
}
else
{
swprintf(m_sApplicationData.wszStringProperty[APP_STRING_APPROOTPATH], L"%c:\\%s\\%s\\%s\\%s", dwDeviceIndex + 65, wszAppManRoot, wszCategory, m_sApplicationData.wszStringProperty[APP_STRING_COMPANYNAME], m_sApplicationData.wszStringProperty[APP_STRING_SIGNATURE]);
}
if (FAILED(CoCreateGuid(&sPathGuid)))
{
THROW(E_UNEXPECTED);
}
swprintf(m_sApplicationData.wszStringProperty[APP_STRING_SETUPROOTPATH], L"%c:\\%s\\%s\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", dwDeviceIndex + 65, wszAppManRoot, wszAppManSetup, sPathGuid.Data1, sPathGuid.Data2, sPathGuid.Data3, sPathGuid.Data4[0], sPathGuid.Data4[1], sPathGuid.Data4[2], sPathGuid.Data4[3], sPathGuid.Data4[4], sPathGuid.Data4[5], sPathGuid.Data4[6], sPathGuid.Data4[7]);
VALIDATE_PROPERTY(IDX_PROPERTY_ROOTPATH);
VALIDATE_PROPERTY(IDX_PROPERTY_SETUPROOTPATH);
//
// Set the Appplication Info
//
m_InformationManager.SetApplicationData(&m_sApplicationData, &m_sInstanceGuid);
}
else
{
THROW(APPMAN_E_NODISKSPACEAVAILABLE);
}
}
}
}
else
{
//
// Let's get the current information about this application
//
hResult = m_InformationManager.GetApplicationData(&m_sApplicationData);
if (FAILED(hResult))
{
THROW(E_UNEXPECTED);
}
//
// First we lock the application
//
LockApplication();
//
// Save the reserved space into dwReservedKilobytes temporarily
//
dwReservedKilobytes = m_sApplicationData.sBaseInfo.dwReservedKilobytes;
//
// Get the application information as registered within the database.
//
if (FAILED(m_InformationManager.GetApplicationData(&m_sApplicationData)))
{
SetInitializationLevel(INIT_LEVEL_BASIC);
THROW(E_UNEXPECTED);
}
//
// Restore the dwReservedKilobytes value
//
m_sApplicationData.sBaseInfo.dwReservedKilobytes = dwReservedKilobytes;
VALIDATE_PROPERTY(IDX_PROPERTY_ESTIMATEDINSTALLKILOBYTES);
//
// Make sure the app is in an APP_STATE_INSTALLING state
//
if (!CHECK_APPLICATIONSTATE(APP_STATE_INSTALLING))
{
SetInitializationLevel(INIT_LEVEL_BASIC);
THROW(APPMAN_E_APPLICATIONALREADYEXISTS);
}
//
// Go get the space
//
if (FAILED(m_InformationManager.FreeSpaceOnDevice(&(m_sApplicationData.sBaseInfo.sDeviceGuid), m_sApplicationData.sBaseInfo.dwReservedKilobytes)))
{
THROW(APPMAN_E_NODISKSPACEAVAILABLE);
}
}
//
// Create the root paths if required
//
if (FALSE == Win32API.FileExists(m_sApplicationData.wszStringProperty[APP_STRING_APPROOTPATH]))
{
Win32API.CreateDirectory(m_sApplicationData.wszStringProperty[APP_STRING_APPROOTPATH], TRUE);
}
if (FALSE == Win32API.FileExists(m_sApplicationData.wszStringProperty[APP_STRING_SETUPROOTPATH]))
{
Win32API.CreateDirectory(m_sApplicationData.wszStringProperty[APP_STRING_SETUPROOTPATH], TRUE);
}
//
// Record the original size of the root paths in order to compute the deltas during
// FinalizeInstall
//
ComputeOriginalApplicationSpaceInfo();
//
// Initialize some other properties
//
m_sApplicationData.sBaseInfo.dwRemovableKilobytes = 0;
m_sApplicationData.sBaseInfo.dwNonRemovableKilobytes = 0;
VALIDATE_PROPERTY(IDX_PROPERTY_REMOVABLEKILOBYTES);
VALIDATE_PROPERTY(IDX_PROPERTY_NONREMOVABLEKILOBYTES);
//
// Get the application record ready for installation
//
SET_APPLICATIONSTATE(APP_STATE_INSTALLING);
SET_ACTIONSTATE(CURRENT_ACTION_INSTALLING);
m_dwInitializationLevel = INIT_LEVEL_TOTAL;
}
///////////////////////////////////////////////////////////////////////////////////////
catch(CAppManExceptionHandler * pException)
{
//
// Make sure that if we have locked parents, we unlock them here
//
if (fParentLocked)
{
APPLICATION_DATA sApplicationData;
//
// Go get the application data of the associated application
//
memcpy((LPVOID) &sApplicationData.sBaseInfo.sApplicationGuid, (LPVOID) &m_sApplicationData.sAssociation.sParentGuid, sizeof(GUID));
m_InformationManager.ValidateApplicationPropertyWithIndex(IDX_PROPERTY_GUID, &sApplicationData);
hResult = m_InformationManager.GetApplicationData(&sApplicationData);
if (SUCCEEDED(hResult))
{
m_InformationManager.UnlockParentApplications(&sApplicationData, &m_sInstanceGuid);
}
}
//
// Make sure to record the hResult that caused the error
//
hResult = pException->GetResultCode();
delete pException;
}
catch(...)
{
//
// Make sure that if we have locked parents, we unlock them here
//
if (fParentLocked)
{
APPLICATION_DATA sApplicationData;
//
// Go get the application data of the associated application
//
memcpy((LPVOID) &sApplicationData.sBaseInfo.sApplicationGuid, (LPVOID) &m_sApplicationData.sAssociation.sParentGuid, sizeof(GUID));
m_InformationManager.ValidateApplicationPropertyWithIndex(IDX_PROPERTY_GUID, &sApplicationData);
hResult = m_InformationManager.GetApplicationData(&sApplicationData);
if (SUCCEEDED(hResult))
{
m_InformationManager.UnlockParentApplications(&sApplicationData, &m_sInstanceGuid);
}
}
hResult = E_UNEXPECTED;
}
///////////////////////////////////////////////////////////////////////////////////////
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CApplicationEntry::FinalizeInstall(void)
{
FUNCTION("CAppEntry::FinalizeInstall ()");
HRESULT hResult = S_OK;
///////////////////////////////////////////////////////////////////////////////////////
try
{
CWin32API sWin32API;
DWORD dwIndex;//, dwActualApplicationSize; // Get rid of /W4 warning.
APPLICATION_DATA sApplicationData;
ASSOCIATION_INFO sAssociationInfo;
//
// Make sure we are currently installing
//
if (!CHECK_ACTIONSTATE(CURRENT_ACTION_INSTALLING))
{
THROW(APPMAN_E_ACTIONNOTINITIALIZED);
}
if (INIT_LEVEL_TOTAL != m_dwInitializationLevel)
{
THROW(APPMAN_E_ACTIONNOTINITIALIZED);
}
//
// Are the required properties set
//
if (((APP_CATEGORY_PATCH | APP_CATEGORY_DATA) & m_sApplicationData.sBaseInfo.dwCategory))
{
if (S_OK == m_InformationManager.IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_EXECUTECMDLINE, &m_sApplicationData))
{
THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
}
}
else
{
if (S_OK != m_InformationManager.IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_EXECUTECMDLINE, &m_sApplicationData))
{
THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
}
if (S_OK != ValidateCommandLine(m_sApplicationData.wszStringProperty[APP_STRING_APPROOTPATH], m_sApplicationData.wszStringProperty[APP_STRING_EXECUTECMDLINE]))
{
THROW(APPMAN_E_INVALIDEXECUTECMDLINE);
}
}
//
// Was a default setup command line given to us
//
if (S_OK == m_InformationManager.IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_DEFAULTSETUPEXECMDLINE, &m_sApplicationData))
{
if (S_OK != ValidateCommandLine(m_sApplicationData.wszStringProperty[APP_STRING_SETUPROOTPATH], m_sApplicationData.wszStringProperty[APP_STRING_DEFAULTSETUPEXECMDLINE]))
{
THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
}
if (S_OK == m_InformationManager.IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_DOWNSIZECMDLINE, &m_sApplicationData))
{
if (S_OK != ValidateCommandLine(m_sApplicationData.wszStringProperty[APP_STRING_SETUPROOTPATH], m_sApplicationData.wszStringProperty[APP_STRING_DOWNSIZECMDLINE]))
{
THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
}
}
if (S_OK == m_InformationManager.IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_REINSTALLCMDLINE, &m_sApplicationData))
{
if (S_OK != ValidateCommandLine(m_sApplicationData.wszStringProperty[APP_STRING_SETUPROOTPATH], m_sApplicationData.wszStringProperty[APP_STRING_REINSTALLCMDLINE]))
{
THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
}
}
if (S_OK == m_InformationManager.IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_UNINSTALLCMDLINE, &m_sApplicationData))
{
if (S_OK != ValidateCommandLine(m_sApplicationData.wszStringProperty[APP_STRING_SETUPROOTPATH], m_sApplicationData.wszStringProperty[APP_STRING_UNINSTALLCMDLINE]))
{
THROW(APPMAN_E_INVALIDUNINSTALLCMDLINE);
}
}
if (S_OK == m_InformationManager.IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_SELFTESTCMDLINE, &m_sApplicationData))
{
if (S_OK != ValidateCommandLine(m_sApplicationData.wszStringProperty[APP_STRING_SETUPROOTPATH], m_sApplicationData.wszStringProperty[APP_STRING_SELFTESTCMDLINE]))
{
THROW(APPMAN_E_INVALIDSELFTESTCMDLINE);
}
}
}
else
{
if (S_OK != m_InformationManager.IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_DOWNSIZECMDLINE, &m_sApplicationData))
{
THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
}
if (S_OK != ValidateCommandLine(m_sApplicationData.wszStringProperty[APP_STRING_SETUPROOTPATH], m_sApplicationData.wszStringProperty[APP_STRING_DOWNSIZECMDLINE]))
{
THROW(APPMAN_E_INVALIDDOWNSIZECMDLINE);
}
if (S_OK != m_InformationManager.IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_REINSTALLCMDLINE, &m_sApplicationData))
{
THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
}
if (S_OK != ValidateCommandLine(m_sApplicationData.wszStringProperty[APP_STRING_SETUPROOTPATH], m_sApplicationData.wszStringProperty[APP_STRING_REINSTALLCMDLINE]))
{
THROW(APPMAN_E_INVALIDREINSTALLCMDLINE);
}
if (S_OK != m_InformationManager.IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_UNINSTALLCMDLINE, &m_sApplicationData))
{
THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
}
if (S_OK != ValidateCommandLine(m_sApplicationData.wszStringProperty[APP_STRING_SETUPROOTPATH], m_sApplicationData.wszStringProperty[APP_STRING_UNINSTALLCMDLINE]))
{
THROW(APPMAN_E_INVALIDUNINSTALLCMDLINE);
}
if (S_OK != m_InformationManager.IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_SELFTESTCMDLINE, &m_sApplicationData))
{
THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
}
if (S_OK != ValidateCommandLine(m_sApplicationData.wszStringProperty[APP_STRING_SETUPROOTPATH], m_sApplicationData.wszStringProperty[APP_STRING_SELFTESTCMDLINE]))
{
THROW(APPMAN_E_INVALIDSELFTESTCMDLINE);
}
}
//
// Do we need to do a cache fixup
//
ComputeApplicationSpaceInfo(m_sApplicationData.sBaseInfo.dwReservedKilobytes);
//
// Delete the reserved space field
//
m_sApplicationData.sBaseInfo.dwReservedKilobytes = 0;
INVALIDATE_PROPERTY(IDX_PROPERTY_ESTIMATEDINSTALLKILOBYTES);
//
// Before we arbitrarily set the state of the application to APP_STATE_READY, check
// to see if the setup technology hasn't already changed
//
if (APP_STATE_INSTALLING == GET_APPLICATIONSTATE())
{
RESET_APPLICATIONSTATE(APP_STATE_READY);
}
else
{
if (APP_STATE_DOWNSIZED != GET_APPLICATIONSTATE())
{
THROW(APPMAN_E_INVALIDPROPERTYVALUE);
}
}
//
// Save the application info
//
m_InformationManager.SetApplicationData(&m_sApplicationData, &m_sInstanceGuid);
//
// Make sure this IApplicationEntry instance is no longer in an action state
//
SET_ACTIONSTATE(CURRENT_ACTION_NONE);
//
// Unlock the parent apps
//
ZeroMemory(&sAssociationInfo, sizeof(sAssociationInfo));
dwIndex = 0;
while (S_OK == m_InformationManager.EnumAssociations(dwIndex, &sAssociationInfo))
{
if (0 == memcmp((LPVOID) &(sAssociationInfo.sChildGuid), (LPVOID) &(m_sApplicationData.sBaseInfo.sApplicationGuid), sizeof(GUID)))
{
//
// Get the associated application
//
ZeroMemory(&sApplicationData, sizeof(sApplicationData));
memcpy((LPVOID) &sApplicationData.sBaseInfo.sApplicationGuid, (LPVOID) &sAssociationInfo.sParentGuid, sizeof(GUID));
m_InformationManager.ValidateApplicationPropertyWithIndex(IDX_PROPERTY_GUID, &sApplicationData);
hResult = m_InformationManager.GetApplicationData(&sApplicationData);
if (SUCCEEDED(hResult))
{
//
// Unlock the parent applications
//
m_InformationManager.UnlockParentApplications(&sApplicationData, &m_sInstanceGuid);
}
}
dwIndex++;
}
//
// Unlock this app
//
UnLockApplication();
}
///////////////////////////////////////////////////////////////////////////////////////
catch(CAppManExceptionHandler * pException)
{
hResult = pException->GetResultCode();
delete pException;
}
catch(...)
{
hResult = E_UNEXPECTED;
}
///////////////////////////////////////////////////////////////////////////////////////
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CApplicationEntry::InitializeDownsize(void)
{
FUNCTION("CAppEntry::InitializeDownsize ()");
HRESULT hResult = S_OK;
HRESULT hLockResult = S_FALSE;
///////////////////////////////////////////////////////////////////////////////////////
try
{
if (!CHECK_ACTIONSTATE(CURRENT_ACTION_NONE))
{
THROW(APPMAN_E_ACTIONINPROGRESS);
}
//
// Are the required properties set
//
if (S_OK != m_InformationManager.IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_GUID, &m_sApplicationData))
{
THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
}
//
// Lock the application
//
hResult = LockApplication();
if (S_OK == hResult)
{
hLockResult = S_OK;
hResult = m_InformationManager.GetApplicationData(&m_sApplicationData);
if (SUCCEEDED(hResult))
{
//
// Since GetApplicationInfo succeeded this means we have a totally initialized object
//
m_dwInitializationLevel = INIT_LEVEL_TOTAL;
//
// Record the original size of the root paths in order to compute the deltas during
// FinalizeInstall
//
ComputeOriginalApplicationSpaceInfo();
//
// Set the states
//
m_dwOriginalState = m_sApplicationData.sBaseInfo.dwState;
RESET_APPLICATIONSTATE(APP_STATE_DOWNSIZING);
SET_ACTIONSTATE(CURRENT_ACTION_DOWNSIZING);
//
// Enter the wait event if any
//
m_InformationManager.EnterWaitEvent(&m_sApplicationData, WAIT_FINALIZE_DOWNSIZE, &m_sInstanceGuid);
}
}
else
{
m_InformationManager.EnterWaitEvent(&m_sApplicationData, WAIT_FINALIZE_DOWNSIZE, &m_sInstanceGuid);
m_InformationManager.LeaveWaitEvent(&m_sApplicationData, WAIT_FINALIZE_DOWNSIZE);
}
}
///////////////////////////////////////////////////////////////////////////////////////
catch(CAppManExceptionHandler * pException)
{
//
// Make sure to kill the wait event
//
if (INIT_LEVEL_TOTAL == m_dwInitializationLevel)
{
m_InformationManager.EnterWaitEvent(&m_sApplicationData, WAIT_FINALIZE_DOWNSIZE, &m_sInstanceGuid);
m_InformationManager.LeaveWaitEvent(&m_sApplicationData, WAIT_FINALIZE_DOWNSIZE);
}
//
// Make sure to unlock the application if it was locked
//
if (S_OK == hLockResult)
{
UnLockApplication();
}
//
// Record the error code
//
hResult = pException->GetResultCode();
delete pException;
}
catch(...)
{
//
// Make sure to kill the wait event
//
if (INIT_LEVEL_TOTAL == m_dwInitializationLevel)
{
m_InformationManager.EnterWaitEvent(&m_sApplicationData, WAIT_FINALIZE_DOWNSIZE, &m_sInstanceGuid);
m_InformationManager.LeaveWaitEvent(&m_sApplicationData, WAIT_FINALIZE_DOWNSIZE);
}
//
// Make sure to unlock the application if it was locked
//
if (S_OK == hLockResult)
{
UnLockApplication();
}
hResult = E_UNEXPECTED;
}
///////////////////////////////////////////////////////////////////////////////////////
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CApplicationEntry::FinalizeDownsize(void)
{
FUNCTION("CAppEntry::FinalizeDownsize ()");
HRESULT hResult = S_OK;
///////////////////////////////////////////////////////////////////////////////////////
try
{
if (!CHECK_ACTIONSTATE(CURRENT_ACTION_DOWNSIZING))
{
THROW(APPMAN_E_ACTIONNOTINITIALIZED);
}
//
// Do we need to do a cache fixup
//
ComputeApplicationSpaceInfo(0);
//
// Set the application state to downsized
//
m_sApplicationData.sBaseInfo.dwState = APP_STATE_DOWNSIZED;
//
// Save the application info
//
m_InformationManager.SetApplicationData(&m_sApplicationData, &m_sInstanceGuid);
//
// Unlock the application
//
UnLockApplication();
//
// Leave the wait event
//
m_InformationManager.LeaveWaitEvent(&m_sApplicationData, WAIT_FINALIZE_DOWNSIZE);
SET_ACTIONSTATE(CURRENT_ACTION_NONE);
}
///////////////////////////////////////////////////////////////////////////////////////
catch(CAppManExceptionHandler * pException)
{
hResult = pException->GetResultCode();
delete pException;
}
catch(...)
{
hResult = E_UNEXPECTED;
}
///////////////////////////////////////////////////////////////////////////////////////
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CApplicationEntry::InitializeReInstall(void)
{
FUNCTION("CAppEntry::InitializeReInstall ()");
HRESULT hResult = S_OK;
HRESULT hLockResult = S_FALSE;
BOOL fParentLocked = FALSE;
///////////////////////////////////////////////////////////////////////////////////////
try
{
APPLICATION_DATA sApplicationData;
ASSOCIATION_INFO sAssociationInfo;
DWORD dwIndex;
DWORD dwReservedKilobytes;
CWin32API sWin32API;
if ((!CHECK_ACTIONSTATE(CURRENT_ACTION_NONE))&&(!CHECK_ACTIONSTATE(CURRENT_ACTION_SELFTESTING)))
{
THROW(APPMAN_E_ACTIONINPROGRESS);
}
//
// Are the required properties set
//
if (S_OK != m_InformationManager.IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_GUID, &m_sApplicationData))
{
THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
}
if (S_OK != m_InformationManager.IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_ESTIMATEDINSTALLKILOBYTES, &m_sApplicationData))
{
THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
}
//
// Save the dwReservedKilobytes property before calling GetApplicationData
//
dwReservedKilobytes = m_sApplicationData.sBaseInfo.dwReservedKilobytes;
//
// First we lock this application
//
hResult = LockApplication();
if (S_OK == hResult)
{
hLockResult = S_OK;
hResult = m_InformationManager.GetApplicationData(& m_sApplicationData);
if (SUCCEEDED(hResult))
{
//
// Since GetApplicationInfo succeeded this means we have a totally initialized object
//
m_dwInitializationLevel = INIT_LEVEL_TOTAL;
//
// Make sure to restore and validate the dwReservedKilobytes
//
m_sApplicationData.sBaseInfo.dwReservedKilobytes = dwReservedKilobytes;
VALIDATE_PROPERTY(IDX_PROPERTY_ESTIMATEDINSTALLKILOBYTES);
//
// Make sure that the parent associated apps are associated
//
ZeroMemory(&sAssociationInfo, sizeof(sAssociationInfo));
dwIndex = 0;
while (S_OK == m_InformationManager.EnumAssociations(dwIndex, &sAssociationInfo))
{
if (0 == memcmp((LPVOID) &(m_sApplicationData.sBaseInfo.sApplicationGuid), (LPVOID) &(sAssociationInfo.sChildGuid), sizeof(GUID)))
{
//
// Get the associated application
//
ZeroMemory(&sApplicationData, sizeof(sApplicationData));
memcpy((LPVOID) &sApplicationData.sBaseInfo.sApplicationGuid, (LPVOID) &sAssociationInfo.sParentGuid, sizeof(GUID));
m_InformationManager.ValidateApplicationPropertyWithIndex(IDX_PROPERTY_GUID, &sApplicationData);
hResult = m_InformationManager.GetApplicationData(&sApplicationData);
if (FAILED(hResult))
{
THROW(APPMAN_E_INVALIDASSOCIATION);
}
//
// Make sure the associated app is in a ready state
//
hResult = m_InformationManager.ReadyApplication(&sApplicationData);
if (FAILED(hResult))
{
THROW(APPMAN_E_APPLICATIONREQUIRED);
}
//
// Lock the parent applications
//
hResult = m_InformationManager.LockParentApplications(&sApplicationData, &m_sInstanceGuid);
if (FAILED(hResult))
{
THROW(hResult);
}
else
{
fParentLocked = TRUE;
}
}
dwIndex++;
}
//
// Go get the space
//
if (FAILED(m_InformationManager.FreeSpaceOnDevice(&(m_sApplicationData.sBaseInfo.sDeviceGuid), m_sApplicationData.sBaseInfo.dwReservedKilobytes)))
{
THROW(APPMAN_E_NODISKSPACEAVAILABLE);
}
//
// Record the original size of the root paths in order to computer the deltas during
// FinalizeInstall
//
ComputeOriginalApplicationSpaceInfo();
//
// Set the state of the application
//
m_dwOriginalState = m_sApplicationData.sBaseInfo.dwState;
m_sApplicationData.sBaseInfo.dwState = APP_STATE_REINSTALLING;
m_InformationManager.SetApplicationData(&m_sApplicationData, &m_sInstanceGuid);
if (CHECK_ACTIONSTATE(CURRENT_ACTION_NONE))
{
SET_ACTIONSTATE(CURRENT_ACTION_REINSTALLING);
}
else
{
SET_ACTIONSTATE(CURRENT_ACTION_REINSTALLING | CURRENT_ACTION_SELFTESTING);
}
//
// Enter the wait event if any
//
m_InformationManager.EnterWaitEvent(&m_sApplicationData, WAIT_FINALIZE_REINSTALL, &m_sInstanceGuid);
}
}
}
///////////////////////////////////////////////////////////////////////////////////////
catch(CAppManExceptionHandler * pException)
{
APPLICATION_DATA sApplicationData;
ASSOCIATION_INFO sAssociationInfo;
DWORD dwIndex;
//
// Make sure to unlock the application if it was locked
//
if (S_OK == hLockResult)
{
UnLockApplication();
}
//
// Make sure that if we have locked parents, we unlock them here
//
if (fParentLocked)
{
ZeroMemory(&sAssociationInfo, sizeof(sAssociationInfo));
dwIndex = 0;
while (S_OK == m_InformationManager.EnumAssociations(dwIndex, &sAssociationInfo))
{
if (0 == memcmp((LPVOID) &(m_sApplicationData.sBaseInfo.sApplicationGuid), (LPVOID) &(sAssociationInfo.sChildGuid), sizeof(GUID)))
{
//
// Get the associated application
//
ZeroMemory(&sApplicationData, sizeof(sApplicationData));
memcpy((LPVOID) &sApplicationData.sBaseInfo.sApplicationGuid, (LPVOID) &sAssociationInfo.sParentGuid, sizeof(GUID));
m_InformationManager.ValidateApplicationPropertyWithIndex(IDX_PROPERTY_GUID, &sApplicationData);
if (SUCCEEDED(m_InformationManager.GetApplicationData(&sApplicationData)))
{
//
// Unlock the parent applications
//
m_InformationManager.LockParentApplications(&sApplicationData, &m_sInstanceGuid);
}
}
dwIndex++;
}
}
//
// Make sure to kill the wait event
//
if (INIT_LEVEL_TOTAL == m_dwInitializationLevel)
{
m_InformationManager.EnterWaitEvent(&m_sApplicationData, WAIT_FINALIZE_REINSTALL, &m_sInstanceGuid);
m_InformationManager.LeaveWaitEvent(&m_sApplicationData, WAIT_FINALIZE_REINSTALL);
}
hResult = pException->GetResultCode();
delete pException;
}
catch(...)
{
APPLICATION_DATA sApplicationData;
ASSOCIATION_INFO sAssociationInfo;
DWORD dwIndex;
//
// Make sure to unlock the application if it was locked
//
if (S_OK == hLockResult)
{
UnLockApplication();
}
//
// Make sure that if we have locked parents, we unlock them here
//
if (fParentLocked)
{
ZeroMemory(&sAssociationInfo, sizeof(sAssociationInfo));
dwIndex = 0;
while (S_OK == m_InformationManager.EnumAssociations(dwIndex, &sAssociationInfo))
{
if (0 == memcmp((LPVOID) &(m_sApplicationData.sBaseInfo.sApplicationGuid), (LPVOID) &(sAssociationInfo.sChildGuid), sizeof(GUID)))
{
//
// Get the associated application
//
ZeroMemory(&sApplicationData, sizeof(sApplicationData));
memcpy((LPVOID) &sApplicationData.sBaseInfo.sApplicationGuid, (LPVOID) &sAssociationInfo.sParentGuid, sizeof(GUID));
m_InformationManager.ValidateApplicationPropertyWithIndex(IDX_PROPERTY_GUID, &sApplicationData);
if (SUCCEEDED(m_InformationManager.GetApplicationData(&sApplicationData)))
{
//
// Unlock the parent applications
//
m_InformationManager.LockParentApplications(&sApplicationData, &m_sInstanceGuid);
}
}
dwIndex++;
}
}
//
// Make sure to kill the wait event
//
if (INIT_LEVEL_TOTAL == m_dwInitializationLevel)
{
m_InformationManager.EnterWaitEvent(&m_sApplicationData, WAIT_FINALIZE_REINSTALL, &m_sInstanceGuid);
m_InformationManager.LeaveWaitEvent(&m_sApplicationData, WAIT_FINALIZE_REINSTALL);
}
hResult = E_UNEXPECTED;
}
///////////////////////////////////////////////////////////////////////////////////////
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CApplicationEntry::FinalizeReInstall(void)
{
FUNCTION("CAppEntry::FinalizeReInstall ()");
HRESULT hResult = S_OK;
///////////////////////////////////////////////////////////////////////////////////////
try
{
CWin32API sWin32API;
DWORD dwIndex; //, dwActualApplicationSize; Get rid of /W4 warning.
APPLICATION_DATA sApplicationData;
ASSOCIATION_INFO sAssociationInfo;
//
// Make sure we are currently reinstalling
//
if ((!CHECK_ACTIONSTATE(CURRENT_ACTION_REINSTALLING))&&(!CHECK_ACTIONSTATE(CURRENT_ACTION_REINSTALLING | CURRENT_ACTION_SELFTESTING)))
{
THROW(APPMAN_E_ACTIONNOTINITIALIZED);
}
//
// Do we need to do a cache fixup
//
ComputeApplicationSpaceInfo(m_sApplicationData.sBaseInfo.dwReservedKilobytes);
//
// Clear the dwReservedKilobytes data member
//
m_sApplicationData.sBaseInfo.dwReservedKilobytes = 0;
INVALIDATE_PROPERTY(IDX_PROPERTY_ESTIMATEDINSTALLKILOBYTES);
//
// Update the aging information
//
m_sApplicationData.sAgingInfo.dwReInstallCount++;
GetLocalTime(&(m_sApplicationData.sAgingInfo.stLastUsedDate));
VALIDATE_PROPERTY(IDX_PROPERTY_LASTUSEDDATE);
//
// Set the application state to ready
//
m_sApplicationData.sBaseInfo.dwState = APP_STATE_READY;
//
// Save the application info
//
m_InformationManager.SetApplicationData(&m_sApplicationData, &m_sInstanceGuid);
if (CHECK_ACTIONSTATE(CURRENT_ACTION_REINSTALLING))
{
RESET_ACTIONSTATE(CURRENT_ACTION_NONE);
}
else
{
RESET_ACTIONSTATE(CURRENT_ACTION_SELFTESTING);
}
//
// Before we do anything, make sure to unlock the parent apps
//
ZeroMemory(&sAssociationInfo, sizeof(sAssociationInfo));
dwIndex = 0;
while (S_OK == m_InformationManager.EnumAssociations(dwIndex, &sAssociationInfo))
{
if (0 == memcmp((LPVOID) &(m_sApplicationData.sBaseInfo.sApplicationGuid), (LPVOID) &(sAssociationInfo.sChildGuid), sizeof(GUID)))
{
//
// Get the associated application
//
ZeroMemory(&sApplicationData, sizeof(sApplicationData));
memcpy((LPVOID) &sApplicationData.sBaseInfo.sApplicationGuid, (LPVOID) &sAssociationInfo.sParentGuid, sizeof(GUID));
m_InformationManager.ValidateApplicationPropertyWithIndex(IDX_PROPERTY_GUID, &sApplicationData);
hResult = m_InformationManager.GetApplicationData(&sApplicationData);
if (SUCCEEDED(hResult))
{
//
// Unlock the parent applications
//
m_InformationManager.UnlockParentApplications(&sApplicationData, &m_sInstanceGuid);
}
}
dwIndex++;
}
UnLockApplication();
//
// Leave the wait event
//
m_InformationManager.LeaveWaitEvent(&m_sApplicationData, WAIT_FINALIZE_REINSTALL);
}
///////////////////////////////////////////////////////////////////////////////////////
catch(CAppManExceptionHandler * pException)
{
hResult = pException->GetResultCode();
delete pException;
}
catch(...)
{
hResult = E_UNEXPECTED;
}
///////////////////////////////////////////////////////////////////////////////////////
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CApplicationEntry::InitializeUnInstall(void)
{
FUNCTION("CAppEntry::InitializeUnInstall ()");
HRESULT hResult = S_OK;
HRESULT hLockResult = S_FALSE;
///////////////////////////////////////////////////////////////////////////////////////
try
{
ASSOCIATION_INFO sAssociationInfo;
DWORD dwIndex;
if (!CHECK_ACTIONSTATE(CURRENT_ACTION_NONE))
{
THROW(APPMAN_E_ACTIONINPROGRESS);
}
//
// Are the required properties set
//
if (S_OK != m_InformationManager.IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_GUID, &m_sApplicationData))
{
THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
}
hResult = m_InformationManager.GetApplicationData(&m_sApplicationData);
if (SUCCEEDED(hResult))
{
//
// Since GetApplicationInfo succeeded this means we have a totally initialized object
//
m_dwInitializationLevel = INIT_LEVEL_TOTAL;
//
// Check to make sure that this application is not required for another to run
//
dwIndex = 0;
while (S_OK == m_InformationManager.EnumAssociations(dwIndex, &sAssociationInfo))
{
if (0 == memcmp((LPVOID) &m_sApplicationData.sBaseInfo.sApplicationGuid, (LPVOID) &sAssociationInfo.sParentGuid, sizeof(GUID)))
{
THROW(APPMAN_E_APPLICATIONREQUIRED);
}
dwIndex++;
}
//
// Lock the application
//
hResult = LockApplication();
if (S_OK == hResult)
{
hLockResult = S_OK;
m_dwOriginalState = m_sApplicationData.sBaseInfo.dwState;
RESET_APPLICATIONSTATE(APP_STATE_UNINSTALLING);
SET_ACTIONSTATE(CURRENT_ACTION_UNINSTALLING);
//
// Enter the wait event if any
//
m_InformationManager.EnterWaitEvent(&m_sApplicationData, WAIT_FINALIZE_UNINSTALL, &m_sInstanceGuid);
}
}
}
///////////////////////////////////////////////////////////////////////////////////////
catch(CAppManExceptionHandler * pException)
{
//
// Make sure to unlock the application if it was locked
//
if (S_OK == hLockResult)
{
UnLockApplication();
}
//
// Make sure to kill the wait event
//
if (INIT_LEVEL_TOTAL == m_dwInitializationLevel)
{
m_InformationManager.EnterWaitEvent(&m_sApplicationData, WAIT_FINALIZE_UNINSTALL, &m_sInstanceGuid);
m_InformationManager.LeaveWaitEvent(&m_sApplicationData, WAIT_FINALIZE_UNINSTALL);
}
hResult = pException->GetResultCode();
delete pException;
}
catch(...)
{
//
// Make sure to unlock the application if it was locked
//
if (S_OK == hLockResult)
{
UnLockApplication();
}
//
// Make sure to kill the wait event
//
if (INIT_LEVEL_TOTAL == m_dwInitializationLevel)
{
m_InformationManager.EnterWaitEvent(&m_sApplicationData, WAIT_FINALIZE_UNINSTALL, &m_sInstanceGuid);
m_InformationManager.LeaveWaitEvent(&m_sApplicationData, WAIT_FINALIZE_UNINSTALL);
}
hResult = E_UNEXPECTED;
}
///////////////////////////////////////////////////////////////////////////////////////
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CApplicationEntry::FinalizeUnInstall(void)
{
FUNCTION("CAppEntry::FinalizeUnInstall ()");
HRESULT hResult = S_OK;
///////////////////////////////////////////////////////////////////////////////////////
try
{
if (!CHECK_ACTIONSTATE(CURRENT_ACTION_UNINSTALLING))
{
THROW(APPMAN_E_ACTIONNOTINITIALIZED);
}
//
// Remove the application from the system
//
m_InformationManager.RemoveApplicationData(&m_sApplicationData);
UnLockApplication();
RESET_ACTIONSTATE(CURRENT_ACTION_NONE);
//
// Leave the wait event
//
m_InformationManager.LeaveWaitEvent(&m_sApplicationData, WAIT_FINALIZE_UNINSTALL);
}
///////////////////////////////////////////////////////////////////////////////////////
catch(CAppManExceptionHandler * pException)
{
hResult = pException->GetResultCode();
delete pException;
}
catch(...)
{
hResult = E_UNEXPECTED;
}
///////////////////////////////////////////////////////////////////////////////////////
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CApplicationEntry::InitializeSelfTest(void)
{
FUNCTION("CAppEntry::InitializeSelfTest ()");
HRESULT hResult = S_OK;
HRESULT hLockResult = S_OK;
///////////////////////////////////////////////////////////////////////////////////////
try
{
if (!CHECK_ACTIONSTATE(CURRENT_ACTION_NONE))
{
THROW(APPMAN_E_ACTIONINPROGRESS);
}
//
// Are the required properties set
//
if (S_OK != m_InformationManager.IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_GUID, &m_sApplicationData))
{
THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
}
hResult = LockApplication();
if (S_OK == hResult)
{
hLockResult = S_OK;
hResult = m_InformationManager.GetApplicationData(&m_sApplicationData);
if (SUCCEEDED(hResult))
{
//
// Since GetApplicationInfo succeeded this means we have a totally initialized object
//
m_dwInitializationLevel = INIT_LEVEL_TOTAL;
m_dwOriginalState = m_sApplicationData.sBaseInfo.dwState;
m_sApplicationData.sBaseInfo.dwState |= APP_STATE_SELFTESTING;
m_InformationManager.SetApplicationData(&m_sApplicationData, &m_sInstanceGuid);
SET_ACTIONSTATE(CURRENT_ACTION_SELFTESTING);
//
// Enter the wait event if any
//
m_InformationManager.EnterWaitEvent(&m_sApplicationData, WAIT_FINALIZE_SELFTEST, &m_sInstanceGuid);
}
}
}
///////////////////////////////////////////////////////////////////////////////////////
catch(CAppManExceptionHandler * pException)
{
//
// Make sure to unlock the application if it was locked
//
if (S_OK == hLockResult)
{
UnLockApplication();
}
//
// Make sure to kill the wait event
//
if (INIT_LEVEL_TOTAL == m_dwInitializationLevel)
{
m_InformationManager.EnterWaitEvent(&m_sApplicationData, WAIT_FINALIZE_SELFTEST, &m_sInstanceGuid);
m_InformationManager.LeaveWaitEvent(&m_sApplicationData, WAIT_FINALIZE_SELFTEST);
}
hResult = pException->GetResultCode();
delete pException;
}
catch(...)
{
//
// Make sure to unlock the application if it was locked
//
if (S_OK == hLockResult)
{
UnLockApplication();
}
//
// Make sure to kill the wait event
//
if (INIT_LEVEL_TOTAL == m_dwInitializationLevel)
{
m_InformationManager.EnterWaitEvent(&m_sApplicationData, WAIT_FINALIZE_SELFTEST, &m_sInstanceGuid);
m_InformationManager.LeaveWaitEvent(&m_sApplicationData, WAIT_FINALIZE_SELFTEST);
}
hResult = E_UNEXPECTED;
}
///////////////////////////////////////////////////////////////////////////////////////
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CApplicationEntry::FinalizeSelfTest(void)
{
FUNCTION("CAppEntry::FinalizeSelfTest ()");
HRESULT hResult = S_OK;
///////////////////////////////////////////////////////////////////////////////////////
try
{
APPLICATION_DATA sApplicationData;
if (!CHECK_ACTIONSTATE(CURRENT_ACTION_SELFTESTING))
{
THROW(APPMAN_E_ACTIONNOTINITIALIZED);
}
//
// Get the latest information from the database
//
ZeroMemory(&sApplicationData, sizeof(sApplicationData));
memcpy((LPVOID) &sApplicationData, (LPVOID) &m_sApplicationData, sizeof(sApplicationData));
m_InformationManager.SetApplicationData(&sApplicationData, &m_sInstanceGuid);
//
// Remove the selftest state flag from the application state
//
sApplicationData.sBaseInfo.dwState &= ~APP_STATE_SELFTESTING;
memcpy((LPVOID) &m_sApplicationData, (LPVOID) &sApplicationData, sizeof(sApplicationData));
//
// Save the application info
//
m_InformationManager.SetApplicationData(&sApplicationData, &m_sInstanceGuid);
UnLockApplication();
RESET_ACTIONSTATE(CURRENT_ACTION_NONE);
//
// Leave the wait event
//
m_InformationManager.LeaveWaitEvent(&m_sApplicationData, WAIT_FINALIZE_SELFTEST);
}
///////////////////////////////////////////////////////////////////////////////////////
catch(CAppManExceptionHandler * pException)
{
hResult = pException->GetResultCode();
delete pException;
}
catch(...)
{
hResult = E_UNEXPECTED;
}
///////////////////////////////////////////////////////////////////////////////////////
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CApplicationEntry::Abort(void)
{
FUNCTION("CAppEntry::Abort ()");
HRESULT hResult = S_OK;
///////////////////////////////////////////////////////////////////////////////////////
try
{
APPLICATION_DATA sApplicationData;
ASSOCIATION_INFO sAssociationInfo;
DWORD dwIndex;
if (CHECK_ACTIONSTATE(CURRENT_ACTION_NONE))
{
THROW(APPMAN_E_ACTIONNOTINITIALIZED);
}
//
// We need to force a leave event
//
switch(m_dwCurrentAction)
{
case CURRENT_ACTION_DOWNSIZING
: m_InformationManager.LeaveWaitEvent(&m_sApplicationData, WAIT_FINALIZE_DOWNSIZE);
break;
case CURRENT_ACTION_REINSTALLING
: m_InformationManager.LeaveWaitEvent(&m_sApplicationData, WAIT_FINALIZE_REINSTALL);
break;
case CURRENT_ACTION_UNINSTALLING
: m_InformationManager.LeaveWaitEvent(&m_sApplicationData, WAIT_FINALIZE_UNINSTALL);
break;
case CURRENT_ACTION_SELFTESTING
: m_InformationManager.LeaveWaitEvent(&m_sApplicationData, WAIT_FINALIZE_SELFTEST);
break;
}
//
// Before we do anything, make sure to unlock the parent apps
//
ZeroMemory(&sAssociationInfo, sizeof(sAssociationInfo));
dwIndex = 0;
while (S_OK == m_InformationManager.EnumAssociations(dwIndex, &sAssociationInfo))
{
if (0 == memcmp((LPVOID) &(sAssociationInfo.sChildGuid), (LPVOID) &(m_sApplicationData.sBaseInfo.sApplicationGuid), sizeof(GUID)))
{
//
// Get the associated application
//
ZeroMemory(&sApplicationData, sizeof(sApplicationData));
memcpy((LPVOID) &sApplicationData.sBaseInfo.sApplicationGuid, (LPVOID) &sAssociationInfo.sParentGuid, sizeof(GUID));
m_InformationManager.ValidateApplicationPropertyWithIndex(IDX_PROPERTY_GUID, &sApplicationData);
hResult = m_InformationManager.GetApplicationData(&sApplicationData);
if (SUCCEEDED(hResult))
{
//
// Unlock the parent applications
//
m_InformationManager.UnlockParentApplications(&sApplicationData, &m_sInstanceGuid);
}
}
dwIndex++;
}
//
// If the application was doing an initial install, abort will cause the application
// entry to be removed from the system
//
if (CHECK_ACTIONSTATE(CURRENT_ACTION_INSTALLING))
{
UnLockApplication();
m_InformationManager.RemoveApplicationData(&m_sApplicationData);
}
else
{
//
// Simply restore the application info with the record currently saved in the
// registry
//
m_InformationManager.GetApplicationData(&m_sApplicationData);
m_sApplicationData.sBaseInfo.dwState = m_dwOriginalState;
m_InformationManager.SetApplicationData(&m_sApplicationData, &m_sInstanceGuid);
UnLockApplication();
}
SET_ACTIONSTATE(CURRENT_ACTION_NONE);
}
///////////////////////////////////////////////////////////////////////////////////////
catch(CAppManExceptionHandler * pException)
{
hResult = pException->GetResultCode();
delete pException;
}
catch(...)
{
hResult = E_UNEXPECTED;
}
///////////////////////////////////////////////////////////////////////////////////////
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CApplicationEntry::Run(const DWORD dwRunFlags, const DWORD dwStringMask, LPVOID lpData, const DWORD dwDataLen)
{
FUNCTION("CAppEntry::Run ()");
HRESULT hResult = S_OK;
///////////////////////////////////////////////////////////////////////////////////////
try
{
WCHAR wszParameters[MAX_PATH_CHARCOUNT];
WCHAR wszCommandLine[MAX_PATH_CHARCOUNT];
CWin32API sWin32API;
BOOL fRunning = FALSE;
PROCESS_INFORMATION sProcessInformation;
//
// We can only run if this object is not doing anything
//
if (!CHECK_ACTIONSTATE(CURRENT_ACTION_NONE))
{
THROW(APPMAN_E_ACTIONINPROGRESS);
}
if (S_OK != m_InformationManager.IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_GUID, &m_sApplicationData))
{
if ((S_OK != m_InformationManager.IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_COMPANYNAME, &m_sApplicationData))||(S_OK != m_InformationManager.IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_SIGNATURE, &m_sApplicationData)))
{
THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
}
}
//
// Make sure the application actually exists
//
if (INIT_LEVEL_NONE == m_dwInitializationLevel)
{
hResult = m_InformationManager.GetApplicationData(&m_sApplicationData);
if (FAILED(hResult))
{
THROW(hResult);
}
m_dwInitializationLevel = INIT_LEVEL_BASIC;
}
//
// This object cannot be run if it is APP_CATEGORY_PATCH or APP_CATEGORY_DAT
//
if ((APP_CATEGORY_PATCH | APP_CATEGORY_DATA) & m_sApplicationData.sBaseInfo.dwCategory)
{
THROW(APPMAN_E_APPNOTEXECUTABLE);
}
//
// Are the required properties set
//
//
// Ready the application
//
m_InformationManager.ReadyApplication(&m_sApplicationData);
//
// Build the command line parameters
//
ZeroMemory(wszParameters, sizeof(wszParameters));
if ((APP_PROPERTY_STR_ANSI == dwStringMask)||(APP_PROPERTY_STR_UNICODE == dwStringMask))
{
//
// Check to make sure the parameters are valid
//
if (NULL != lpData)
{
if (IsBadReadPtr(lpData, dwDataLen))
{
THROW(APPMAN_E_INVALIDPARAMETERS);
}
if (0 < dwDataLen)
{
//
// Make sure the command line parameters are converted to unicode
//
if (APP_PROPERTY_STR_ANSI == dwStringMask)
{
if (MAX_PATH_CHARCOUNT < StrLenA((LPCSTR) lpData))
{
THROW(APPMAN_E_INVALIDEXECUTECMDLINE);
}
else
{
sWin32API.MultiByteToWideChar((LPCSTR) lpData, dwDataLen, wszParameters, MAX_PATH_CHARCOUNT);
}
}
else
{
if (MAX_PATH_CHARCOUNT < StrLenW((LPCWSTR) lpData))
{
THROW(APPMAN_E_INVALIDEXECUTECMDLINE);
}
else
{
memcpy(wszParameters, lpData, StrLenW((LPCWSTR) lpData) * 2);
}
}
}
}
}
else
{
if (0 != dwStringMask)
{
THROW(APPMAN_E_INVALIDPARAMETERS);
}
}
//
// Construct the command line
//
if (1 < StrLenW(wszParameters))
{
//
// Make sure the total lenght does not exceed MAX_PATH_CHARCOUNT
//
if (MAX_PATH_CHARCOUNT < (StrLenW(m_sApplicationData.wszStringProperty[APP_STRING_EXECUTECMDLINE])+StrLenW(wszParameters)))
{
THROW(APPMAN_E_INVALIDEXECUTECMDLINE);
}
wcscpy(wszCommandLine, m_sApplicationData.wszStringProperty[APP_STRING_EXECUTECMDLINE]);
wcscat(wszCommandLine, L" /AppManStarted ");
wcscat(wszCommandLine, wszParameters);
}
else
{
wcscpy(wszCommandLine, m_sApplicationData.wszStringProperty[APP_STRING_EXECUTECMDLINE]);
wcscat(wszCommandLine, L" /AppManStarted");
}
//
// Run it
//
if (sWin32API.CreateProcess(wszCommandLine, &sProcessInformation))
{
fRunning = TRUE;
}
else
{
if (SUCCEEDED(m_InformationManager.SelfTestApplication(&m_sApplicationData)))
{
if (sWin32API.CreateProcess(wszCommandLine, &sProcessInformation))
{
fRunning = TRUE;
}
else
{
THROW(E_FAIL);
}
}
else
{
THROW(E_FAIL);
}
}
if (fRunning)
{
m_sApplicationData.sAgingInfo.dwUsageCount++;
GetLocalTime(&(m_sApplicationData.sAgingInfo.stLastUsedDate));
m_InformationManager.SetApplicationData(&m_sApplicationData, &m_sInstanceGuid);
if (APP_RUN_BLOCK & dwRunFlags)
{
WaitForSingleObject(sProcessInformation.hProcess, INFINITE);
}
CloseHandle(sProcessInformation.hThread);
CloseHandle(sProcessInformation.hProcess);
hResult = S_OK;
}
}
///////////////////////////////////////////////////////////////////////////////////////
catch(CAppManExceptionHandler * pException)
{
hResult = pException->GetResultCode();
delete pException;
}
catch(...)
{
hResult = E_UNEXPECTED;
}
///////////////////////////////////////////////////////////////////////////////////////
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
// TODO
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CApplicationEntry::AddAssociation(const DWORD dwAssociationType, const IApplicationEntry * lpApplicationEntry)
{
FUNCTION("CAppEntry::AddAssociation ()");
HRESULT hResult = S_OK;
///////////////////////////////////////////////////////////////////////////////////////
try
{
ASSOCIATION_INFO sAssociationRecord;
APPLICATION_DATA sApplicationData;
//
// Make sure we are in a proper state
//
if (!CHECK_ACTIONSTATE(CURRENT_ACTION_NONE))
{
THROW(APPMAN_E_CANNOTASSOCIATE);
}
//
// The initialization level should be INIT_LEVEL_NONE
//
if (INIT_LEVEL_NONE != m_dwInitializationLevel)
{
THROW(APPMAN_E_CANNOTASSOCIATE);
}
//
// Make sure an association does not already exist
//
if (0 != m_sApplicationData.sAssociation.dwAssociationType)
{
THROW(APPMAN_E_CANNOTASSOCIATE);
}
//
// Make sure the lpApplicationEntry parameter is valid
//
if (NULL == lpApplicationEntry)
{
THROW(APPMAN_E_INVALIDPARAMETERS);
}
if (IsBadReadPtr((LPVOID) lpApplicationEntry, sizeof(CApplicationEntry)))
{
THROW(APPMAN_E_INVALIDPARAMETERS);
}
//
// Make sure that dwAssociationType is valid
//
if ((APP_ASSOCIATION_INHERITBOTHPATHS != dwAssociationType)&&(APP_ASSOCIATION_INHERITAPPROOTPATH != dwAssociationType)&&(APP_ASSOCIATION_INHERITSETUPROOTPATH != dwAssociationType))
{
THROW(APPMAN_E_INVALIDASSOCIATION);
}
//
// Make sure the root path is not already set
//
if (S_OK == m_InformationManager.IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_ROOTPATH, &m_sApplicationData))
{
THROW(APPMAN_E_CANNOTASSOCIATE);
}
//
// Initialize the sAssociationRecord structure
//
sAssociationRecord.dwSize = sizeof(ASSOCIATION_INFO);
sAssociationRecord.dwStructId = ASSOCIATION_STRUCT;
sAssociationRecord.dwAssociationType = dwAssociationType;
//
// Does the application we want to association with even exist
//
memcpy((LPVOID) &sApplicationData, (LPVOID) ((CApplicationEntry *)lpApplicationEntry)->GetApplicationDataPtr(), sizeof(APPLICATION_DATA));
hResult = m_InformationManager.GetApplicationData(&sApplicationData);
if (FAILED(hResult))
{
THROW(APPMAN_E_UNKNOWNAPPLICATION);
}
//
// Fill in the rest of the information
//
memcpy((LPVOID)&sAssociationRecord.sParentGuid, (LPVOID) &sApplicationData.sBaseInfo.sApplicationGuid, sizeof(GUID));
//
// Is there an association already ?
//
if (0 != m_sApplicationData.sAssociation.dwAssociationType)
{
THROW(APPMAN_E_ALREADYASSOCIATED);
}
//
// Ok make the association happen
//
memcpy((LPVOID) &m_sApplicationData.sAssociation, (LPVOID) &sAssociationRecord, sizeof(ASSOCIATION_INFO));
}
///////////////////////////////////////////////////////////////////////////////////////
catch(CAppManExceptionHandler * pException)
{
hResult = pException->GetResultCode();
delete pException;
}
catch(...)
{
hResult = E_UNEXPECTED;
}
///////////////////////////////////////////////////////////////////////////////////////
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
// TODO
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CApplicationEntry::RemoveAssociation(const DWORD dwAssociationType, const IApplicationEntry * lpApplicationEntry)
{
FUNCTION("CAppEntry::RemoveAssociation ()");
HRESULT hResult = S_OK;
///////////////////////////////////////////////////////////////////////////////////////
try
{
//
// Make sure we are in a proper state
//
if (!CHECK_ACTIONSTATE(CURRENT_ACTION_NONE))
{
THROW(E_FAIL);
}
//
// The initialization level should be INIT_LEVEL_NONE
//
if (INIT_LEVEL_NONE != m_dwInitializationLevel)
{
THROW(E_FAIL);
}
//
// Make sure the lpApplicationEntry parameter is proper
//
if (NULL == lpApplicationEntry)
{
THROW(APPMAN_E_INVALIDPARAMETERS);
}
if (IsBadReadPtr((LPVOID) lpApplicationEntry, sizeof(CApplicationEntry)))
{
THROW(APPMAN_E_INVALIDPARAMETERS);
}
//
// Make sure that dwAssociationType is valid
//
if ((APP_ASSOCIATION_INHERITBOTHPATHS != dwAssociationType)&&(APP_ASSOCIATION_INHERITAPPROOTPATH != dwAssociationType)&&(APP_ASSOCIATION_INHERITSETUPROOTPATH != dwAssociationType))
{
THROW(APPMAN_E_INVALIDASSOCIATION);
}
//
// Make sure an association does exist
//
if (0 == m_sApplicationData.sAssociation.dwAssociationType)
{
THROW(E_FAIL);
}
ZeroMemory(&m_sApplicationData.sAssociation, sizeof(ASSOCIATION_INFO));
}
///////////////////////////////////////////////////////////////////////////////////////
catch(CAppManExceptionHandler * pException)
{
hResult = pException->GetResultCode();
delete pException;
}
catch(...)
{
hResult = E_UNEXPECTED;
}
///////////////////////////////////////////////////////////////////////////////////////
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
// TODO
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CApplicationEntry::EnumAssociations(const DWORD dwTargetIndex, LPDWORD lpdwAssociationType, IApplicationEntry * lpApplicationEntry)
{
FUNCTION("CAppEntry::EnumAssociations ()");
HRESULT hResult = S_OK;
///////////////////////////////////////////////////////////////////////////////////////
try
{
ASSOCIATION_INFO sAssociationInfo;
DWORD dwIndex, dwActualIndex;
//
// Make sure the lpApplicationEntry pointer is good
//
if (NULL == lpApplicationEntry)
{
THROW(APPMAN_E_INVALIDPARAMETERS);
}
if (IsBadReadPtr((LPVOID) lpApplicationEntry, sizeof(CApplicationEntry)))
{
THROW(APPMAN_E_INVALIDPARAMETERS);
}
//
// Make sure that the lpdwAssociationType is valid
//
if (NULL == lpdwAssociationType)
{
THROW(APPMAN_E_INVALIDPARAMETERS);
}
if (IsBadWritePtr((LPVOID) lpdwAssociationType, sizeof(DWORD)))
{
THROW(APPMAN_E_INVALIDPARAMETERS);
}
//
// Get the nth association record. Ignore associations that belong to other applications
//
dwActualIndex = dwTargetIndex;
dwIndex = 0;
do
{
hResult = m_InformationManager.EnumAssociations(dwIndex, &sAssociationInfo);
if (S_OK == hResult)
{
if (memcmp((LPVOID) &m_sApplicationData.sBaseInfo.sApplicationGuid, (LPVOID) &sAssociationInfo.sChildGuid, sizeof(GUID)))
{
if (memcmp((LPVOID) &m_sApplicationData.sBaseInfo.sApplicationGuid, (LPVOID) &sAssociationInfo.sParentGuid, sizeof(GUID)))
{
dwActualIndex++;
}
}
}
dwIndex++;
}
while ((dwIndex <= dwActualIndex)&&(S_OK == hResult));
//
// Did we find an association
//
if (S_OK == hResult)
{
if (0 == memcmp((LPVOID) &m_sApplicationData.sBaseInfo.sApplicationGuid, (LPVOID) &sAssociationInfo.sChildGuid, sizeof(GUID)))
{
//
// The association is a child associations
//
*lpdwAssociationType = sAssociationInfo.dwAssociationType | APP_ASSOCIATION_CHILD;
hResult = lpApplicationEntry->Clear();
if (SUCCEEDED(hResult))
{
hResult = lpApplicationEntry->SetProperty(APP_PROPERTY_GUID, (LPCVOID) &sAssociationInfo.sParentGuid, sizeof(GUID));
if (SUCCEEDED(hResult))
{
hResult = m_InformationManager.GetApplicationData(((CApplicationEntry *) lpApplicationEntry)->GetApplicationDataPtr());
if (SUCCEEDED(hResult))
{
((CApplicationEntry *) lpApplicationEntry)->SetInitializationLevel(INIT_LEVEL_BASIC);
}
}
}
}
else
{
if (0 == memcmp((LPVOID) &m_sApplicationData.sBaseInfo.sApplicationGuid, (LPVOID) &sAssociationInfo.sParentGuid, sizeof(GUID)))
{
//
// The association is a parent association
//
*lpdwAssociationType = sAssociationInfo.dwAssociationType | APP_ASSOCIATION_PARENT;
hResult = lpApplicationEntry->Clear();
if (SUCCEEDED(hResult))
{
hResult = lpApplicationEntry->SetProperty(APP_PROPERTY_GUID, (LPCVOID) &sAssociationInfo.sChildGuid, sizeof(GUID));
if (SUCCEEDED(hResult))
{
hResult = m_InformationManager.GetApplicationData(((CApplicationEntry *) lpApplicationEntry)->GetApplicationDataPtr());
if (SUCCEEDED(hResult))
{
((CApplicationEntry *) lpApplicationEntry)->SetInitializationLevel(INIT_LEVEL_BASIC);
}
}
}
}
}
}
}
///////////////////////////////////////////////////////////////////////////////////////
catch(CAppManExceptionHandler * pException)
{
hResult = pException->GetResultCode();
delete pException;
}
catch(...)
{
hResult = E_UNEXPECTED;
}
///////////////////////////////////////////////////////////////////////////////////////
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
// TODO
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CApplicationEntry::GetTemporarySpace(const DWORD dwKilobytes, const DWORD dwStringMask, LPVOID lpData, const DWORD dwDataLen)
{
FUNCTION("CAppEntry::GetTemporarySpace ()");
HRESULT hResult = E_FAIL;
BOOL fParentsLocked = FALSE;
BOOL fLocked = FALSE;
APPLICATION_DATA sApplicationData;
///////////////////////////////////////////////////////////////////////////////////////
try
{
TEMP_SPACE_RECORD sTempSpaceRecord;
DWORD dwCharCount;
//
// Are the required properties set
//
if (S_OK != m_InformationManager.IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_GUID, &m_sApplicationData))
{
THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
}
//
// Is the object a valid application object
//
memcpy((LPVOID) &sApplicationData, (LPVOID) &m_sApplicationData, sizeof(APPLICATION_DATA));
hResult = m_InformationManager.GetApplicationData(&sApplicationData);
if (FAILED(hResult))
{
THROW(APPMAN_E_UNKNOWNAPPLICATION);
}
//
// Make sure the string mask is good
//
if ((APP_PROPERTY_STR_ANSI != dwStringMask)&&(APP_PROPERTY_STR_UNICODE != dwStringMask))
{
THROW(APPMAN_E_INVALIDPARAMETERS);
}
//
// Check to make sure dwDataLen is greater than 0
//
if (0 == dwDataLen)
{
THROW(APPMAN_E_INVALIDPARAMETERS);
}
//
// Make sure that the lpData parameter is valid
//
if (NULL == lpData)
{
THROW(APPMAN_E_INVALIDPARAMETERS);
}
if (IsBadWritePtr(lpData, dwDataLen))
{
THROW(APPMAN_E_INVALIDPARAMETERS);
}
//
// Make sure the dwKilobytes is not 0
//
if (0 == dwKilobytes)
{
THROW(APPMAN_E_INVALIDPARAMETERS);
}
//
// Lock this application and all of it's parents
//
if (SUCCEEDED(m_InformationManager.LockParentApplications(&sApplicationData, &m_sInstanceGuid)))
{
//
// Make sure to record that fact that the applications got locked (in case of a THROW)
//
fParentsLocked = TRUE;
if (SUCCEEDED(m_InformationManager.LockApplicationData(&sApplicationData, &m_sInstanceGuid)))
{
//
// Make sure to record the fact that this application is locked (in case of a THROW)
//
fLocked = TRUE;
//
// Get the space
//
sTempSpaceRecord.dwSize = sizeof(TEMP_SPACE_RECORD);
sTempSpaceRecord.dwStructId = TEMP_SPACE_STRUCT;
sTempSpaceRecord.dwKilobytes = dwKilobytes;
memcpy((LPVOID) &sTempSpaceRecord.sApplicationGuid, (LPVOID) &sApplicationData.sBaseInfo.sApplicationGuid, sizeof(GUID));
hResult = m_InformationManager.AddTempSpace(&sTempSpaceRecord);
if (FAILED(hResult))
{
THROW(hResult);
}
dwCharCount = StrLenW(sTempSpaceRecord.wszDirectory);
if (APP_PROPERTY_STR_ANSI == dwStringMask)
{
if (dwCharCount > dwDataLen)
{
m_InformationManager.RemoveTempSpace(&sTempSpaceRecord);
THROW(APPMAN_E_OVERFLOW);
}
CWin32API::WideCharToMultiByte((LPCWSTR) sTempSpaceRecord.wszDirectory, MAX_PATH_CHARCOUNT, (LPSTR) lpData, dwDataLen);
}
else
{
if (dwDataLen < (dwCharCount*2))
{
m_InformationManager.RemoveTempSpace(&sTempSpaceRecord);
THROW(APPMAN_E_OVERFLOW);
}
memcpy((LPVOID) lpData, (LPVOID) sTempSpaceRecord.wszDirectory, dwCharCount*2);
}
//
// Unlock this application
//
m_InformationManager.UnlockApplicationData(&sApplicationData, &m_sInstanceGuid);
}
//
// Unlock the parent applications
//
m_InformationManager.UnlockParentApplications(&sApplicationData, &m_sInstanceGuid);
}
}
///////////////////////////////////////////////////////////////////////////////////////
catch(CAppManExceptionHandler * pException)
{
//
// Unlock the applications if required
//
if (fParentsLocked)
{
m_InformationManager.UnlockParentApplications(&sApplicationData, &m_sInstanceGuid);
}
//
// Is this application locked
//
if (fLocked)
{
m_InformationManager.UnlockApplicationData(&sApplicationData, &m_sInstanceGuid);
}
hResult = pException->GetResultCode();
delete pException;
}
catch(...)
{
//
// Unlock the applications if required
//
if (fParentsLocked)
{
m_InformationManager.UnlockParentApplications(&sApplicationData, &m_sInstanceGuid);
}
//
// Is this application locked
//
if (fLocked)
{
m_InformationManager.UnlockApplicationData(&sApplicationData, &m_sInstanceGuid);
}
hResult = E_UNEXPECTED;
}
///////////////////////////////////////////////////////////////////////////////////////
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
// TODO
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CApplicationEntry::RemoveTemporarySpace(const DWORD dwStringMask, LPVOID lpData, const DWORD dwDataLen)
{
FUNCTION("CAppEntry::RemoveTemporarySpace ()");
HRESULT hResult = S_OK;
APPLICATION_DATA sApplicationData;
///////////////////////////////////////////////////////////////////////////////////////
try
{
TEMP_SPACE_RECORD sTempSpaceRecord;
DWORD dwCharCount;
//
// Are the required properties set
//
if (S_OK != m_InformationManager.IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_GUID, &m_sApplicationData))
{
THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
}
//
// Is the object a valid application object
//
memcpy((LPVOID) &sApplicationData, (LPVOID) &m_sApplicationData, sizeof(APPLICATION_DATA));
hResult = m_InformationManager.GetApplicationData(&sApplicationData);
if (FAILED(hResult))
{
THROW(APPMAN_E_UNKNOWNAPPLICATION);
}
//
// Make sure the string mask is good
//
if ((APP_PROPERTY_STR_ANSI != dwStringMask)&&(APP_PROPERTY_STR_UNICODE != dwStringMask))
{
THROW(APPMAN_E_INVALIDPARAMETERS);
}
//
// Check to make sure dwDataLen is greater than 0
//
if (0 == dwDataLen)
{
THROW(APPMAN_E_INVALIDPARAMETERS);
}
//
// Make sure that the lpData parameter is valid
//
if (NULL == lpData)
{
THROW(APPMAN_E_INVALIDPARAMETERS);
}
if (IsBadReadPtr(lpData, dwDataLen))
{
THROW(APPMAN_E_INVALIDPARAMETERS);
}
//
// Initialize the sTempSpaceRecord structure
//
sTempSpaceRecord.dwSize = sizeof(TEMP_SPACE_RECORD);
sTempSpaceRecord.dwStructId = TEMP_SPACE_STRUCT;
memcpy((LPVOID) &sTempSpaceRecord.sApplicationGuid, (LPVOID) &sApplicationData.sBaseInfo.sApplicationGuid, sizeof(GUID));
if (APP_PROPERTY_STR_ANSI == dwStringMask)
{
dwCharCount = StrLenA((LPSTR) lpData);
if (dwCharCount > MAX_PATH_CHARCOUNT)
{
THROW(APPMAN_E_OVERFLOW);
}
CWin32API::MultiByteToWideChar((LPCSTR) lpData, dwDataLen, sTempSpaceRecord.wszDirectory, MAX_PATH_CHARCOUNT);
}
else
{
dwCharCount = StrLenW((LPWSTR) lpData);
if (dwCharCount > MAX_PATH_CHARCOUNT)
{
THROW(APPMAN_E_OVERFLOW);
}
memcpy((LPVOID) sTempSpaceRecord.wszDirectory, (LPVOID) lpData, dwCharCount*2);
}
//
// Delete the temporary space
//
hResult = m_InformationManager.RemoveTempSpace(&sTempSpaceRecord);
}
///////////////////////////////////////////////////////////////////////////////////////
catch(CAppManExceptionHandler * pException)
{
hResult = pException->GetResultCode();
delete pException;
}
catch(...)
{
hResult = E_UNEXPECTED;
}
///////////////////////////////////////////////////////////////////////////////////////
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
// TODO
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CApplicationEntry::EnumTemporarySpaces(const DWORD dwTargetIndex, LPDWORD lpdwSpace, const DWORD dwStringMask, LPVOID lpData, const DWORD dwDataLen)
{
FUNCTION("CAppEntry::EnumTemporarySpaces ()");
HRESULT hResult = S_OK;
APPLICATION_DATA sApplicationData;
///////////////////////////////////////////////////////////////////////////////////////
try
{
TEMP_SPACE_RECORD sTempSpaceRecord;
DWORD dwIndex, dwActualIndex;
DWORD dwCharCount;
//
// Are the required properties set
//
if (S_OK != m_InformationManager.IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_GUID, &m_sApplicationData))
{
THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
}
//
// Is the object a valid application object
//
memcpy((LPVOID) &sApplicationData, (LPVOID) &m_sApplicationData, sizeof(APPLICATION_DATA));
hResult = m_InformationManager.GetApplicationData(&sApplicationData);
if (FAILED(hResult))
{
THROW(APPMAN_E_UNKNOWNAPPLICATION);
}
//
// Make sure the string mask is good
//
if ((APP_PROPERTY_STR_ANSI != dwStringMask)&&(APP_PROPERTY_STR_UNICODE != dwStringMask))
{
THROW(APPMAN_E_INVALIDPARAMETERS);
}
//
// Check to make sure dwDataLen is greater than 0
//
if (0 == dwDataLen)
{
THROW(APPMAN_E_INVALIDPARAMETERS);
}
//
// Make sure that the lpData parameter is valid
//
if (NULL == lpData)
{
THROW(APPMAN_E_INVALIDPARAMETERS);
}
if (IsBadWritePtr(lpData, dwDataLen))
{
THROW(APPMAN_E_INVALIDPARAMETERS);
}
//
// Check to make sure lpdwSpace is valid
//
if (NULL == lpdwSpace)
{
THROW(APPMAN_E_INVALIDPARAMETERS);
}
if (IsBadWritePtr(lpdwSpace, sizeof(DWORD)))
{
THROW(APPMAN_E_INVALIDPARAMETERS);
}
//
// Get the nth temp space. Ignore temp spaces that are not owned by this application
//
dwActualIndex = dwTargetIndex;
dwIndex = 0;
do
{
hResult = m_InformationManager.EnumTempSpace(dwIndex, &sTempSpaceRecord);
if (S_OK == hResult)
{
if (memcmp((LPVOID) &sTempSpaceRecord.sApplicationGuid, (LPVOID) &sApplicationData.sBaseInfo.sApplicationGuid, sizeof(GUID)))
{
dwActualIndex++;
}
}
dwIndex++;
}
while ((dwIndex <= dwActualIndex)&&(S_OK == hResult));
//
// Did we find a target temp space
//
if (S_OK == hResult)
{
//
// Record the size
//
*lpdwSpace = sTempSpaceRecord.dwKilobytes;
//
// Record the string
//
dwCharCount = StrLenW(sTempSpaceRecord.wszDirectory);
if (APP_PROPERTY_STR_ANSI == dwStringMask)
{
if (dwCharCount > dwDataLen)
{
THROW(APPMAN_E_OVERFLOW);
}
CWin32API::WideCharToMultiByte((LPCWSTR) sTempSpaceRecord.wszDirectory, MAX_PATH_CHARCOUNT, (LPSTR) lpData, dwDataLen);
}
else
{
if (dwDataLen < (dwCharCount*2))
{
THROW(APPMAN_E_OVERFLOW);
}
memcpy((LPVOID) lpData, (LPVOID) sTempSpaceRecord.wszDirectory, dwCharCount*2);
}
}
}
///////////////////////////////////////////////////////////////////////////////////////
catch(CAppManExceptionHandler * pException)
{
hResult = pException->GetResultCode();
delete pException;
}
catch(...)
{
hResult = E_UNEXPECTED;
}
///////////////////////////////////////////////////////////////////////////////////////
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CApplicationEntry::ComputeOriginalApplicationSpaceInfo(void)
{
FUNCTION("CAppEntry::ComputeOriginalApplicationSpaceInfo ()");
CWin32API Win32API;
//
// Make sure the root paths are set
//
if (S_OK != m_InformationManager.IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_SETUPROOTPATH, &m_sApplicationData))
{
THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
}
if (S_OK != m_InformationManager.IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_ROOTPATH, &m_sApplicationData))
{
THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
}
//
// How much space is currently take by the application
//
m_dwOriginalSetupRootPathSizeKilobytes = Win32API.GetDirectorySize(m_sApplicationData.wszStringProperty[APP_STRING_SETUPROOTPATH]);
m_dwOriginalApplicationRootPathSizeKilobytes = Win32API.GetDirectorySize(m_sApplicationData.wszStringProperty[APP_STRING_APPROOTPATH]);
return S_OK;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CApplicationEntry::ComputeApplicationSpaceInfo(const DWORD dwInstalledKilobytesExpected)
{
FUNCTION("CAppEntry::ComputeApplicationSpaceInfo ()");
HRESULT hResult = S_OK;
DWORD dwSetupInstalledKilobytes, dwSetupUnInstalledKilobytes;
DWORD dwApplicationInstalledKilobytes, dwApplicationUnInstalledKilobytes;
DWORD dwInstalledKilobytes, dwUnInstalledKilobytes;
DWORD dwSetupRootPathSizeKilobytes, dwApplicationRootPathSizeKilobytes;
CWin32API Win32API;
//
// Make sure the root paths and estimated install kilobytes are set
//
if (S_OK != m_InformationManager.IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_SETUPROOTPATH, &m_sApplicationData))
{
THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
}
if (S_OK != m_InformationManager.IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_ROOTPATH, &m_sApplicationData))
{
THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
}
if (S_OK != m_InformationManager.IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_REMOVABLEKILOBYTES, &m_sApplicationData))
{
THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
}
if (S_OK != m_InformationManager.IsApplicationPropertyInitializedWithIndex(IDX_PROPERTY_NONREMOVABLEKILOBYTES, &m_sApplicationData))
{
THROW(APPMAN_E_REQUIREDPROPERTIESMISSING);
}
//
// What is the actual amount of kilobytes taken up by the application paths
//
dwSetupRootPathSizeKilobytes = Win32API.GetDirectorySize(m_sApplicationData.wszStringProperty[APP_STRING_SETUPROOTPATH]);
dwApplicationRootPathSizeKilobytes = Win32API.GetDirectorySize(m_sApplicationData.wszStringProperty[APP_STRING_APPROOTPATH]);
//
// Did we add or remove kilobytes from the setup root path
//
if (dwSetupRootPathSizeKilobytes > m_dwOriginalSetupRootPathSizeKilobytes)
{
dwSetupInstalledKilobytes = dwSetupRootPathSizeKilobytes - m_dwOriginalSetupRootPathSizeKilobytes;
dwSetupUnInstalledKilobytes = 0;
}
else
{
dwSetupInstalledKilobytes = 0;
dwSetupUnInstalledKilobytes = m_dwOriginalSetupRootPathSizeKilobytes - dwSetupRootPathSizeKilobytes;
}
//
// Did we add or remove kilobytes from the application root path
//
if (dwApplicationRootPathSizeKilobytes > m_dwOriginalApplicationRootPathSizeKilobytes)
{
dwApplicationInstalledKilobytes = dwApplicationRootPathSizeKilobytes - m_dwOriginalApplicationRootPathSizeKilobytes;
dwApplicationUnInstalledKilobytes = 0;
}
else
{
dwApplicationInstalledKilobytes = 0;
dwApplicationUnInstalledKilobytes = m_dwOriginalApplicationRootPathSizeKilobytes - dwApplicationRootPathSizeKilobytes;
}
//
// The total is
//
dwInstalledKilobytes = dwSetupInstalledKilobytes + dwApplicationInstalledKilobytes;
dwUnInstalledKilobytes = dwSetupUnInstalledKilobytes + dwApplicationUnInstalledKilobytes;
//
// Did we use up more kilobytes than expected
//
if (dwInstalledKilobytes > dwUnInstalledKilobytes)
{
if ((dwInstalledKilobytes - dwUnInstalledKilobytes) > dwInstalledKilobytesExpected)
{
DWORD dwExtraKilobytes;
//
// How many extra kilobytes were used up by the installation
//
dwExtraKilobytes = (dwInstalledKilobytes - dwUnInstalledKilobytes) - dwInstalledKilobytesExpected;
//
// Go get the space required to install the application on the device
//
hResult = m_InformationManager.FixCacheOverrun(&m_sApplicationData.sBaseInfo.sDeviceGuid, dwExtraKilobytes);
if (FAILED(hResult))
{
THROW(APPMAN_E_CACHEOVERRUN);
}
}
}
//
// Update the removable and non-removable space and validate the properties
//
m_sApplicationData.sBaseInfo.dwRemovableKilobytes += dwApplicationInstalledKilobytes;
if (m_sApplicationData.sBaseInfo.dwRemovableKilobytes > dwApplicationUnInstalledKilobytes)
{
m_sApplicationData.sBaseInfo.dwRemovableKilobytes -= dwApplicationUnInstalledKilobytes;
}
else
{
m_sApplicationData.sBaseInfo.dwRemovableKilobytes = 0;
}
m_sApplicationData.sBaseInfo.dwNonRemovableKilobytes += dwSetupInstalledKilobytes;
if (m_sApplicationData.sBaseInfo.dwNonRemovableKilobytes > dwSetupUnInstalledKilobytes)
{
m_sApplicationData.sBaseInfo.dwNonRemovableKilobytes -= dwSetupUnInstalledKilobytes;
}
else
{
m_sApplicationData.sBaseInfo.dwNonRemovableKilobytes = 0;
}
//
// Make sure dwRemovableKilobytes and dwNonRemovableKilobytes are not recursively adding
//
if (m_sApplicationData.sBaseInfo.dwRemovableKilobytes > dwApplicationRootPathSizeKilobytes)
{
m_sApplicationData.sBaseInfo.dwRemovableKilobytes = dwApplicationRootPathSizeKilobytes;
}
if (m_sApplicationData.sBaseInfo.dwNonRemovableKilobytes > dwSetupRootPathSizeKilobytes)
{
m_sApplicationData.sBaseInfo.dwNonRemovableKilobytes = dwSetupRootPathSizeKilobytes;
}
VALIDATE_PROPERTY(IDX_PROPERTY_REMOVABLEKILOBYTES);
VALIDATE_PROPERTY(IDX_PROPERTY_NONREMOVABLEKILOBYTES);
return hResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////////////////////
LPAPPLICATION_DATA CApplicationEntry::GetApplicationDataPtr(void)
{
FUNCTION("CAppEntry::GetApplicationDataPtr()");
return &m_sApplicationData;
}