mirror of https://github.com/tongzx/nt5src
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.
424 lines
14 KiB
424 lines
14 KiB
//+--------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1994 - 1998.
|
|
//
|
|
// File: addupgrd.cpp
|
|
//
|
|
// Contents: add upgrade dialog
|
|
//
|
|
// Classes: CAddUpgrade
|
|
//
|
|
// History: 03-14-1998 stevebl Commented
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
#include "precomp.hxx"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CAddUpgrade dialog
|
|
|
|
|
|
CAddUpgrade::CAddUpgrade(CWnd* pParent /*=NULL*/)
|
|
: CDialog(CAddUpgrade::IDD, pParent)
|
|
{
|
|
//{{AFX_DATA_INIT(CAddUpgrade)
|
|
m_iUpgradeType = 1; // default to rip-and-replace
|
|
m_iSource = 0; // default to current container
|
|
m_szGPOName = L"";
|
|
//}}AFX_DATA_INIT
|
|
m_fPopulated = FALSE;
|
|
}
|
|
|
|
|
|
void CAddUpgrade::DoDataExchange(CDataExchange* pDX)
|
|
{
|
|
CDialog::DoDataExchange(pDX);
|
|
//{{AFX_DATA_MAP(CAddUpgrade)
|
|
DDX_Radio(pDX, IDC_RADIO4, m_iUpgradeType);
|
|
DDX_Radio(pDX, IDC_RADIO1, m_iSource);
|
|
DDX_Text(pDX, IDC_EDIT1, m_szGPOName);
|
|
//}}AFX_DATA_MAP
|
|
}
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(CAddUpgrade, CDialog)
|
|
//{{AFX_MSG_MAP(CAddUpgrade)
|
|
ON_BN_CLICKED(IDC_RADIO1, OnCurrentContainer)
|
|
ON_BN_CLICKED(IDC_RADIO2, OnOtherContainer)
|
|
ON_BN_CLICKED(IDC_RADIO10, OnAllContainers)
|
|
ON_BN_CLICKED(IDC_BUTTON1, OnBrowse)
|
|
ON_LBN_DBLCLK(IDC_LIST1, OnOK)
|
|
ON_WM_CONTEXTMENU()
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CAddUpgrade message handlers
|
|
|
|
BOOL CAddUpgrade::OnInitDialog()
|
|
{
|
|
// If m_fPopulated is FALSE then populate the map with all packages in
|
|
// this GPO container _EXCEPT_ the current app.
|
|
if (!m_fPopulated)
|
|
{
|
|
OnCurrentContainer();
|
|
m_szGPO = m_pScope->m_szGPO;
|
|
m_fPopulated = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// This will be done in OnCurrentContainer if m_fPopulated is FALSE
|
|
RefreshList();
|
|
}
|
|
|
|
CDialog::OnInitDialog();
|
|
|
|
return TRUE; // return TRUE unless you set the focus to a control
|
|
// EXCEPTION: OCX Property Pages should return FALSE
|
|
}
|
|
|
|
void CAddUpgrade::RefreshList()
|
|
{
|
|
// For every element in the map, if it isn't already in the upgrade
|
|
// list then add it to the list.
|
|
|
|
CListBox * pList = (CListBox *)GetDlgItem(IDC_LIST1);
|
|
pList->ResetContent();
|
|
|
|
BOOL fEnable = FALSE;
|
|
|
|
// add all elements that aren't already in the upgrade list
|
|
map<CString, CUpgradeData>::iterator i;
|
|
for (i = m_NameIndex.begin(); i != m_NameIndex.end(); i++)
|
|
{
|
|
if (m_pUpgradeList->end() == m_pUpgradeList->find(GetUpgradeIndex(i->second.m_PackageGuid)))
|
|
{
|
|
fEnable = TRUE;
|
|
pList->AddString(i->first);
|
|
CDC * pDC = pList->GetDC();
|
|
CSize size = pDC->GetTextExtent(i->first);
|
|
pDC->LPtoDP(&size);
|
|
pList->ReleaseDC(pDC);
|
|
if (pList->GetHorizontalExtent() < size.cx)
|
|
{
|
|
pList->SetHorizontalExtent(size.cx);
|
|
}
|
|
}
|
|
}
|
|
GetDlgItem(IDOK)->EnableWindow(fEnable);
|
|
if (NULL == GetFocus())
|
|
{
|
|
GetDlgItem(IDCANCEL)->SetFocus();
|
|
}
|
|
pList->SetCurSel(0);
|
|
}
|
|
|
|
void CAddUpgrade::OnOK()
|
|
{
|
|
CListBox * pList = (CListBox *)GetDlgItem(IDC_LIST1);
|
|
int iSel = pList->GetCurSel();
|
|
if (iSel != LB_ERR)
|
|
{
|
|
// only allow the dialog to close with IDOK if a selection has been made
|
|
CDialog::OnOK();
|
|
|
|
// Do this part later to make sure that all data members are
|
|
// refreshed (this happens as part of the OnOk processing)
|
|
pList->GetText(iSel, m_szPackageName);
|
|
m_UpgradeData = m_NameIndex[m_szPackageName];
|
|
m_UpgradeData.m_flags = (m_iUpgradeType == 1) ? UPGFLG_Uninstall : UPGFLG_NoUninstall;
|
|
}
|
|
}
|
|
|
|
void CAddUpgrade::OnCurrentContainer()
|
|
{
|
|
// Populate the map with all packages in this GPO container _EXCEPT_ the
|
|
// current app.
|
|
CString szClassStore;
|
|
HRESULT hr = m_pScope->GetClassStoreName(szClassStore, FALSE);
|
|
ASSERT(hr == S_OK);
|
|
m_NameIndex.erase(m_NameIndex.begin(), m_NameIndex.end());
|
|
map <MMC_COOKIE, CAppData>::iterator i;
|
|
for (i = m_pScope->m_AppData.begin(); i != m_pScope->m_AppData.end(); i ++)
|
|
{
|
|
CString szIndex = GetUpgradeIndex(i->second.m_pDetails->pInstallInfo->PackageGuid);
|
|
if (0 != _wcsicmp(szIndex, m_szMyGuid))
|
|
{
|
|
// make sure we exclude legacy apps
|
|
if (i->second.m_pDetails->pInstallInfo->PathType != SetupNamePath)
|
|
{
|
|
CUpgradeData data;
|
|
memcpy(&data.m_PackageGuid, &i->second.m_pDetails->pInstallInfo->PackageGuid, sizeof(GUID));
|
|
data.m_szClassStore = szClassStore;
|
|
// Add this element to the list
|
|
m_NameIndex[i->second.m_pDetails->pszPackageName] = data;
|
|
}
|
|
}
|
|
}
|
|
|
|
RefreshList();
|
|
}
|
|
|
|
void CAddUpgrade::OnOtherContainer()
|
|
{
|
|
// Populate the map with all packages in the other container.
|
|
|
|
m_NameIndex.erase(m_NameIndex.begin(), m_NameIndex.end());
|
|
WCHAR szBuffer[MAX_DS_PATH];
|
|
LPGROUPPOLICYOBJECT pGPO = NULL;
|
|
HRESULT hr = CoCreateInstance(CLSID_GroupPolicyObject, NULL,
|
|
CLSCTX_SERVER, IID_IGroupPolicyObject,
|
|
(void **)&pGPO);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// open GPO object without opening registry data
|
|
hr = pGPO->OpenDSGPO((LPOLESTR)((LPCOLESTR)m_szGPO), GPO_OPEN_READ_ONLY);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pGPO->GetDSPath(m_pScope->m_fMachine ? GPO_SECTION_MACHINE : GPO_SECTION_USER, szBuffer, sizeof(szBuffer) / sizeof(szBuffer[0]));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// OK, we should now have a DS path that we can use to locate
|
|
// a class store.
|
|
LPOLESTR szCSPath;
|
|
hr = CsGetClassStorePath((LPOLESTR)((LPCOLESTR)szBuffer), &szCSPath);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// now we should have the DS path to the class store itself
|
|
IClassAdmin * pIClassAdmin;
|
|
hr = CsGetClassStore((LPOLESTR)((LPCOLESTR)szCSPath), (LPVOID*)&pIClassAdmin);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// and finally we should have a pointer to the IClassAdmin
|
|
IEnumPackage * pIPE = NULL;
|
|
|
|
HRESULT hr = pIClassAdmin->EnumPackages(NULL,
|
|
NULL,
|
|
APPQUERY_ADMINISTRATIVE,
|
|
NULL,
|
|
NULL,
|
|
&pIPE);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pIPE->Reset();
|
|
PACKAGEDISPINFO stPDI;
|
|
ULONG nceltFetched;
|
|
while (SUCCEEDED(hr))
|
|
{
|
|
hr = pIPE->Next(1, &stPDI, &nceltFetched);
|
|
if (nceltFetched)
|
|
{
|
|
// make sure we exclude legacy apps
|
|
// and deleted apps
|
|
if (stPDI.PathType != SetupNamePath)
|
|
{
|
|
CString szIndex = GetUpgradeIndex(stPDI.PackageGuid);
|
|
if (0 != _wcsicmp(szIndex, m_szMyGuid))
|
|
{
|
|
// Add this element to the list
|
|
CString sz = stPDI.pszPackageName;
|
|
if (0 != _wcsicmp(m_szGPO, m_pScope->m_szGPO))
|
|
{
|
|
// This isn't in the host GPO
|
|
sz += L" (";
|
|
sz += m_szGPOName;
|
|
sz += L")";
|
|
}
|
|
CUpgradeData data;
|
|
data.m_szClassStore = szCSPath;
|
|
memcpy(&data.m_PackageGuid, &stPDI.PackageGuid, sizeof(GUID));
|
|
m_NameIndex[sz] = data;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
OLESAFE_DELETE(stPDI.pszPackageName);
|
|
OLESAFE_DELETE(stPDI.pszScriptPath);
|
|
OLESAFE_DELETE(stPDI.pszPublisher);
|
|
OLESAFE_DELETE(stPDI.pszUrl);
|
|
UINT n = stPDI.cUpgrades;
|
|
while (n--)
|
|
{
|
|
OLESAFE_DELETE(stPDI.prgUpgradeInfoList[n].szClassStore);
|
|
}
|
|
OLESAFE_DELETE(stPDI.prgUpgradeInfoList);
|
|
}
|
|
pIPE->Release();
|
|
}
|
|
|
|
pIClassAdmin->Release();
|
|
}
|
|
OLESAFE_DELETE(szCSPath);
|
|
}
|
|
}
|
|
}
|
|
pGPO->Release();
|
|
}
|
|
|
|
RefreshList();
|
|
}
|
|
|
|
void CAddUpgrade::OnAllContainers()
|
|
{
|
|
RefreshList();
|
|
}
|
|
|
|
//+--------------------------------------------------------------------------
|
|
//
|
|
// Function: GetDomainFromLDAPPath
|
|
//
|
|
// Synopsis: returns a freshly allocated string containing the LDAP path
|
|
// to the domain name contained with an arbitrary LDAP path.
|
|
//
|
|
// Arguments: [szIn] - LDAP path to the initial object
|
|
//
|
|
// Returns: NULL - if no domain could be found or if OOM
|
|
//
|
|
// History: 5-06-1998 stevebl Created
|
|
// 10-20-1998 stevebl modified to preserve server names
|
|
//
|
|
// Notes: This routine works by repeatedly removing leaf elements from
|
|
// the LDAP path until an element with the "DC=" prefix is
|
|
// found, indicating that a domain name has been located. If a
|
|
// path is given that is not rooted in a domain (is that even
|
|
// possible?) then NULL would be returned.
|
|
//
|
|
// The caller must free this path using the standard c++ delete
|
|
// operation. (I/E this isn't an exportable function.)
|
|
//
|
|
// Stolen from GPEDIT\UTIL.CPP
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
LPOLESTR GetDomainFromLDAPPath(LPOLESTR szIn)
|
|
{
|
|
LPOLESTR sz = NULL;
|
|
IADsPathname * pADsPathname = NULL;
|
|
HRESULT hr = CoCreateInstance(CLSID_Pathname,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_IADsPathname,
|
|
(LPVOID*)&pADsPathname);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pADsPathname->Set(szIn, ADS_SETTYPE_FULL);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
BSTR bstr;
|
|
BOOL fStop = FALSE;
|
|
|
|
while (!fStop)
|
|
{
|
|
hr = pADsPathname->Retrieve(ADS_FORMAT_LEAF, &bstr);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
|
|
// keep peeling them off until we find something
|
|
// that is a domain name
|
|
fStop = (0 == _wcsnicmp(L"DC=", bstr, 3));
|
|
SysFreeString(bstr);
|
|
}
|
|
else
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("GetDomainFromLDAPPath: Failed to retrieve leaf with 0x%x."), hr));
|
|
}
|
|
|
|
if (!fStop)
|
|
{
|
|
hr = pADsPathname->RemoveLeafElement();
|
|
if (FAILED(hr))
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("GetDomainFromLDAPPath: Failed to remove leaf with 0x%x."), hr));
|
|
fStop = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
hr = pADsPathname->Retrieve(ADS_FORMAT_X500, &bstr);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
sz = new OLECHAR[wcslen(bstr)+1];
|
|
if (sz)
|
|
{
|
|
wcscpy(sz, bstr);
|
|
}
|
|
SysFreeString(bstr);
|
|
}
|
|
else
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("GetDomainFromLDAPPath: Failed to retrieve full path with 0x%x."), hr));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("GetDomainFromLDAPPath: Failed to set pathname with 0x%x."), hr));
|
|
}
|
|
|
|
pADsPathname->Release();
|
|
}
|
|
else
|
|
{
|
|
DebugMsg((DM_WARNING, TEXT("GetDomainFromLDAPPath: Failed to CoCreateInstance for IID_IADsPathname with 0x%x."), hr));
|
|
}
|
|
|
|
|
|
return sz;
|
|
}
|
|
|
|
|
|
void CAddUpgrade::OnBrowse()
|
|
{
|
|
// Browse to the other container and then call OnOtherContainer.
|
|
OLECHAR szPath[MAX_DS_PATH];
|
|
OLECHAR szName[256];
|
|
GPOBROWSEINFO stGBI;
|
|
memset(&stGBI, 0, sizeof(GPOBROWSEINFO));
|
|
stGBI.dwSize = sizeof(GPOBROWSEINFO);
|
|
stGBI.dwFlags = GPO_BROWSE_NOCOMPUTERS | GPO_BROWSE_INITTOALL;
|
|
stGBI.hwndOwner = m_hWnd;
|
|
stGBI.lpInitialOU = GetDomainFromLDAPPath((LPWSTR)((LPCWSTR)m_szGPO));
|
|
stGBI.lpDSPath = szPath;
|
|
stGBI.dwDSPathSize = MAX_DS_PATH;
|
|
stGBI.lpName = szName;
|
|
stGBI.dwNameSize = 256;
|
|
if (SUCCEEDED(BrowseForGPO(&stGBI)))
|
|
{
|
|
m_szGPO = szPath;
|
|
m_szGPOName = szName;
|
|
m_iSource = 1;
|
|
UpdateData(FALSE);
|
|
OnOtherContainer();
|
|
}
|
|
if (stGBI.lpInitialOU != NULL)
|
|
{
|
|
delete [] stGBI.lpInitialOU;
|
|
}
|
|
}
|
|
|
|
LRESULT CAddUpgrade::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (message)
|
|
{
|
|
case WM_HELP:
|
|
StandardHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, IDD);
|
|
return 0;
|
|
default:
|
|
return CDialog::WindowProc(message, wParam, lParam);
|
|
}
|
|
}
|
|
|
|
void CAddUpgrade::OnContextMenu(CWnd* pWnd, CPoint point)
|
|
{
|
|
StandardContextMenu(pWnd->m_hWnd, IDD_FIND_UPGRADE);
|
|
}
|