|
|
#include <stdafx.h>
#include <adminpak.h>
#include <objidl.h>
#include "shlobj.h"
// shortcut icons table ConditionType definition
#define SHI_TYPE_NONE 0
#define SHI_TYPE_SEARCH 1 // searches for existence of component's key file
#define SHI_TYPE_INSTALLCOMPONENT 2 // checked for the component mentioned in the
// Condition column at HKLM\SOFTWARE\Microsoft\CurrentVersion\Setup\OC Manager\Subcomponents
#define SHI_TYPE_CONDITION 3 // evaluate the condition specified
#define SAFE_EXECUTE_CS( statement ) \
hr = statement; \ if ( FAILED( hr ) ) \ { \ bResult = FALSE; \ goto cleanup; \ } \ 1
#define SAFE_RELEASE( pointer ) \
if ( (pointer) != NULL ) \ { \ (pointer)->Release(); \ (pointer) = NULL; \ } \ 1
//
// prototypes
//
BOOL IsComponentInstalled( LPCWSTR pwszComponent ); BOOL LocateFile( LPCWSTR pwszFile, LPCWSTR pwszDirectory, PBOOL pbShortForm = NULL ); BOOL CheckForComponents( HKEY hKey, LPCWSTR pwszComponents ); BOOL CreateShortcut( LPCWSTR pwszShortcut, LPCWSTR pwszDescription, LPCWSTR pwszDirectory, LPCWSTR pwszFileName, LPCWSTR pwszArguments, LPCWSTR pwszWorkingDir, WORD wHotKey, INT nShowCmd, LPCWSTR pwszIconFile, DWORD dwIconIndex );
//
// implementation
//
BOOL PropertyGet_String( MSIHANDLE hInstall, LPCWSTR pwszProperty, CHString& strValue ) { // local variables
DWORD dwLength = 0; DWORD dwResult = 0; LPWSTR pwszValue = NULL; BOOL bSecondChance = FALSE;
// check the input arguments
if ( hInstall == NULL || pwszProperty == NULL ) { return FALSE; }
try { // mark this as first chance
dwLength = 255; bSecondChance = FALSE;
//
// re-start point
//
retry_get:
// get the pointer to the internal buffer
pwszValue = strValue.GetBufferSetLength( dwLength + 1 );
// get the value from the MSI record and check the result
dwResult = MsiGetPropertyW( hInstall, pwszProperty, pwszValue, &dwLength ); if ( dwResult == ERROR_MORE_DATA && bSecondChance == FALSE ) { // now go back and try to the read the value again
bSecondChance = TRUE; goto retry_get; } else if ( dwResult != ERROR_SUCCESS ) { SetLastError( dwResult ); strValue.ReleaseBuffer( 1 ); // simply pass some number
return FALSE; }
// release the buffer
strValue.ReleaseBuffer( dwLength );
// return the result
return TRUE; } catch( ... ) { return FALSE; } }
BOOL GetFieldValueFromRecord_String( MSIHANDLE hRecord, DWORD dwColumn, CHString& strValue ) { // local variables
DWORD dwLength = 0; DWORD dwResult = 0; LPWSTR pwszValue = NULL; BOOL bSecondChance = FALSE;
// check the input
if ( hRecord == NULL ) { return FALSE; }
try {
// mark this as first chance
dwLength = 255; bSecondChance = FALSE;
//
// re-start point
//
retry_get:
// get the pointer to the internal buffer
pwszValue = strValue.GetBufferSetLength( dwLength + 1 );
// get the value from the MSI record and check the result
dwResult = MsiRecordGetStringW( hRecord, dwColumn, pwszValue, &dwLength ); if ( dwResult == ERROR_MORE_DATA && bSecondChance == FALSE ) { // now go back and try to the read the value again
bSecondChance = TRUE; goto retry_get; } else if ( dwResult != ERROR_SUCCESS ) { SetLastError( dwResult ); return FALSE; }
// release the buffer
strValue.ReleaseBuffer( dwLength );
// we successfully got the value from the record
return TRUE; } catch( ... ) { return FALSE; } }
BOOL CreateShortcut( LPCWSTR pwszShortcut, LPCWSTR pwszDescription, LPCWSTR pwszDirectory, LPCWSTR pwszFileName, LPCWSTR pwszArguments, LPCWSTR pwszWorkingDir, WORD wHotKey, INT nShowCmd, LPCWSTR pwszIconFile, DWORD dwIconIndex ) { // local variables
CHString str; HRESULT hr = S_OK; HANDLE hFile = NULL; BOOL bResult = FALSE; IShellLinkW* pShellLink = NULL; IPersistFile* pPersistFile = NULL;
// check the input parameters
// we dont care about the input for pwszArguments parameter
if ( pwszShortcut == NULL || pwszDescription == NULL || pwszDirectory == NULL || pwszFileName == NULL || pwszWorkingDir == NULL || pwszIconFile == NULL ) { return FALSE; }
try { //
// check if shortcut is already existing at this location or not
//
// prepare the link name and save it
str.Format( L"%s%s", pwszDirectory, pwszShortcut ); if ( str.Mid( str.GetLength() - 4 ).CompareNoCase( L".lnk" ) != 0 ) { str += ".lnk"; }
// try to open the file
hFile = CreateFileW( str, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if ( hFile != INVALID_HANDLE_VALUE ) { // close the handle to the file
CloseHandle( hFile );
// shortcut is alreadt existing -- so, dont create it again
bResult = TRUE; goto cleanup; } //
// shortcut is not existing -- so we need to create it now
//
// get the pointer to the IShellLink interface
SAFE_EXECUTE_CS( CoCreateInstance( CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, (LPVOID*) &pShellLink ) );
// get the pointer to the IPersistFile interface
SAFE_EXECUTE_CS( pShellLink->QueryInterface( IID_IPersistFile, (LPVOID*) &pPersistFile ) );
// set the working directory for the shortcut.
SAFE_EXECUTE_CS( pShellLink->SetWorkingDirectory( pwszWorkingDir ) );
// prepare the shortcut name -- path (working dir) + file name -- finally set the path
// NOTE: we assume path containded in pwszWorkingDir ends with "\"
str.Format( L"%s%s", pwszWorkingDir, pwszFileName ); SAFE_EXECUTE_CS( pShellLink->SetPath( str ) );
// check if arguments needs to set
if ( pwszArguments == NULL || lstrlenW( pwszArguments ) > 0 ) { SAFE_EXECUTE_CS( pShellLink->SetArguments( pwszArguments ) ); }
// set the description
SAFE_EXECUTE_CS( pShellLink->SetDescription( pwszDescription ) );
// set icon location
SAFE_EXECUTE_CS( pShellLink->SetIconLocation( pwszIconFile, ((dwIconIndex == MSI_NULL_INTEGER) ? 0 : dwIconIndex) ) );
// set hotkey
if ( wHotKey != MSI_NULL_INTEGER ) { SAFE_EXECUTE_CS( pShellLink->SetHotkey( wHotKey ) ); }
// set showcmd
if ( nShowCmd != MSI_NULL_INTEGER ) { SAFE_EXECUTE_CS( pShellLink->SetShowCmd( nShowCmd ) ); }
// prepare the link name and save it
str.Format( L"%s%s", pwszDirectory, pwszShortcut ); if ( str.Mid( str.GetLength() - 4 ).CompareNoCase( L".lnk" ) != 0 ) { str += ".lnk"; }
// ...
SAFE_EXECUTE_CS( pPersistFile->Save( str, TRUE ) );
// mark the result as success
bResult = TRUE; } catch( ... ) { bResult = FALSE; }
// default clean up
cleanup:
// release the interfaces
SAFE_RELEASE( pShellLink ); SAFE_RELEASE( pPersistFile );
// return
return bResult; }
extern "C" ADMINPAK_API int _stdcall fnReCreateShortcuts( MSIHANDLE hInstall ) { // local variables
CHString str; HRESULT hr = S_OK; BOOL bFileFound = FALSE; BOOL bCreateShortcut = FALSE; DWORD dwResult = ERROR_SUCCESS;
// MSI handles
PMSIHANDLE hView = NULL; PMSIHANDLE hRecord = NULL; PMSIHANDLE hDatabase = NULL;
// query field variables
WORD wHotKey = 0; INT nShowCmd = 0; CHString strShortcut; CHString strFileName; CHString strIconFile; CHString strDirectory; CHString strArguments; CHString strCondition; DWORD dwIconIndex = 0; CHString strWorkingDir; CHString strDescription; CHString strIconDirectory; DWORD dwConditionType = 0;
// sql for retrieving the information from MSI table
const WCHAR cwszSQL[] = L" SELECT DISTINCT" L" `Shortcut`.`Name`, `Shortcut`.`Description`, `Shortcut`.`Directory_`, `File`.`FileName`, " L" `Shortcut`.`Arguments`, `Component`.`Directory_`, `Shortcut`.`Hotkey`, `Shortcut`.`ShowCmd`, " L" `ShortcutIcons`.`IconDirectory_`, `ShortcutIcons`.`IconFile`, `ShortcutIcons`.`IconIndex`, " L" `ShortcutIcons`.`ConditionType`, `ShortcutIcons`.`Condition` " L" FROM `Shortcut`, `Component`, `File`, `ShortcutIcons` " L" WHERE `Shortcut`.`Component_` = `Component`.`Component` " L" AND `Component`.`KeyPath` = `File`.`File` " L" AND `ShortcutIcons`.`Shortcut_` = `Shortcut`.`Shortcut`";
// column indices into the record
enum { Shortcut = 1, Description, Directory, FileName, Arguments, WorkingDir, HotKey, ShowCmd, IconDirectory, IconFile, IconIndex, ConditionType, Condition };
// initialize the COM library
hr = CoInitializeEx( NULL, COINIT_APARTMENTTHREADED ); if ( FAILED( hr ) ) { dwResult = ERROR_INVALID_HANDLE; goto cleanup; }
// get a handle on the MSI database
hDatabase = MsiGetActiveDatabase( hInstall ); if ( hDatabase == NULL ) { dwResult = ERROR_INVALID_HANDLE; goto cleanup; } // get a view of our table in the MSI
dwResult = MsiDatabaseOpenViewW( hDatabase, cwszSQL, &hView ); if ( dwResult != ERROR_SUCCESS ) { dwResult = ERROR_INVALID_HANDLE; goto cleanup; } // if no errors, get our records
dwResult = MsiViewExecute( hView, NULL ); if( dwResult != ERROR_SUCCESS ) { dwResult = ERROR_INVALID_HANDLE; goto cleanup; }
// loop through the result records obtain via SQL
hRecord = NULL; while( MsiViewFetch( hView, &hRecord ) == ERROR_SUCCESS ) { // get the values from the record
wHotKey = (WORD) MsiRecordGetInteger( hRecord, HotKey ); nShowCmd = MsiRecordGetInteger( hRecord, ShowCmd ); dwIconIndex = MsiRecordGetInteger( hRecord, IconIndex ); dwConditionType = MsiRecordGetInteger( hRecord, ConditionType ); GetFieldValueFromRecord_String( hRecord, Shortcut, strShortcut ); GetFieldValueFromRecord_String( hRecord, FileName, strFileName ); GetFieldValueFromRecord_String( hRecord, IconFile, strIconFile ); GetFieldValueFromRecord_String( hRecord, Directory, strDirectory ); GetFieldValueFromRecord_String( hRecord, Arguments, strArguments ); GetFieldValueFromRecord_String( hRecord, Condition, strCondition ); GetFieldValueFromRecord_String( hRecord, WorkingDir, strWorkingDir ); GetFieldValueFromRecord_String( hRecord, Description, strDescription ); GetFieldValueFromRecord_String( hRecord, IconDirectory, strIconDirectory );
// shortcut name might contain '|' as seperator for 8.3 and long name formats -- suppress this
if( strShortcut.Find( L'|' ) != -1 ) { str = strShortcut.Mid( strShortcut.Find( L'|' ) + 1 ); strShortcut = str; // store the result back
}
// transform the directory property references
TransformDirectory( hInstall, strDirectory ); TransformDirectory( hInstall, strWorkingDir ); TransformDirectory( hInstall, strIconDirectory );
// prepare the icon locatio
str.Format( L"%s%s", strIconDirectory, strIconFile ); strIconFile = str; // store the result back
//
// determine whether shortcut need to be created or not
//
// if the condition type is not specified, assume it "SEARCH"
if ( dwConditionType == MSI_NULL_INTEGER ) { dwConditionType = SHI_TYPE_SEARCH; }
// no matter what the "ConditionType" -- since creation of the shortcut very much depends
// on the existence of the file, we will try to locate for the file first -- this is necessary condition
// so, do a simple file search for the component key file
bFileFound = LocateFile( strFileName, strWorkingDir, NULL );
// proceed with rest of the conditions only if necessary condition is satisfied
if ( bFileFound == TRUE ) { //
// now do additional sufficient conditon(s) if needed
//
bCreateShortcut = FALSE; if ( dwConditionType == SHI_TYPE_SEARCH ) { // search is already successful
bCreateShortcut = TRUE; } else if ( dwConditionType == SHI_TYPE_INSTALLCOMPONENT ) { // check whether the component specified in 'Condition' field is installed or not
bCreateShortcut = IsComponentInstalled( strCondition ); } else if ( dwConditionType == SHI_TYPE_CONDITION ) { // evaluate the condition specified by the user
if ( MsiEvaluateConditionW( hInstall, strCondition ) == MSICONDITION_TRUE ) { bCreateShortcut = TRUE; } }
// check the shortcut if needed
if ( bCreateShortcut == TRUE ) { CreateShortcut( strShortcut, strDescription, strDirectory, strFileName, strArguments, strWorkingDir, wHotKey, nShowCmd, strIconFile, dwIconIndex ); } }
// close the MSI handle to the current record object -- ignore the error
MsiCloseHandle( hRecord ); hRecord = NULL; }
// mark the flag as success
dwResult = ERROR_SUCCESS;
//
// cleanup
//
cleanup:
// un-initialize the COM library
CoUninitialize();
// close the handle to the record
if ( hRecord != NULL ) { MsiCloseHandle( hRecord ); hRecord = NULL; } // close View -- ignore the errors
if ( hView != NULL ) { MsiViewClose( hView ); hView = NULL; }
// close the database handle
if ( hDatabase != NULL ) { MsiCloseHandle( hDatabase ); hDatabase = NULL; }
// return
return dwResult; }
BOOL LocateFile( LPCWSTR pwszFile, LPCWSTR pwszDirectory, PBOOL pbShortForm ) { // local variables
INT nPosition = 0; HANDLE hFind = NULL; BOOL bFound = FALSE; CHString strPath; CHString strFileName; WIN32_FIND_DATAW findData;
// check the optional parameter
if ( pbShortForm != NULL ) { *pbShortForm = FALSE; }
// check the input
if ( pwszFile == NULL || pwszDirectory == NULL ) { return FALSE; }
try { // init the variable with file name passed
strFileName = pwszFile;
// check whether user specified two formats for this file (8.3 and long format)
nPosition = strFileName.Find( L'|' ); if ( nPosition != -1 ) { // extract the long file name first
CHString strTemp; strTemp = strFileName.Mid( nPosition + 1 ); strFileName = strTemp; // check the length of the file name
if ( strFileName.GetLength() == 0 ) { // invalid file name format
return FALSE; } }
// prepare the path
strPath.Format( L"%s%s", pwszDirectory, strFileName );
// search for this file
bFound = FALSE; hFind = FindFirstFileW( strPath, &findData ); if ( hFind == INVALID_HANDLE_VALUE ) { // find failed -- may be file is not found -- confirm this
bFound = FALSE; if ( GetLastError() == ERROR_FILE_NOT_FOUND ) { // yes -- file is not found
} } else { // file is located
// take the actions needed
// close the handle to the file search first
FindClose( hFind ); hFind = NULL;
// set the flag
bFound = TRUE; if ( pbShortForm != NULL ) { *pbShortForm = FALSE; } }
//
// file is not found in long format
// may be, it is existed in 8.3 format
// so, check whether user supplied 8.3 file name for this file
if ( nPosition != -1 && bFound == FALSE ) { // extract the 8.3 format of the file name
CHString strTemp; strTemp = pwszFile; strFileName = strTemp.Mid( 0, nPosition );
// prepare the path
strPath.Format( L"%s%s", pwszDirectory, strFileName );
// search for this file
bFound = FALSE; hFind = FindFirstFileW( strPath, &findData ); if ( hFind == INVALID_HANDLE_VALUE ) { // find failed -- may be file is not found -- confirm this
if ( GetLastError() == ERROR_FILE_NOT_FOUND ) { // yes -- file is not found
} } else { // file is located
// take the actions needed
// close the handle to the file search first
FindClose( hFind ); hFind = NULL;
// set the flag
bFound = TRUE; if ( pbShortForm != NULL ) { *pbShortForm = TRUE; } } } } catch( ... ) { return FALSE; }
// return the result of search
return bFound; }
BOOL IsComponentInstalled( LPCWSTR pwszComponent ) { // local variables
HKEY hKey = NULL; LONG lResult = 0; LONG lPosition = 0; CHString strTemp; CHString strComponent; CHString strComponents; BOOL bComponentInstalled = FALSE; const WCHAR cwszSubKey[] = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup\\OC Manager\\Subcomponents";
// open the registry path
lResult = RegOpenKeyExW( HKEY_LOCAL_MACHINE, cwszSubKey, 0, KEY_READ, &hKey ); if ( lResult != ERROR_SUCCESS ) { SetLastError( lResult ); return FALSE; }
//
// since components may be multiple -- we need to check for each and every component
//
try { // get the component -- ready for processing
strComponents = pwszComponent;
// loop until there are no more components
bComponentInstalled = FALSE; while ( strComponents.GetLength() != 0 ) { // extract the first component
lPosition = strComponents.Find( L';' ); if ( lPosition != -1 ) { strComponent = strComponents.Mid( 0, lPosition ); strTemp = strComponents.Mid( lPosition + 1 ); strComponents = strTemp; } else { // there is only one component
strComponent = strComponents; strComponents = L""; }
// check for the components existence
if ( CheckForComponents( hKey, strComponent ) == TRUE ) { // since this is an OR condition checking -- if atleast one component in installed
// then we will return from here itself as there wont be any meaning in checking for the
// existence of other components -- the condition is satisfied
bComponentInstalled = TRUE; break; } }
} catch( ... ) { // ignore the exception
}
// we are done with the opened registry key -- we can close it
RegCloseKey( hKey ); hKey = NULL;
// return the result
return bComponentInstalled; }
BOOL CheckForComponents( HKEY hKey, LPCWSTR pwszComponents ) { // local variables
LONG lResult = 0; DWORD dwType = 0; DWORD dwSize = 0; DWORD dwValue = 0; CHString strTemp; CHString strComponent; CHString strComponents; LONG lPosition = 0;
// check the input
if ( hKey == NULL || pwszComponents == NULL ) { return FALSE; }
try { // ...
strComponents = pwszComponents; if ( strComponents.GetLength() == 0 ) { return FALSE; }
// loop until all the components are checked
while ( strComponents.GetLength() != 0 ) { // extract the first component
lPosition = strComponent.Find( L',' ); if ( lPosition != -1 ) { strComponent = strComponents.Mid( 0, lPosition ); strTemp = strComponents.Mid( lPosition + 1 ); strComponents = strTemp; } else { // there is only one component
strComponent = strComponents; strComponents = L""; }
// now check for this component in registry
dwSize = sizeof( DWORD ); lResult = RegQueryValueExW( hKey, strComponent, NULL, &dwType, (LPBYTE) &dwValue, &dwSize );
// *) check result of the registry query operation
// *) confirm the type of the value -- it should be REG_DWORD
// *) also check the state of the component and return the accordingly
// 1 Installed
// 0 Not Installed
strTemp.Format( L"%d", dwValue ); if ( lResult != ERROR_SUCCESS || dwType != REG_DWORD || dwValue == 0 ) { // no matter what is the reason -- we will treat this as
// component is not installed at all
//
// and since this is an AND condition checking -- if atleast one component in not installed
// then we will return from here itself as there wont be any meaning in checking for the
// existence of other components
return FALSE; } } } catch( ... ) { return FALSE; }
// if the control came to this point -- it is obvious that required components are installed
return TRUE; }
BOOL TransformDirectory( MSIHANDLE hInstall, CHString& strDirectory ) { // local variables
CHString strActualDirectory;
// check the input parameters
if ( hInstall == NULL ) { return FALSE; }
try { // get the property value
PropertyGet_String( hInstall, strDirectory, strActualDirectory );
// assign the property value to the input argument
strDirectory = strActualDirectory;
// return
return TRUE; } catch( ... ) { return FALSE; } }
// remove the shortcuts that are created by W2K version of adminpak.msi (W2K -> .NET upgrade scenario)
extern "C" ADMINPAK_API int _stdcall fnDeleteW2KShortcuts( MSIHANDLE hInstall ) { // local variables
CHString str; HRESULT hr = S_OK; BOOL bFileFound = FALSE; BOOL bShortForm = FALSE; BOOL bCreateShortcut = FALSE; DWORD nPosition = 0; DWORD dwResult = ERROR_SUCCESS;
// MSI handles
PMSIHANDLE hView = NULL; PMSIHANDLE hRecord = NULL; PMSIHANDLE hDatabase = NULL;
// query field variables
CHString strShortcut; CHString strNewShortcut; CHString strShortcutDirectory; CHString strRecreate; CHString strFileDirectory; CHString strFileName; CHString strArguments; CHString strDescription; CHString strIconDirectory; CHString strIconFile; DWORD dwIconIndex = 0; DWORD dwConditionType = 0; CHString strCondition;
// sql for retrieving the information from MSI table
const WCHAR cwszSQL[] = L"SELECT * FROM `W2KShortcutCleanup`";
// column indices into the record
enum { Shortcut = 2, ShortcutDirectory, Recreate, NewShortcut, FileDirectory, FileName, Arguments, Description, IconDirectory, IconFile, IconIndex, ConditionType, Condition };
// initialize the COM library
hr = CoInitializeEx( NULL, COINIT_APARTMENTTHREADED ); if ( FAILED( hr ) ) { dwResult = ERROR_INVALID_HANDLE; goto cleanup; }
// get a handle on the MSI database
hDatabase = MsiGetActiveDatabase( hInstall ); if ( hDatabase == NULL ) { dwResult = ERROR_INVALID_HANDLE; goto cleanup; }
// get a view of our table in the MSI
dwResult = MsiDatabaseOpenViewW( hDatabase, cwszSQL, &hView ); if ( dwResult != ERROR_SUCCESS ) { dwResult = ERROR_INVALID_HANDLE; goto cleanup; }
// if no errors, get our records
dwResult = MsiViewExecute( hView, NULL ); if( dwResult != ERROR_SUCCESS ) { dwResult = ERROR_INVALID_HANDLE; goto cleanup; }
try { // loop through the result records obtain via SQL
hRecord = NULL; while( MsiViewFetch( hView, &hRecord ) == ERROR_SUCCESS ) { // get the values from the record
dwIconIndex = MsiRecordGetInteger( hRecord, IconIndex ); dwConditionType = MsiRecordGetInteger( hRecord, ConditionType ); GetFieldValueFromRecord_String( hRecord, Shortcut, strShortcut ); GetFieldValueFromRecord_String( hRecord, NewShortcut, strNewShortcut ); GetFieldValueFromRecord_String( hRecord, Recreate, strRecreate ); GetFieldValueFromRecord_String( hRecord, FileName, strFileName ); GetFieldValueFromRecord_String( hRecord, IconFile, strIconFile ); GetFieldValueFromRecord_String( hRecord, Arguments, strArguments ); GetFieldValueFromRecord_String( hRecord, Condition, strCondition ); GetFieldValueFromRecord_String( hRecord, Description, strDescription ); GetFieldValueFromRecord_String( hRecord, FileDirectory, strFileDirectory ); GetFieldValueFromRecord_String( hRecord, IconDirectory, strIconDirectory ); GetFieldValueFromRecord_String( hRecord, ShortcutDirectory, strShortcutDirectory );
// transform the directory property references
TransformDirectory( hInstall, strFileDirectory ); TransformDirectory( hInstall, strIconDirectory ); TransformDirectory( hInstall, strShortcutDirectory ); // search for the existence of the shortcut
if ( LocateFile( strShortcut, strShortcutDirectory ) == FALSE ) { // file is not found
goto loop_cleanup; }
//
// shortcut is found
//
// delete the shortcut
//
// file might be in short name or long name -- so attempt to delete the appropriate file only
nPosition = strShortcut.Find( L'|' ); if ( nPosition != -1 ) { if ( bShortForm == TRUE ) { str = strShortcut.Mid( 0, nPosition ); } else { str = strShortcut.Mid( nPosition + 1 ); }
// ...
strShortcut = str; }
str.Format( L"%s%s", strShortcutDirectory, strShortcut ); if ( DeleteFileW( str ) == FALSE ) { // failed to delete the file
goto loop_cleanup; }
// check if the directory is empty or not --
// if the directory is empty, delete the directory also
if ( LocateFile( L"*.lnk", strShortcutDirectory ) == FALSE ) { // directory is empty -- delete it
// NOTE: we dont care about the suceess of the function call
RemoveDirectoryW( strShortcutDirectory ); }
// check whether we need to recreate the shortcut or not
if ( strRecreate == L"N" ) { // no need to create the shortcut
goto loop_cleanup; }
//
// we need to recreate the shortcut
//
// prepare the icon location
str.Format( L"%s%s", strIconDirectory, strIconFile ); strIconFile = str; // store the result back
//
// determine whether shortcut need to be created or not
//
// if the condition type is not specified, assume it "SEARCH"
if ( dwConditionType == MSI_NULL_INTEGER ) { dwConditionType = SHI_TYPE_SEARCH; }
// no matter what the "ConditionType" -- since creation of the shortcut very much depends
// on the existence of the file, we will try to locate for the file first -- this is necessary condition
// so, do a simple file search for the component key file
bFileFound = LocateFile( strFileName, strFileDirectory );
// proceed with rest of the conditions only if necessary condition is satisfied
if ( bFileFound == TRUE ) { //
// now do additional sufficient conditon(s) if needed
//
bCreateShortcut = FALSE; if ( dwConditionType == SHI_TYPE_SEARCH ) { // search is already successful
bCreateShortcut = TRUE; } else if ( dwConditionType == SHI_TYPE_INSTALLCOMPONENT ) { // check whether the component specified in 'Condition' field is installed or not
bCreateShortcut = IsComponentInstalled( strCondition ); } else if ( dwConditionType == SHI_TYPE_CONDITION ) { // evaluate the condition specified by the user
if ( MsiEvaluateConditionW( hInstall, strCondition ) == MSICONDITION_TRUE ) { bCreateShortcut = TRUE; } }
// check the shortcut if needed
if ( bCreateShortcut == TRUE ) { CreateShortcut( ((strNewShortcut.GetLength() == 0) ? strShortcut : strNewShortcut), strDescription, strShortcutDirectory, strFileName, strArguments, strFileDirectory, 0, 0, strIconFile, dwIconIndex ); } }
loop_cleanup:
// close the MSI handle to the current record object -- ignore the error
MsiCloseHandle( hRecord ); hRecord = NULL; }
// mark the flag as success
dwResult = ERROR_SUCCESS; } catch( ... ) { // error
dwResult = ERROR_INVALID_HANDLE; }
//
// cleanup
//
cleanup:
// un-initialize the COM library
CoUninitialize();
// close the handle to the record
if ( hRecord != NULL ) { MsiCloseHandle( hRecord ); hRecord = NULL; } // close View -- ignore the errors
if ( hView != NULL ) { MsiViewClose( hView ); hView = NULL; }
// close the database handle
if ( hDatabase != NULL ) { MsiCloseHandle( hDatabase ); hDatabase = NULL; }
// return
return dwResult; }
|