|
|
//*************************************************************
//
// Copyright (c) Microsoft Corporation 1998-2000
// All rights reserved
//
// apis.cxx
//
//*************************************************************
#include "appmgmt.hxx"
static CLoadMsi * gLoadMsi = 0; static WCHAR * gpwszWinsta = 0;
static DWORD ReportInstallStatus( PINSTALLCONTEXT pInstallContext, DWORD InstallStatus, BOOL bUninstall, WCHAR * pwszDeploymentName, WCHAR * pwszGPOName, WCHAR * pwszDeploymentId );
DWORD WINAPI InstallApplication( IN PINSTALLDATA pInstallData ) { APPKEY AppKey; HINSTANCE hMsi; MSICONFIGUREPRODUCTEXW * pfnConfigureProduct; PINSTALLCONTEXT pInstallContext; APPLICATION_INFO InstallInfo; UNINSTALL_APPS UninstallApps; DWORD InstallUILevel; INSTALLUILEVEL OldUILevel; DWORD UninstallCount; DWORD n; DWORD ExtraStatus; DWORD Status; BOOL bStatus; boolean bInstall;
Status = Bind();
if ( Status != ERROR_SUCCESS ) return Status;
if ( DebugLevelOn(DM_VERBOSE) ) { WCHAR * pwszCommandLine; WCHAR UserName[32]; DWORD NameLength;
NameLength = sizeof(UserName) / sizeof(WCHAR); UserName[0] = 0;
GetUserName( UserName, &NameLength );
pwszCommandLine = GetCommandLine(); if ( ! pwszCommandLine ) pwszCommandLine = L"";
DebugMsg((DM_VERBOSE, IDS_INSTALL_REQUEST, pwszCommandLine, UserName)); }
AppKey.Type = pInstallData->Type; AppKey.ProcessorArchitecture = DEFAULT_ARCHITECTURE;
switch ( pInstallData->Type ) { case APPNAME : AppKey.uType.AppName.Name = pInstallData->Spec.AppName.Name; memcpy( &AppKey.uType.AppName.PolicyId, &pInstallData->Spec.AppName.GPOId, sizeof(GUID) ); break; case FILEEXT : AppKey.uType.FileExt = pInstallData->Spec.FileExt; break; case PROGID : AppKey.uType.ProgId = pInstallData->Spec.ProgId; break; case COMCLASS : AppKey.uType.COMClass.Clsid = pInstallData->Spec.COMClass.Clsid; AppKey.uType.COMClass.ClsCtx = pInstallData->Spec.COMClass.ClsCtx;
break; default : return ERROR_INVALID_PARAMETER; }
pInstallContext = 0; memset( &InstallInfo, 0, sizeof(InstallInfo) ); memset( &UninstallApps, 0, sizeof(UninstallApps) );
Status = InstallBegin( ghRpc, &AppKey, &pInstallContext, &InstallInfo, &UninstallApps );
if ( Status != ERROR_SUCCESS ) return Status;
CLoadMsi LoadMsi( Status );
if ( Status != ERROR_SUCCESS ) goto InstallApplicationExit;
if ( InstallInfo.pwszSetupCommand ) { HINSTANCE hShell32; SHELLEXECUTEEXW * pfnShellExecuteEx; SHELLEXECUTEINFO ShellExInfo; WCHAR * pwszCommand; WCHAR * pwszParams; WCHAR * pwszDirectory;
pwszDirectory = NULL;
pfnShellExecuteEx = 0; hShell32 = LoadLibrary( L"shell32.dll" );
if ( hShell32 ) pfnShellExecuteEx = (SHELLEXECUTEEXW *) GetProcAddress( hShell32, "ShellExecuteExW" );
if ( ! pfnShellExecuteEx ) Status = GetLastError();
if ( ERROR_SUCCESS == Status ) { pwszCommand = InstallInfo.pwszSetupCommand;
if ( L'"' == pwszCommand[0] ) { pwszParams = wcschr( &pwszCommand[1], L'"' ); if ( pwszParams ) pwszCommand++; } else { pwszParams = wcschr( pwszCommand, L' ' ); }
if ( pwszParams ) { *pwszParams++ = 0; while ( L' ' == *pwszParams ) pwszParams++; } }
//
// Need to set the current directory to that
// containing the actual executable
//
if ( ERROR_SUCCESS == Status ) { WCHAR* pwszDirectoryEnd;
//
// Find the last pathsep, which marks the
// end of the containing directory -- if we
// don't find it, the admin specified some strange
// path and we'll just end up passing NULL for
// the current directory
//
pwszDirectoryEnd = wcsrchr( pwszCommand, L'\\' );
if ( pwszDirectoryEnd ) { //
// Get a copy of the full path that we can
// truncate to the containing directory
//
pwszDirectory = StringDuplicate( pwszCommand );
if ( pwszDirectory ) { //
// Truncate to the containing directory
//
pwszDirectory[ pwszDirectoryEnd - pwszCommand ] = L'\0'; } else { Status = ERROR_OUTOFMEMORY; } } }
if ( ERROR_SUCCESS == Status ) { ShellExInfo.cbSize = sizeof( ShellExInfo ); ShellExInfo.fMask = SEE_MASK_NOCLOSEPROCESS; ShellExInfo.hwnd = NULL; ShellExInfo.lpVerb = NULL; ShellExInfo.lpFile = pwszCommand; ShellExInfo.lpParameters = pwszParams; ShellExInfo.lpDirectory = pwszDirectory; ShellExInfo.nShow = SW_SHOWNORMAL; ShellExInfo.hProcess = 0;
DebugMsg((DM_VERBOSE, IDS_LEGACY_INSTALL, pwszCommand));
bStatus = (*pfnShellExecuteEx)( &ShellExInfo );
if ( ! bStatus ) Status = GetLastError(); }
delete [] pwszDirectory;
if ( hShell32 ) FreeLibrary( hShell32 );
if ( (ERROR_SUCCESS == Status) && ShellExInfo.hProcess ) { Status = WAIT_OBJECT_0;
if ( LoadUser32Funcs() ) { MSG msg; HANDLE Handles[2];
Handles[0] = ShellExInfo.hProcess;
for (;;) { Status = (*pfnMsgWaitForMultipleObjects)( 1, Handles, FALSE, INFINITE, QS_ALLINPUT );
if ( (WAIT_OBJECT_0+1) == Status ) { if ( (*pfnPeekMessageW)( &msg, NULL, 0, 0, PM_REMOVE) ) { (*pfnTranslateMessage)( &msg ); (*pfnDispatchMessageW)( &msg ); } continue; }
break; } }
CloseHandle( ShellExInfo.hProcess );
if ( WAIT_OBJECT_0 == Status ) Status = ERROR_SUCCESS; else Status = GetLastError(); }
gpEvents->ZAPInstall( Status, InstallInfo.pwszDeploymentName, InstallInfo.pwszGPOName, pwszCommand );
goto InstallApplicationExit; }
OldUILevel = (*gpfnMsiSetInternalUI)( INSTALLUILEVEL_NOCHANGE, NULL );
if ( UninstallApps.Products > 0 ) (*gpfnMsiSetInternalUI)( INSTALLUILEVEL_BASIC, NULL );
for ( UninstallCount = 0; UninstallCount < UninstallApps.Products; ) { if ( UninstallApps.ApplicationInfo[UninstallCount].Flags & APPINFOFLAG_UNINSTALL ) { DebugMsg((DM_VERBOSE, IDS_UNINSTALL, UninstallApps.ApplicationInfo[UninstallCount].pwszDeploymentName, UninstallApps.ApplicationInfo[UninstallCount].pwszGPOName));
//
// The MsiQueryProductState could fail due to out of memory -- it could
// return INSTALL_STATE_UNKNOWN in out of memory situations, and we would incorrectly
// unmanage the application -- so we use MsiGetProductInfo which returns a status
// that allows us to distinguish these cases
//
Status = gpfnMsiGetProductInfo( UninstallApps.ApplicationInfo[UninstallCount].pwszProductCode, INSTALLPROPERTY_PACKAGECODE, NULL, NULL);
//
// If the product is installed, try to uninstall. If it exists but has
// bad configuration data, attempt the uninstall anyway in the hope that
// it will get removed
//
if ( ( ERROR_SUCCESS == Status ) || ( ERROR_BAD_CONFIGURATION == Status ) ) { //
// ERROR_SUCCESS_REBOOT_INITIATED here will be treated as an error
// since we don't want to attempt to do an install if the machine
// is being rebooted.
// The two REJECTED errors can be encountered when the application is
// only advertised and is prevented from (un)installing by policy.
//
Status = (*gpfnMsiConfigureProductEx)( UninstallApps.ApplicationInfo[UninstallCount].pwszProductCode, INSTALLLEVEL_MAXIMUM, INSTALLSTATE_ABSENT, NULL );
if ( ERROR_SUCCESS_REBOOT_REQUIRED == Status ) { Status = ERROR_SUCCESS; } else if ( (ERROR_INSTALL_PACKAGE_REJECTED == Status) || (ERROR_INSTALL_TRANSFORM_REJECTED == Status) ) { Status = InstallUnmanageApp( pInstallContext, UninstallApps.ApplicationInfo[UninstallCount].pwszDeploymentId, TRUE ); } } else if ( ERROR_UNKNOWN_PRODUCT == Status ) { //
// If we didn't find the product, treat this as a successful removal
// since the desired state, absence of the app, is achieved.
//
Status = ERROR_SUCCESS; }
ReportInstallStatus( pInstallContext, Status, TRUE, UninstallApps.ApplicationInfo[UninstallCount].pwszDeploymentName, UninstallApps.ApplicationInfo[UninstallCount].pwszGPOName, UninstallApps.ApplicationInfo[UninstallCount].pwszDeploymentId); }
// Nothing to do here for an orphaned app.
if ( ERROR_SUCCESS == Status ) UninstallCount++;
if ( Status != ERROR_SUCCESS ) goto InstallApplicationRollback; }
Status = InstallManageApp( pInstallContext, InstallInfo.pwszDeploymentId, ERROR_SUCCESS, &bInstall );
if ( Status != ERROR_SUCCESS ) goto InstallApplicationRollback;
if ( InstallInfo.Flags & APPINFOFLAG_FULLUI ) InstallUILevel = INSTALLUILEVEL_FULL; else // InstallInfo.Flags & APPINFOFLAG_BASICUI
InstallUILevel = INSTALLUILEVEL_BASIC;
if ( (APPNAME == pInstallData->Type) && (InstallInfo.Flags & APPINFOFLAG_BASICUI) ) InstallUILevel |= INSTALLUILEVEL_ENDDIALOG;
(void) (*gpfnMsiSetInternalUI)( (INSTALLUILEVEL) InstallUILevel, NULL );
if ( InstallInfo.pwszDescriptor ) { DebugMsg((DM_VERBOSE, IDS_INSTALL_DESC, InstallInfo.pwszDeploymentName, InstallInfo.pwszGPOName)); Status = (*gpfnMsiProvideComponentFromDescriptor)( InstallInfo.pwszDescriptor, NULL, NULL, NULL ); REMAP_DARWIN_STATUS( Status );
ReportInstallStatus( pInstallContext, Status, FALSE, InstallInfo.pwszDeploymentName, InstallInfo.pwszGPOName, InstallInfo.pwszDeploymentId); } else { DebugMsg((DM_VERBOSE, IDS_INSTALL_PC, InstallInfo.pwszDeploymentName, InstallInfo.pwszGPOName)); Status = (*gpfnMsiConfigureProductEx)( InstallInfo.pwszProductCode, INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, NULL ); REMAP_DARWIN_STATUS( Status );
ReportInstallStatus( pInstallContext, Status, FALSE, InstallInfo.pwszDeploymentName, InstallInfo.pwszGPOName, InstallInfo.pwszDeploymentId); }
(void) (*gpfnMsiSetInternalUI)( OldUILevel, NULL );
//
// If the added app was already managed, any error must be ignored, we don't want to
// unmanage it in this case. Darwin rollback & repair should handle these cases.
//
if ( (Status != ERROR_SUCCESS) && (InstallInfo.Flags & APPINFOFLAG_ALREADYMANAGED) ) goto InstallApplicationExit;
if ( ERROR_SUCCESS == Status ) { //
// Now we can finally unmanage any upgraded apps.
// If these fail, it will be fixed up in a subsequent run of policy.
//
for ( n = 0; n < UninstallCount; n++ ) ExtraStatus = InstallUnmanageApp( pInstallContext, UninstallApps.ApplicationInfo[n].pwszDeploymentId, FALSE );
goto InstallApplicationExit; }
//
// Failed to install the new app, unmanage it and fall through to our rollback.
//
ExtraStatus = InstallUnmanageApp( pInstallContext, InstallInfo.pwszDeploymentId, FALSE );
InstallApplicationRollback:
for ( n = 0; n < UninstallCount; n++ ) { bInstall = FALSE; ExtraStatus = InstallManageApp( pInstallContext, UninstallApps.ApplicationInfo[n].pwszDeploymentId, Status, &bInstall ); if ( (ERROR_SUCCESS == ExtraStatus) && bInstall ) { (void) (*gpfnMsiConfigureProductEx)( UninstallApps.ApplicationInfo[n].pwszProductCode, INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT, NULL ); gpEvents->Install( Status, UninstallApps.ApplicationInfo[n].pwszDeploymentName, UninstallApps.ApplicationInfo[n].pwszGPOName ); } }
InstallApplicationExit:
if ( pInstallContext ) InstallEnd( (Status == ERROR_SUCCESS), &pInstallContext );
FreeApplicationInfo( &InstallInfo );
while ( UninstallApps.Products ) FreeApplicationInfo( &UninstallApps.ApplicationInfo[--UninstallApps.Products] ); LocalFree( UninstallApps.ApplicationInfo );
return Status; }
DWORD WINAPI UninstallApplication( IN WCHAR * ProductCode, IN DWORD dwStatus ) { DWORD Status;
Status = Bind();
if ( Status != ERROR_SUCCESS ) return Status;
return ARPRemoveApp( ghRpc, ProductCode, dwStatus ); }
DWORD WINAPI CommandLineFromMsiDescriptor( IN WCHAR * Descriptor, OUT WCHAR * CommandLine, IN OUT DWORD * CommandLineLength ) { INSTALLUILEVEL NewUILevel; INSTALLUILEVEL OldUILevel; HKEY hkAppmgmt; WCHAR ProductCode[40]; DWORD Size; DWORD ArgStart; DWORD Status;
Status = ERROR_SUCCESS;
//
// For this api we can not affort to dynamically load/unload msi each time, it
// is just called too frequently.
// We'll store the load object in a global rather then a static in case we
// add support for a call-in mechanism to free this.
//
if ( ! gLoadMsi ) gLoadMsi = new CLoadMsi( Status );
if ( gLoadMsi && (Status != ERROR_SUCCESS) ) { delete gLoadMsi; gLoadMsi = 0; }
if ( Status != ERROR_SUCCESS ) return Status;
if ( ! LoadUser32Funcs() ) return ERROR_OUTOFMEMORY;
//
// We get the process window station in order to detect processes running
// in non-interactive desktops where Darwin UI is not possible. Darwin
// itself is not aware of these situations.
//
if ( ! gpwszWinsta ) { HWINSTA hWinsta; BOOL bStatus;
hWinsta = (*pfnGetProcessWindowStation)();
if ( hWinsta ) { Size = 0; (void) (*pfnGetUserObjectInformationW)( hWinsta, UOI_NAME, NULL, 0, &Size );
gpwszWinsta = new WCHAR[Size/2]; if ( gpwszWinsta ) { bStatus = (*pfnGetUserObjectInformationW)( hWinsta, UOI_NAME, gpwszWinsta, Size, &Size ); if ( ! bStatus ) { Status = GetLastError(); delete [] gpwszWinsta; gpwszWinsta = 0; } } else Status = ERROR_OUTOFMEMORY;
(*pfnCloseWindowStation)( hWinsta ); }
//
// Since this code was added very late (just before nt5 rc3) we don't
// treat an error in getting the window station handle as a failure in
// this API. Too many unknowns with the security configuration of
// services. We'll treat this case as a non-winsta0 process.
//
}
if ( Status != ERROR_SUCCESS ) return Status;
//
// If we can't grab the winsta handle or can confirm that this is a
// non-winsta0 process, we fix the ui level to none.
//
if ( (0 == gpwszWinsta) || (lstrcmp( L"WinSta0", gpwszWinsta ) != 0) ) (*gpfnMsiSetInternalUI)( INSTALLUILEVEL_NONE, NULL );
OldUILevel = (*gpfnMsiSetInternalUI)( INSTALLUILEVEL_NOCHANGE, NULL );
//
// Some processes, like the dcom service, may not be able to handle UI
// of any kind. So if the UI level is currently set to none we never
// change it.
//
if ( OldUILevel != INSTALLUILEVEL_NONE ) { Status = (*gpfnMsiDecomposeDescriptor)( Descriptor, ProductCode, NULL, NULL, NULL );
if ( Status != ERROR_SUCCESS ) return Status;
Status = RegOpenKeyEx( HKEY_CURRENT_USER, APPMGMTKEY, 0, KEY_READ, &hkAppmgmt );
if ( ERROR_SUCCESS == Status ) { Size = sizeof( NewUILevel );
Status = RegQueryValueEx( hkAppmgmt, ProductCode, NULL, NULL, (PBYTE) &NewUILevel, &Size );
RegCloseKey( hkAppmgmt ); }
if ( ERROR_SUCCESS == Status ) (*gpfnMsiSetInternalUI)( NewUILevel, NULL ); }
//
// Returns a quoted exe path with appended args. The forth parameter
// is obsolete and returns no usefull value.
//
Status = (*gpfnMsiProvideComponentFromDescriptor)( Descriptor, CommandLine, CommandLineLength, &ArgStart );
REMAP_DARWIN_STATUS( Status );
if ( Status != ERROR_SUCCESS ) DebugMsg((DM_VERBOSE, IDS_DESC_FAIL, Descriptor, Status));
(*gpfnMsiSetInternalUI)( OldUILevel, NULL );
return Status; }
DWORD WINAPI GetLocalManagedApplications( IN BOOL bUserApps, OUT LPDWORD pdwApps, OUT PLOCALMANAGEDAPPLICATION * prgLocalApps )
{ PLOCALMANAGEDAPPLICATION pLocalApps; HKEY hkRoot; HKEY hkAppmgmt; HKEY hkApp; WCHAR wszDeploymentId[44]; DWORD Size; DWORD Index; DWORD Apps; DWORD Status;
*pdwApps = 0; *prgLocalApps = 0;
Status = ERROR_SUCCESS;
if ( bUserApps ) Status = RegOpenCurrentUser( KEY_READ, &hkRoot ); else hkRoot = HKEY_LOCAL_MACHINE;
if ( Status != ERROR_SUCCESS ) return Status;
Status = RegOpenKeyEx( hkRoot, APPMGMTKEY, 0, KEY_READ, &hkAppmgmt );
if ( Status != ERROR_SUCCESS ) return Status;
Status = RegQueryInfoKey ( hkAppmgmt, NULL, NULL, NULL, &Apps, NULL, NULL, NULL, NULL, NULL, NULL, NULL );
if ( ERROR_SUCCESS == Status ) { pLocalApps = (PLOCALMANAGEDAPPLICATION) LocalAlloc( LMEM_ZEROINIT, Apps * sizeof(LOCALMANAGEDAPPLICATION) ); if ( ! pLocalApps ) Status = ERROR_OUTOFMEMORY; }
if ( Status != ERROR_SUCCESS ) { RegCloseKey( hkAppmgmt ); if ( bUserApps ) RegCloseKey( hkRoot ); return ERROR_SUCCESS; }
for ( Index = 0; Index < Apps; Index++ ) { Status = RegEnumKey( hkAppmgmt, Index, wszDeploymentId, sizeof(wszDeploymentId) / sizeof(WCHAR) );
if ( ERROR_SUCCESS == Status ) { Status = RegOpenKeyEx( hkAppmgmt, wszDeploymentId, 0, KEY_READ, &hkApp ); }
if ( Status != ERROR_SUCCESS ) break;
Size = sizeof(DWORD);
Status = RegQueryValueEx( hkApp, APPSTATEVALUE, 0, NULL, (LPBYTE) &pLocalApps[Index].dwState, &Size );
if ( ERROR_SUCCESS == Status ) Status = ReadStringValue( hkApp, DEPLOYMENTNAMEVALUE, &pLocalApps[Index].pszDeploymentName );
if ( ERROR_SUCCESS == Status ) Status = ReadStringValue( hkApp, GPONAMEVALUE, &pLocalApps[Index].pszPolicyName );
if ( ERROR_SUCCESS == Status ) Status = ReadStringValue( hkApp, PRODUCTIDVALUE, &pLocalApps[Index].pszProductId );
RegCloseKey( hkApp );
if ( Status != ERROR_SUCCESS ) break; }
if ( Status != ERROR_SUCCESS ) { for ( Index = 0; Index < Apps; Index++ ) { LocalFree( pLocalApps[Index].pszDeploymentName ); LocalFree( pLocalApps[Index].pszPolicyName ); LocalFree( pLocalApps[Index].pszProductId ); } LocalFree( pLocalApps ); } else { *prgLocalApps = pLocalApps; *pdwApps = Apps; }
RegCloseKey( hkAppmgmt ); if ( bUserApps ) RegCloseKey( hkRoot );
return Status; }
void WINAPI GetLocalManagedApplicationData( WCHAR * ProductCode, LPWSTR * DisplayName, LPWSTR * SupportUrl ) { HKEY hkRoot; HKEY hkAppmgmt; HKEY hkApp; WCHAR wszDeploymentId[44]; WCHAR wszProductId[40]; DWORD Index; DWORD Size; DWORD Status; BOOL bUser;
*DisplayName = 0; *SupportUrl = 0;
for ( int i = 0; i < 2; i++ ) { Status = ERROR_SUCCESS; bUser = (0 == i);
if ( bUser ) Status = RegOpenCurrentUser( KEY_READ, &hkRoot ); else hkRoot = HKEY_LOCAL_MACHINE; if ( Status != ERROR_SUCCESS ) break;
hkAppmgmt = 0; Status = RegOpenKeyEx( hkRoot, APPMGMTKEY, 0, KEY_READ, &hkAppmgmt ); if ( bUser ) RegCloseKey( hkRoot );
if ( ERROR_SUCCESS == Status ) { DWORD InstallUI;
Size = sizeof(InstallUI);
// This is the hint that we will use to determine if this product is managed.
Status = RegQueryValueEx( hkAppmgmt, ProductCode, NULL, NULL, (LPBYTE) &InstallUI, &Size ); }
if ( Status != ERROR_SUCCESS ) { if ( hkAppmgmt ) RegCloseKey( hkAppmgmt ); continue; }
for ( Index = 0 ;; Index++ ) { Status = RegEnumKey( hkAppmgmt, Index, wszDeploymentId, sizeof(wszDeploymentId) / sizeof(WCHAR) ); if ( ERROR_SUCCESS == Status ) { Status = RegOpenKeyEx( hkAppmgmt, wszDeploymentId, 0, KEY_READ, &hkApp ); }
if ( Status != ERROR_SUCCESS ) break; Size = sizeof(wszProductId); wszProductId[0] = 0; (void) RegQueryValueEx( hkApp, PRODUCTIDVALUE, NULL, NULL, (LPBYTE) wszProductId, &Size ); if ( lstrcmpi( ProductCode, wszProductId ) != 0 ) { RegCloseKey( hkApp ); continue; } (void) ReadStringValue( hkApp, DEPLOYMENTNAMEVALUE, DisplayName ); (void) ReadStringValue( hkApp, SUPPORTURL, SupportUrl );
RegCloseKey( hkApp ); break; } RegCloseKey( hkAppmgmt );
if ( *DisplayName || *SupportUrl ) break; } }
DWORD WINAPI GetManagedApplications( IN GUID* pCategory, IN DWORD dwQueryFlags, IN DWORD dwInfoLevel, OUT LPDWORD pdwApps, OUT PMANAGEDAPPLICATION* prgManagedApps) { LONG Status; MANAGED_APPLIST AppList;
//
// Initialize the out parameters
//
if (pdwApps) { *pdwApps = NULL; }
if (prgManagedApps) { *prgManagedApps = NULL; }
//
// Validate caller parameters that aren't passed to the
// rpc interface -- other parameters will be validated
// by the server
//
if (!pdwApps || !prgManagedApps) { return ERROR_INVALID_PARAMETER; }
Status = Bind();
if ( Status != ERROR_SUCCESS ) return Status;
//
// Initialize our stack variables
//
memset(&AppList, 0, sizeof(AppList));
//
// Call the method on the server.
//
Status = GetManagedApps( ghRpc, pCategory, dwQueryFlags, dwInfoLevel, &AppList);
//
// On success, set the caller's out parameters to refer
// to the results returned by the server
//
if ( ERROR_SUCCESS == Status) { *pdwApps = AppList.Applications; *prgManagedApps = (PMANAGEDAPPLICATION) AppList.rgApps; }
return Status; }
static DWORD ReportInstallStatus( PINSTALLCONTEXT pInstallContext, DWORD InstallStatus, BOOL bUninstall, WCHAR * pwszDeploymentName, WCHAR * pwszGPOName, WCHAR * pwszDeploymentId ) { DWORD Status; DWORD dwEventId;
Status = ERROR_SUCCESS;
//
// First, report the correct event based on whether
// this is an install or an uninstall
//
if ( ! bUninstall ) { gpEvents->Install( InstallStatus, pwszDeploymentName, pwszGPOName );
( ERROR_SUCCESS == InstallStatus ) ? ( dwEventId = EVENT_APPMGMT_INSTALL ) : ( dwEventId = EVENT_APPMGMT_INSTALL_FAILED ); } else { gpEvents->Uninstall( InstallStatus, pwszDeploymentName, pwszGPOName );
( ERROR_SUCCESS == InstallStatus ) ? ( dwEventId = EVENT_APPMGMT_UNINSTALL ) : ( dwEventId = EVENT_APPMGMT_UNINSTALL_FAILED ); }
//
// If there was an error, log a failure status
//
if ( ERROR_SUCCESS != InstallStatus ) { Status = RsopReportInstallFailure( pInstallContext, pwszDeploymentId, dwEventId); }
return Status; }
DWORD WINAPI GetManagedApplicationCategories( DWORD dwReserved, APPCATEGORYINFOLIST* pAppCategory ) { DWORD Status; APPCATEGORYLIST CategoryList; if ( ( 0 != dwReserved ) || ! pAppCategory ) { return ERROR_INVALID_PARAMETER; }
memset( &CategoryList, 0, sizeof( CategoryList ) );
Status = Bind();
if ( Status != ERROR_SUCCESS ) return Status;
Status = GetManagedAppCategories( ghRpc, &CategoryList);
*pAppCategory = *( ( APPCATEGORYINFOLIST* ) &CategoryList );
return Status; }
|