Leaked source code of windows server 2003
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.
 
 
 
 
 
 

4435 lines
138 KiB

//+--------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1994 - 1998.
//
// File: browser.cpp
//
// Contents: implementation of the general GPO browser pane
//
// Classes: CBrowserPP
//
// Functions:
//
// History: 04-30-1998 stevebl Created
//
// Notes: This is the pane that behaves much like the standard file
// open dialog. The class is used for all panes that have this
// format since they share so much functionality. The
// dwPageType parameter passed to CBrowserPP::Initialize is
// used to distinguish between the different flavors.
//
//---------------------------------------------------------------------------
#include "main.h"
#include "browser.h"
#include "commctrl.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//
// Help ids
//
DWORD aBrowserDomainHelpIds[] =
{
IDC_COMBO1, IDH_BROWSER_LOOKIN,
IDC_LIST1, IDH_BROWSER_DOMAINGPO,
IDC_DESCRIPTION, IDH_NOCONTEXTHELP,
0, 0
};
DWORD aBrowserSiteHelpIds[] =
{
IDC_COMBO1, IDH_BROWSER_SITELIST,
IDC_LIST1, IDH_BROWSER_GPOLIST,
IDC_DESCRIPTION, IDH_NOCONTEXTHELP,
0, 0
};
DWORD aBrowserAllHelpIds[] =
{
IDC_COMBO1, IDH_BROWSER_DOMAINLIST,
IDC_LIST1, IDH_BROWSER_FULLGPOLIST,
IDC_DESCRIPTION, IDH_NOCONTEXTHELP,
0, 0
};
CBrowserPP::CBrowserPP()
{
m_ppActive = NULL;
m_pGBI = NULL;
m_pPrevSel = NULL;
m_szServerName = NULL;
m_szDomainName = NULL;
}
//+--------------------------------------------------------------------------
//
// Function: CopyAsFriendlyName
//
// Synopsis: Copies a LDAP path converting it to a friendly name by
// removing the "LDAP://" and "XX=" and converting "," to "."
// and removing a server name (if any)
//
// Arguments: [lpDest] - destination buffer
// [lpSrc] - source buffer
//
// Returns: nothing
//
// History: 5-07-1998 stevebl Created
//
// Notes: The destination buffer should be as large as the source
// buffer to ensure safe completion. lpDest and lpSrc may both
// point to the same buffer.
//
// As an example, this routine would convert the following path:
// LDAP://DC=abcd,DC=efg
// into this:
// abcd.efg
//
//---------------------------------------------------------------------------
void CopyAsFriendlyName(WCHAR * lpDest, WCHAR * lpSrc)
{
LPOLESTR lpProvider = L"LDAP://";
DWORD dwStrLen = wcslen(lpProvider);
// lpStopChecking marks the last spot where we can safely
// look ahead 2 spaces for an '=' character. Anything past
// this and we are looking in memory we don't own.
OLECHAR * lpStopChecking = (wcslen(lpSrc) - 2) + lpSrc;
//
// Skip the LDAP:// if found
//
if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE | NORM_STOP_ON_NULL,
lpProvider, dwStrLen, lpSrc, dwStrLen) == CSTR_EQUAL)
{
lpSrc += dwStrLen;
}
//
// Remove server name (if any)
//
if (lpSrc < lpStopChecking)
{
if (*(lpSrc+2) != L'=')
{
// look for a '/' character marking the end of a server name
while (*lpSrc)
{
if (*lpSrc == L'/')
{
lpSrc++;
break;
}
lpSrc++;
}
}
}
//
// Parse through the name replacing all the XX= with .
//
while (*lpSrc)
{
if (lpSrc < lpStopChecking)
{
if (*(lpSrc+2) == L'=')
{
lpSrc += 3;
}
}
while (*lpSrc && (*lpSrc != L','))
{
// remove escape sequences
if (*lpSrc == L'\\')
{
lpSrc++;
// special cases
// make sure that '\\x' becomes '\x'
if (*lpSrc == L'\\')
{
*lpDest++ = *lpSrc++;
}
// make sure that '\0D' becomes '\r'
else if (*lpSrc == L'0' && *(lpSrc+1) == L'D')
{
*lpDest++ = L'\r';
lpSrc += 2;
}
// make sure that '\0A' becomes '\n'
else if (*lpSrc == L'0' && *(lpSrc+1) == L'A')
{
*lpDest++ = L'\n';
lpSrc += 2;
}
}
else
{
*lpDest++ = *lpSrc++;
}
}
if (*lpSrc == L',')
{
*lpDest++ = L'.';
lpSrc++;
}
}
*lpDest = L'\0';
}
//+--------------------------------------------------------------------------
//
// Member: CBrowserPP::Initialize
//
// Synopsis: Initializes the property page.
//
// Arguments: [dwPageType] - used to identify which page this is. (See
// notes.)
// [pGBI] - pointer to the browse info structure passed
// by caller
// [ppActive] - pointer to a common variable that remembers
// which object was last given the focus.
// Needed because only the page with the focus
// is allowed to return data to the caller when
// the property sheet is dismissed.
//
// Returns: Handle to the newly created property page.
//
// Modifies:
//
// Derivation:
//
// History: 04-30-1998 stevebl Created
//
// Notes: This class implements the following property pages:
// PAGETYPE_DOMAINS - GPO's linked to domains
// PAGETYPE_SITES - GPO's linked to sites
// PAGETYPE_ALL - All GPO's in a selected
//
// PAGETYPE_COMPUTERS is implemented by CCompsPP since it
// behaves so differently.
//
//---------------------------------------------------------------------------
HPROPSHEETPAGE CBrowserPP::Initialize(DWORD dwPageType, LPGPOBROWSEINFO pGBI, void * * ppActive)
{
m_ppActive = ppActive;
m_dwPageType = dwPageType;
m_pGBI = pGBI;
if (m_pGBI->lpInitialOU)
{
//
// Get the server name
//
m_szServerName = ExtractServerName(m_pGBI->lpInitialOU);
DebugMsg((DM_VERBOSE, TEXT("CBrowserPP::Initialize extracted server name: %s"), m_szServerName));
//
// Get the friendly domain name
//
LPOLESTR pszDomain = GetDomainFromLDAPPath(m_pGBI->lpInitialOU);
//
// Convert LDAP to dot (DN) style
//
if (pszDomain)
{
ConvertToDotStyle (pszDomain, &m_szDomainName);
DebugMsg((DM_VERBOSE, TEXT("CBrowserPP::Initialize extracted domain name: %s"), m_szDomainName));
delete [] pszDomain;
}
}
DWORD dwTitle;
switch (dwPageType)
{
case PAGETYPE_DOMAINS:
dwTitle = IDS_DOMAINS;
break;
case PAGETYPE_SITES:
dwTitle = IDS_SITES;
break;
case PAGETYPE_ALL:
default:
dwTitle = IDS_ALL;
break;
}
LoadString(g_hInstance, dwTitle, m_szTitle, sizeof(m_szTitle) / sizeof(WCHAR));
PROPSHEETPAGE psp;
memset(&psp, 0, sizeof(psp));
psp.dwSize = sizeof(psp);
psp.dwFlags = PSP_USETITLE;
psp.pszTitle = m_szTitle;
psp.hInstance = g_hInstance;
psp.pszTemplate = MAKEINTRESOURCE(IDD_PROPPAGE_GPOBROWSER);
return CreatePropertySheetPage(&psp);
}
CBrowserPP::~CBrowserPP()
{
if (m_szServerName)
{
LocalFree(m_szServerName);
}
if (m_szDomainName)
{
LocalFree(m_szDomainName);
}
}
/////////////////////////////////////////////////////////////////////////////
// CBrowserPP message handlers
INT CBrowserPP::AddElement(MYLISTEL * pel, INT index)
{
LV_ITEM item;
memset(&item, 0, sizeof(item));
item.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
if (-1 == index)
{
index = ListView_GetItemCount(m_hList);
}
item.iItem = index;
item.pszText = pel->szName;
if (pel->nType == ITEMTYPE_FOREST)
{
item.iImage = 10;
}
else if (pel->nType == ITEMTYPE_SITE)
{
item.iImage = 6;
}
else if (pel->nType == ITEMTYPE_DOMAIN)
{
item.iImage = 7;
}
else if (pel->nType == ITEMTYPE_OU)
{
item.iImage = 0;
}
else
{
if (pel->bDisabled)
{
item.iImage = 3;
}
else
{
item.iImage = 2;
}
}
item.lParam = (LPARAM)pel;
index = ListView_InsertItem(m_hList, &item);
if (index != -1 && pel->nType == ITEMTYPE_GPO)
{
// check to see if we need to add the domain name
LPOLESTR szObject = GetCurrentObject();
LPOLESTR szDomain = GetDomainFromLDAPPath(pel->szData);
if (szDomain && szObject)
{
// ignore potential differences in server name when we compare
// the domain paths
LPOLESTR szBuffer1 = NULL;
LPOLESTR szBuffer2 = NULL;
szBuffer1 = new OLECHAR[wcslen(szObject) + 1];
szBuffer2 = new OLECHAR[wcslen(szDomain) + 1];
if (NULL != szBuffer1 && NULL != szBuffer1)
{
CopyAsFriendlyName(szBuffer1, szObject);
CopyAsFriendlyName(szBuffer2, szDomain);
if (0 != wcscmp(szBuffer1, szBuffer2))
{
// Need to add the domain name since the domain is different
// from the focus object.
// Need to convert the domain to a friendly name.
// Let's just do it in place so I don't have to allocate any
// more memory. :)
// We can get away with this because the string can only get smaller.
CopyAsFriendlyName(szDomain, szDomain);
memset(&item, 0, sizeof(item));
item.mask = LVIF_TEXT;
item.iItem = index;
item.iSubItem = 1;
item.pszText = szDomain;
ListView_SetItem(m_hList, &item);
}
}
if (szBuffer1)
{
delete [] szBuffer1;
}
if (szBuffer2)
{
delete [] szBuffer2;
}
}
if (szDomain)
delete [] szDomain;
if (szObject)
delete [] szObject;
}
return (index);
}
#include "ntdsapi.h"
//+--------------------------------------------------------------------------
//
// Member: CBrowserPP::FillSitesList
//
// Synopsis: Fills the combobox with the trusted sites information.
// The szData member of the combobox element structure is the
// containing domain.
//
// Returns: TRUE - successful
// FALSE - error
//
// History: 05-04-1998 stevebl created
// 05-27-1999 stevebl now initializes to site in lpInitialOU
//
//---------------------------------------------------------------------------
BOOL CBrowserPP::FillSitesList ()
{
HCURSOR hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
PDS_NAME_RESULTW pSites;
int iInitialSite = 0;
int iIndex = -1;
HANDLE hDs;
DWORD dw = DsBindW(NULL, NULL, &hDs);
if (ERROR_SUCCESS == dw)
{
dw = DsListSitesW(hDs, &pSites);
if (ERROR_SUCCESS == dw)
{
DWORD n = 0;
for (n = 0; n < pSites->cItems; n++)
{
//
// Add the site name (if it has a name)
//
if (pSites->rItems[n].pName)
{
LPTSTR lpFullPath, lpTempPath;
LOOKDATA * pdata;
pdata = new LOOKDATA;
if (pdata)
{
HRESULT hr;
ULONG ulNoChars;
ulNoChars = wcslen(pSites->rItems[n].pName)+1;
pdata->szName = new WCHAR[ulNoChars];
if (pdata->szName)
{
hr = StringCchCopy(pdata->szName, ulNoChars, pSites->rItems[n].pName);
ASSERT(SUCCEEDED(hr));
}
pdata->szData = NULL;
ulNoChars = lstrlen(pSites->rItems[n].pName) + 10;
lpTempPath = (LPTSTR) LocalAlloc (LPTR, ulNoChars * sizeof(TCHAR));
if (lpTempPath)
{
hr = StringCchCopy (lpTempPath, ulNoChars, TEXT("LDAP://"));
ASSERT(SUCCEEDED(hr));
hr = StringCchCat (lpTempPath, ulNoChars, pSites->rItems[n].pName);
ASSERT(SUCCEEDED(hr));
lpFullPath = GetFullPath (lpTempPath, m_hwndDlg);
if (lpFullPath)
{
ulNoChars = wcslen(lpFullPath)+1;
pdata->szData = new WCHAR[ulNoChars];
if (pdata->szData)
{
hr = StringCchCopy(pdata->szData, ulNoChars, lpFullPath);
ASSERT(SUCCEEDED(hr));
}
LocalFree (lpFullPath);
}
LocalFree (lpTempPath);
}
if (!pdata->szData)
{
if (pdata->szName)
{
delete [] pdata->szName;
}
delete pdata;
continue;
}
// try and use a friendlier name for the site
{
IADs * pADs = NULL;
// Get the friendly display name
hr = OpenDSObject(pdata->szData, IID_IADs,
(void **)&pADs);
if (SUCCEEDED(hr))
{
VARIANT varName;
BSTR bstrNameProp;
VariantInit(&varName);
bstrNameProp = SysAllocString(SITE_NAME_PROPERTY);
if (bstrNameProp)
{
hr = pADs->Get(bstrNameProp, &varName);
if (SUCCEEDED(hr))
{
ulNoChars = wcslen(varName.bstrVal) + 1;
LPOLESTR sz = new OLECHAR[ulNoChars];
if (sz)
{
hr = StringCchCopy(sz, ulNoChars, varName.bstrVal);
ASSERT(SUCCEEDED(hr));
if (pdata->szName)
delete [] pdata->szName;
pdata->szName = sz;
}
}
SysFreeString(bstrNameProp);
}
VariantClear(&varName);
pADs->Release();
}
}
pdata->nIndent = 0;
pdata->nType = ITEMTYPE_SITE;
iIndex = (int)SendMessage(m_hCombo, CB_INSERTSTRING, (WPARAM) -1, (LPARAM) (LPCTSTR) pdata);
if (CB_ERR == iIndex)
{
DebugMsg((DM_WARNING, TEXT("CBrowserPP::AddSitesList: Failed to alloc memory with %d"), GetLastError()));
}
if (NULL != pdata->szData && NULL != m_pGBI->lpInitialOU)
{
if (0 == wcscmp(pdata->szData, m_pGBI->lpInitialOU))
{
iInitialSite = iIndex;
}
}
}
}
}
DsFreeNameResultW(pSites);
}
DsUnBindW(&hDs);
}
else
{
DebugMsg((DM_WARNING, TEXT("CBrowserPP::AddSitesList: DsBindW failed with 0x%x"), dw));
ReportError(m_hwndDlg, dw, IDS_DSBINDFAILED);
}
if (iIndex >= 0)
{
SendMessage (m_hCombo, CB_SETCURSEL, iInitialSite, 0);
}
SetCursor(hcur);
return TRUE;
}
PDS_DOMAIN_TRUSTS Domains;
int __cdecl CompareDomainInfo(const void * arg1, const void * arg2)
{
WCHAR * sz1, *sz2;
sz1 = Domains[*(ULONG *)arg1].DnsDomainName;
sz2 = Domains[*(ULONG *)arg2].DnsDomainName;
if (!sz1)
{
sz1 = Domains[*(ULONG *)arg1].NetbiosDomainName;
}
if (!sz2)
{
sz2 = Domains[*(ULONG *)arg2].NetbiosDomainName;
}
return _wcsicmp(sz1,sz2);
}
typedef struct tag_WORKING_LIST_EL
{
ULONG index;
struct tag_WORKING_LIST_EL * pNext;
} WORKING_LIST_EL;
//+--------------------------------------------------------------------------
//
// Function: BuildDomainList
//
// Synopsis: Builds a tree containing all domains that have a trust
// relationship with the server.
//
// Siblings within the tree are alphabetized.
//
// Arguments: [szServerName] - (NULL for local)
//
// Returns: pointer to the root node of the tree (NULL on error)
//
// History: 10-16-1998 stevebl Created
//
// Notes: Tree nodes must be freed by the caller (using delete).
//
//---------------------------------------------------------------------------
LOOKDATA * BuildDomainList(WCHAR * szServerName)
{
ULONG DomainCount;
OLECHAR szBuffer[128];
HRESULT hr;
ULONG ulNoChars;
#if FGPO_SUPPORT
LOOKDATA * pDomainList = new LOOKDATA;
if (!pDomainList)
{
// failed to even create the Forest node!
return NULL;
}
pDomainList->szData = GetPathToForest(szServerName);
if (!pDomainList->szData)
{
delete pDomainList;
return NULL;
}
// load the name for the forest from resources
if (0 == LoadStringW(g_hInstance, IDS_FOREST, szBuffer, sizeof(szBuffer) / sizeof(szBuffer[0])))
{
// failed to get the resource name
delete pDomainList;
return NULL;
}
ulNoChars = lstrlen(szBuffer) + 1;
pDomainList->szName = new OLECHAR [ulNoChars];
if (NULL == pDomainList->szName)
{
// not enough memory to create name of the forest node
delete pDomainList;
return NULL;
}
hr = StringCchCopy(pDomainList->szName, ulNoChars, szBuffer);
ASSERT(SUCCEEDED(hr));
pDomainList->nIndent = 0;
pDomainList->nType = ITEMTYPE_FOREST;
pDomainList->pParent = NULL;
pDomainList->pSibling = NULL;
pDomainList->pChild = NULL;
#else
LOOKDATA * pDomainList = NULL;
#endif
long l = DsEnumerateDomainTrusts(szServerName,
DS_DOMAIN_IN_FOREST | DS_DOMAIN_NATIVE_MODE |
DS_DOMAIN_PRIMARY | DS_DOMAIN_TREE_ROOT,
&Domains,
&DomainCount);
//
// Some of the below code might be unnecessary since DsEnumerateTrusts will no
// longer return domains from other forests. Shouldn't do any harm though..
//
if ((0 == l) && (DomainCount > 0))
{
// sort the list of domains alphabetically
ULONG * rgSorted = new ULONG[DomainCount];
if (rgSorted)
{
ULONG uCount = DomainCount;
while (uCount--)
{
rgSorted[uCount] = uCount;
}
qsort(rgSorted, DomainCount, sizeof (ULONG), CompareDomainInfo);
// Build a working list of the domains, sorted alphabetically in
// INVERTED order.
WORKING_LIST_EL * pWorkList = NULL;
LOOKDATA ** rgDataMap = new LOOKDATA * [DomainCount];
if (rgDataMap)
{
uCount = 0;
while (uCount < DomainCount)
{
WORKING_LIST_EL * pNew = new WORKING_LIST_EL;
if (pNew)
{
pNew->index = rgSorted[uCount];
pNew->pNext = pWorkList;
pWorkList = pNew;
}
rgDataMap[uCount] = NULL;
uCount++;
}
// Build the ordered tree of domains by removing domains from the
// working list and inserting them into the new tree until there are
// none left in the working list.
// NOTE - if this routine runs out of memory it will begin
// to drop nodes rather than AV.
WORKING_LIST_EL ** ppWorker;
BOOL fContinue = TRUE;
while (pWorkList && fContinue)
{
fContinue = FALSE;
ppWorker = &pWorkList;
while (*ppWorker)
{
if (NULL == Domains[(*ppWorker)->index].DnsDomainName)
{
//
// For now, if it doesn't have a
// DnsDomainName then we're going to
// skip it.
// Eventually we'll want to make sure it doesn't
// have a DC by calling DsGetDcName with
// DS_DIRECTORY_SERVICE_PREFERRED.
// remove it from the worker list
WORKING_LIST_EL * pNext = (*ppWorker)->pNext;
delete *ppWorker;
*ppWorker = pNext;
}
else
{
// Does this node have a parent?
ULONG flags = Domains[(*ppWorker)->index].Flags;
if ((0 != (flags & DS_DOMAIN_IN_FOREST)) && (0 == (flags & DS_DOMAIN_TREE_ROOT)))
{
// it has a parent has its parent been added?
LOOKDATA * pParent = rgDataMap[Domains[(*ppWorker)->index].ParentIndex];
if (pParent != NULL)
{
// its parent has been added
// insert this one in its parent's child list
LOOKDATA * pData = new LOOKDATA;
if (pData)
{
WCHAR * szName = Domains[(*ppWorker)->index].DnsDomainName;
if (!szName)
{
szName = Domains[(*ppWorker)->index].NetbiosDomainName;
}
ulNoChars = wcslen(szName) + 1;
pData->szName = new WCHAR[ulNoChars];
if (pData->szName)
{
int cch = 0;
int count=0;
// count the dots in szName;
while (szName[count])
{
if (L'.' == szName[count])
{
cch++;
}
count++;
}
cch *= 3; // multiply the number of dots by 3;
cch += 11; // add 10 + 1 (for the null)
cch += count; // add the string size;
pData->szData = new WCHAR[cch];
if (pData->szData)
{
NameToPath(pData->szData, szName, cch);
hr = StringCchCopy(pData->szName, ulNoChars, szName);
ASSERT(SUCCEEDED(hr));
pData->nIndent = pParent->nIndent+1;
pData->nType = ITEMTYPE_DOMAIN;
pData->pParent = pParent;
pData->pSibling = pParent->pChild;
pData->pChild = NULL;
pParent->pChild = pData;
rgDataMap[(*ppWorker)->index] = pData;
// make sure we remember
// that we added something
// to the master list (helps
// us avoid infinite loops
// in case of an error)
fContinue = TRUE;
}
else
{
delete [] pData->szName;
delete pData;
}
}
else
{
delete pData;
}
}
// and remove it from the worker list
WORKING_LIST_EL * pNext = (*ppWorker)->pNext;
delete *ppWorker;
*ppWorker = pNext;
}
else
{
// skip it for now
ppWorker = &((*ppWorker)->pNext);
}
}
else
{
// it doesn't have a parent add it just under the forest
// level of the list
LOOKDATA * pData = new LOOKDATA;
if (pData)
{
WCHAR * szName = Domains[(*ppWorker)->index].DnsDomainName;
if (!szName)
{
szName = Domains[(*ppWorker)->index].NetbiosDomainName;
}
ulNoChars = wcslen(szName) + 1;
pData->szName = new WCHAR[ulNoChars];
if (pData->szName)
{
int cch = 0;
int count=0;
// count the dots in szName;
while (szName[count])
{
if (L'.' == szName[count])
{
cch++;
}
count++;
}
cch *= 3; // multiply the number of dots by 3;
cch += 11; // add 10 + 1 for the null
cch += count; // add the string size;
pData->szData = new WCHAR[cch];
if (pData->szData)
{
NameToPath(pData->szData, szName, cch);
hr = StringCchCopy(pData->szName, ulNoChars, szName);
ASSERT(SUCCEEDED(hr));
#if FGPO_SUPPORT
pData->nIndent = 1;
pData->nType = ITEMTYPE_DOMAIN;
pData->pParent = pDomainList;
pData->pSibling = pDomainList->pChild;
pData->pChild = NULL;
pDomainList->pChild = pData;
#else
pData->nIndent = 0;
pData->nType = ITEMTYPE_DOMAIN;
pData->pParent = NULL;
pData->pSibling = pDomainList;
pData->pChild = NULL;
pDomainList = pData;
#endif
rgDataMap[(*ppWorker)->index] = pData;
// make sure we remember
// that we added something
// to the master list (helps
// us avoid infinite loops
// in case of an error)
fContinue = TRUE;
}
else
{
delete [] pData->szName;
delete pData;
}
}
else
{
delete pData;
}
}
// and remove it from the worker list
WORKING_LIST_EL * pNext = (*ppWorker)->pNext;
delete *ppWorker;
*ppWorker = pNext;
}
}
}
}
delete [] rgDataMap;
}
delete [] rgSorted;
}
NetApiBufferFree(Domains);
}
else
{
if (0 != l)
{
DebugMsg((DM_WARNING, TEXT("DsEnumerateDomainTrustsW failed with %u"), l));
}
}
return pDomainList;
}
VOID FreeDomainInfo (LOOKDATA * pEntry)
{
if (!pEntry)
{
return;
}
if (pEntry->pChild)
{
FreeDomainInfo (pEntry->pChild);
}
if (pEntry->pSibling)
{
FreeDomainInfo (pEntry->pSibling);
}
delete [] pEntry->szName;
delete pEntry;
}
//+--------------------------------------------------------------------------
//
// Member: CBrowserPP::FillDomainList
//
// Synopsis: Fills the combobox with the trusted domain information.
// The szData member of the combobox element structure is the
// LDAP domain name.
//
// Returns: TRUE - successful
// FALSE - error
//
// History: 04-30-1998 stevebl Modified from original version
// written by EricFlo
// 10-20-1998 stevebl Heavily modified to support domains
// "outside the forest" and to fix a
// whole passle o' bugs.
//
// Note: This routine also sets the focus to the domain of the object
// passed in via the lpInitialOU member of the GPOBROWSEINFO
// structure.
//
//---------------------------------------------------------------------------
BOOL CBrowserPP::FillDomainList ()
{
BOOL bResult = TRUE;
HRESULT hr;
DWORD dwIndex;
BOOL fEnableBackbutton = FALSE;
HCURSOR hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
WCHAR * szBuffer1 = NULL;
if (m_pGBI->lpInitialOU)
{
if (IsForest(m_pGBI->lpInitialOU))
{
szBuffer1 = new TCHAR[128];
LoadStringW(g_hInstance, IDS_FOREST, szBuffer1, 128);
}
else
{
WCHAR * sz = GetDomainFromLDAPPath(m_pGBI->lpInitialOU);
if (sz)
{
szBuffer1 = new WCHAR[wcslen(sz) + 1];
if (szBuffer1)
{
CopyAsFriendlyName(szBuffer1, sz);
}
delete [] sz;
}
}
}
LOOKDATA * pDomainList = BuildDomainList(m_szServerName);
if (!pDomainList)
{
ReportError(m_hwndDlg, GetLastError(), IDS_DOMAINLIST);
}
// Walk the ordered tree of domains, inserting each one into the
// dialog box
DWORD dwInitialDomain = -1;
// start at the head
while (pDomainList)
{
WCHAR * szBuffer2 = NULL;
// add this node
dwIndex = (DWORD)SendMessage(m_hCombo, CB_INSERTSTRING, (WPARAM) -1, (LPARAM)(LPCTSTR) pDomainList);
szBuffer2 = new WCHAR[wcslen(pDomainList->szData) + 1];
if (szBuffer2)
{
CopyAsFriendlyName(szBuffer2, pDomainList->szData);
}
if (NULL != szBuffer1 && NULL !=szBuffer2 && 0 ==_wcsicmp(szBuffer1, szBuffer2))
{
// replace the domain path with the path provided by the caller
// (because it contains the server)
WCHAR * sz = GetDomainFromLDAPPath(m_pGBI->lpInitialOU);
if (sz)
{
DebugMsg((DM_VERBOSE, TEXT("CBrowserPP::FillDomainList: Resetting domain path to user specified path: %s"), sz));
delete [] pDomainList->szData;
pDomainList->szData = sz;
}
dwInitialDomain = dwIndex;
if (pDomainList->nIndent > 0)
fEnableBackbutton = TRUE;
}
if (szBuffer2)
{
delete [] szBuffer2;
}
if (pDomainList->pChild)
{
// go to its child
pDomainList = pDomainList->pChild;
}
else
{
if (pDomainList->pSibling)
{
// go to its sibling if there are no children
pDomainList = pDomainList->pSibling;
}
else
{
// there are no children and no siblings
// back up until we find a parent with a sibling
// or there are no more parents (we're done)
do
{
pDomainList = pDomainList->pParent;
if (pDomainList)
{
if (pDomainList->pSibling)
{
pDomainList = pDomainList->pSibling;
break;
}
}
else
{
break;
}
} while (TRUE);
}
}
}
if (szBuffer1)
{
delete [] szBuffer1;
}
if (-1 == dwInitialDomain)
{
// didn't find the initial domain anywhere in that list
// Set the first entry by default
dwInitialDomain = 0;
}
SendMessage (m_hCombo, CB_SETCURSEL, dwInitialDomain, 0);
SendMessage (m_toolbar, TB_ENABLEBUTTON, (WPARAM) ID_BACKBUTTON, (LPARAM) MAKELONG(fEnableBackbutton, 0));
SetCursor(hcur);
return bResult;
}
//+--------------------------------------------------------------------------
//
// Member: CBrowserPP::SetInitialOU
//
// Synopsis: Adds nodes to the combobox until the initial OU specified by
// the caller via the lpInitalOU member of the GPOBROWSEINFO
// structure is present and gives it the focus.
//
// Returns: TRUE - success
//
// History: 10-20-1998 stevebl Created
//
// Notes: This routine assumes that FillDomainList() was just called.
// It will not work properly otherwise.
//
//---------------------------------------------------------------------------
BOOL CBrowserPP::SetInitialOU()
{
if (!m_pGBI->lpInitialOU)
{
// nothing requested so nothing required
return TRUE;
}
int iIndex = (int)SendMessage (m_hCombo, CB_GETCURSEL, 0, 0);
if (iIndex == CB_ERR)
{
DebugMsg((DM_WARNING, TEXT("CBrowserPP::SetInitialOU: No object selected.")));
return FALSE;
}
// get the current object to see what's selected
LOOKDATA * pdataSelected = (LOOKDATA *) SendMessage (m_hCombo, CB_GETITEMDATA, iIndex, 0);
if (pdataSelected)
{
// is it the same as the requested object?
WCHAR * szSelected = NULL;
WCHAR * szRequested = NULL;
szSelected = new WCHAR[wcslen(pdataSelected->szData) + 1];
if (szSelected)
{
CopyAsFriendlyName(szSelected, pdataSelected->szData);
}
szRequested = new WCHAR[wcslen(m_pGBI->lpInitialOU + 1)];
if (NULL != szSelected && NULL != szRequested && 0 != wcscmp(szSelected, szRequested))
{
// it's not the same
// try and bind to the requested object
IADs * pADs = NULL;
HRESULT hr = OpenDSObject(m_pGBI->lpInitialOU,
IID_IADs, (void **)&pADs);
if (SUCCEEDED(hr))
{
// the requested object exists and we have access permission
// now make sure that it's a domain or OU
BOOL fDomainOrOU = FALSE;
VARIANT var;
VariantInit(&var);
BSTR bstrProperty = SysAllocString(L"objectClass");
if (bstrProperty)
{
hr = pADs->Get(bstrProperty, &var);
if (SUCCEEDED(hr))
{
int cElements = var.parray->rgsabound[0].cElements;
VARIANT * rgData = (VARIANT *)var.parray->pvData;
while (cElements--)
{
if (0 == _wcsicmp(L"domain", rgData[cElements].bstrVal))
{
fDomainOrOU = TRUE;
}
if (0 == _wcsicmp(L"organizationalUnit", rgData[cElements].bstrVal))
{
fDomainOrOU = TRUE;
}
}
}
SysFreeString(bstrProperty);
}
VariantClear(&var);
pADs->Release();
if (fDomainOrOU)
{
LOOKDATA * pLast = NULL;
LOOKDATA * pNew = NULL;
// build a list of nodes
// repeat removing leaf nodes until we're down to the domain
// (which will be the same as the selected object)
IADsPathname * pADsPathname = NULL;
BSTR bstr;
hr = CoCreateInstance(CLSID_Pathname,
NULL,
CLSCTX_INPROC_SERVER,
IID_IADsPathname,
(LPVOID*)&pADsPathname);
if (SUCCEEDED(hr))
{
BSTR bstrInitialOU = SysAllocString( m_pGBI->lpInitialOU );
if ( bstrInitialOU != NULL )
{
hr = pADsPathname->Set( bstrInitialOU, ADS_SETTYPE_FULL );
if (SUCCEEDED(hr))
{
while (TRUE)
{
// add this node to the list
hr = pADsPathname->Retrieve(ADS_FORMAT_X500, &bstr);
if (FAILED(hr))
{
break;
}
if (szRequested)
{
delete [] szRequested;
}
szRequested = new WCHAR[wcslen(bstr) + 1];
if (szRequested)
{
CopyAsFriendlyName(szRequested, bstr);
}
if (NULL != szRequested && 0 == wcscmp(szSelected, szRequested))
{
// we're back to the first node
SysFreeString(bstr);
break;
}
pNew = new LOOKDATA;
if (!pNew)
{
// ran out of memory
SysFreeString(bstr);
break;
}
ULONG ulNoCharsRequested = wcslen(szRequested) + 1;
pNew->szName = new WCHAR[ulNoCharsRequested];
if (!pNew->szName)
{
// ran out of memory
delete pNew;
SysFreeString(bstr);
break;
}
ULONG ulNoChars = wcslen(bstr) + 1;
pNew->szData = new WCHAR[ulNoChars];
if (!pNew->szData)
{
// ran out of memory
delete [] pNew->szName;
delete pNew;
SysFreeString(bstr);
break;
}
hr = StringCchCopy(pNew->szData, ulNoChars, bstr);
ASSERT(SUCCEEDED(hr));
hr = StringCchCopy(pNew->szName, ulNoCharsRequested, szRequested);
ASSERT(SUCCEEDED(hr));
SysFreeString(bstr);
pNew->nIndent = 0;
pNew->nType = ITEMTYPE_OU;
pNew->pParent = NULL;
pNew->pSibling = NULL;
pNew->pChild = pLast;
if (pLast)
{
pLast->pParent = pNew;
}
pLast = pNew;
// strip off a leaf node and go again
hr = pADsPathname->RemoveLeafElement();
if (FAILED(hr))
{
break;
}
}
}
SysFreeString( bstrInitialOU );
}
pADsPathname->Release();
}
// At this point I should have a list of LOOKDATA nodes
// (in pLast).
// The only things left to do are to link them into the
// tree, set their nIndent members, add them to the combo
// box and set the combo box's focus to the last one.
if (pLast)
{
// link in the list
pLast->pSibling = pdataSelected->pChild;
pLast->pParent = pdataSelected;
pLast->nIndent = pdataSelected->nIndent+1;
pdataSelected->pChild = pLast;
// now walk the tree, adding entries to the combo box
// and updating the nIndent members
while (pLast)
{
iIndex = (int)SendMessage(m_hCombo, CB_INSERTSTRING, iIndex+1, (LPARAM)(LPCTSTR) pLast);
if (pLast->pChild)
{
pLast->pChild->nIndent = pLast->nIndent+1;
}
pLast = pLast->pChild;
}
if (iIndex != CB_ERR)
{
SendMessage(m_hCombo, CB_SETCURSEL, iIndex, 0);
SendMessage(m_toolbar, TB_ENABLEBUTTON, (WPARAM) ID_BACKBUTTON, (LPARAM) MAKELONG(TRUE, 0));
}
}
}
}
}
if (szSelected)
{
delete [] szSelected;
}
if (szRequested)
{
delete [] szRequested;
}
}
return TRUE;
}
//+--------------------------------------------------------------------------
//
// Member: CBrowserPP::GetCurrentObject
//
// Synopsis: returns the LDAP path to the currently selected object
//
// Arguments: [] -
//
// Returns: NULL if no ojbect is selected else the LDAP path of the object
//
// Modifies:
//
// Derivation:
//
// History: 5-05-1998 stevebl Created
// 06-23-1999 stevebl Added logic to give DCs names
//
// Notes:
// Checks to see if a domain has a named server. If it doesn't
// then it calls GetDCName to get it one.
//
//---------------------------------------------------------------------------
LPOLESTR CBrowserPP::GetCurrentObject()
{
int iIndex = (int)SendMessage (m_hCombo, CB_GETCURSEL, 0, 0);
if (iIndex == CB_ERR)
{
DebugMsg((DM_WARNING, TEXT("CBrowserPP::GetCurrentObject: No object selected.")));
return NULL;
}
LPOLESTR sz=NULL;
LOOKDATA * pdata = (LOOKDATA *) SendMessage (m_hCombo, CB_GETITEMDATA, iIndex, 0);
if (pdata)
{
if (pdata->szData)
{
HRESULT hr;
ULONG ulNoChars;
if (ITEMTYPE_DOMAIN == pdata->nType)
{
// make sure that domains are resolved to a server
LPTSTR szServer = ExtractServerName(pdata->szData);
if (NULL == szServer)
{
LPWSTR szTemp = GetDCName(pdata->szName, NULL, NULL, TRUE, 0);
if (szTemp)
{
LPWSTR szFullPath = MakeFullPath(pdata->szData, szTemp);
if (szFullPath)
{
ulNoChars = wcslen(szFullPath)+1;
LPWSTR szTemp2 = new WCHAR[ulNoChars];
if (szTemp2)
{
hr = StringCchCopy (szTemp2, ulNoChars, szFullPath);
ASSERT(SUCCEEDED(hr));
delete [] pdata->szData;
pdata->szData = szTemp2;
}
LocalFree(szFullPath);
}
LocalFree(szTemp);
}
else
{
return NULL;
}
}
else
{
LocalFree(szServer);
}
}
ulNoChars = wcslen(pdata->szData) + 1;
sz = new OLECHAR[ulNoChars];
if (sz)
{
hr = StringCchCopy(sz, ulNoChars, pdata->szData);
ASSERT(SUCCEEDED(hr));
}
}
}
return sz;
}
//+--------------------------------------------------------------------------
//
// Member: CBrowserPP::IsCurrentObjectAForest
//
// Synopsis: tests to see if the currently selected object is a forest
//
// Arguments: [] -
//
// Returns: TRUE - if it is a forest
// FALSE - otherwise
//
// History: 03-31-2000 stevebl Created
//
//---------------------------------------------------------------------------
BOOL CBrowserPP::IsCurrentObjectAForest()
{
int iIndex = (int)SendMessage (m_hCombo, CB_GETCURSEL, 0, 0);
if (iIndex == CB_ERR)
{
DebugMsg((DM_WARNING, TEXT("CBrowserPP::IsCurrentObjectAForest: No object selected.")));
return FALSE;
}
LOOKDATA * pdata = (LOOKDATA *) SendMessage (m_hCombo, CB_GETITEMDATA, iIndex, 0);
return (ITEMTYPE_FOREST == pdata->nType);
}
//+--------------------------------------------------------------------------
//
// Member: CBrowserPP::GetCurrentDomain
//
// Synopsis: returns the domain of the currently selecte object (if the
// currently currently selected object is the domain then they
// are one and the same)
//
// Arguments: [] -
//
// Returns: NULL - if no object is selected else returns LDAP path of
// domain
//
// History: 05-04-1998 stevebl Created
// 06-23-1999 stevebl Added logic to give DCs names
//
// Notes: Checks to see if a domain has a named server. If it doesn't
// then it calls GetDCName to get it one.
//
//---------------------------------------------------------------------------
LPOLESTR CBrowserPP::GetCurrentDomain()
{
int iIndex = (int)SendMessage (m_hCombo, CB_GETCURSEL, 0, 0);
if (iIndex == CB_ERR)
{
DebugMsg((DM_WARNING, TEXT("CBrowserPP::GetCurrentDomain: No object selected.")));
return NULL;
}
LOOKDATA * pdata = (LOOKDATA *) SendMessage (m_hCombo, CB_GETITEMDATA, iIndex, 0);
switch (pdata->nType)
{
case ITEMTYPE_DOMAIN:
{
if (pdata->szData)
{
HRESULT hr;
ULONG ulNoChars;
// make sure the domain has a server
LPTSTR szServer = ExtractServerName(pdata->szData);
if (NULL == szServer)
{
LPWSTR szTemp = GetDCName(pdata->szName, NULL, NULL, TRUE, 0);
if (szTemp)
{
LPWSTR szFullPath = MakeFullPath(pdata->szData, szTemp);
if (szFullPath)
{
ulNoChars = wcslen(szFullPath)+1;
LPWSTR sz = new WCHAR[ulNoChars];
if (sz)
{
hr = StringCchCopy(sz, ulNoChars, szFullPath);
ASSERT(SUCCEEDED(hr));
delete [] pdata->szData;
pdata->szData = sz;
}
LocalFree(szFullPath);
}
LocalFree(szTemp);
}
else
{
return NULL;
}
}
else
{
LocalFree(szServer);
}
ulNoChars = wcslen(pdata->szData)+1;
LPOLESTR sz = new OLECHAR[ulNoChars];
if (sz)
{
hr = StringCchCopy(sz, ulNoChars, pdata->szData);
ASSERT(SUCCEEDED(hr));
}
return sz;
}
return NULL;
}
case ITEMTYPE_FOREST:
case ITEMTYPE_SITE:
case ITEMTYPE_OU:
{
return GetDomainFromLDAPPath(pdata->szData);
}
break;
default:
break;
}
return NULL;
}
BOOL CBrowserPP::AddGPOsLinkedToObject()
{
HCURSOR hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
LPOLESTR lpObject;
HRESULT hr;
IADs * pADs = NULL;
IADs * pADsGPO;
VARIANT var;
BSTR bstrProperty;
BOOL fResult = FALSE;
int index = ListView_GetItemCount(m_hList);
//
// Get the current object name
//
lpObject = GetCurrentObject();
if (NULL == lpObject)
{
return FALSE;
}
DebugMsg((DM_VERBOSE, TEXT("CBrowserPP::AddGPOsLinkedToObject: Reading gPLink property from %s"), lpObject));
hr = OpenDSObject(lpObject, IID_IADs, (void **)&pADs);
delete [] lpObject;
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("CBrowserPP::AddGPOsLinkedToObject: OpenDSObject failed with 0x%x"), hr));
ReportError(m_hwndDlg, hr, IDS_FAILEDGPLINK);
goto Exit;
}
VariantInit(&var);
bstrProperty = SysAllocString(GPM_LINK_PROPERTY);
if (bstrProperty)
{
hr = pADs->Get(bstrProperty, &var);
if (SUCCEEDED(hr))
{
LPOLESTR szGPOList = var.bstrVal;
OLECHAR * pchTemp;
OLECHAR * pchGPO;
VARIANT varName;
BSTR bstrNameProp;
if (szGPOList)
{
OLECHAR * szGPO = new WCHAR[wcslen(szGPOList) + 1];
if (szGPO)
{
pchTemp = szGPOList;
while (TRUE)
{
// Look for the [
while (*pchTemp && (*pchTemp != L'['))
pchTemp++;
if (!(*pchTemp))
break;
pchTemp++;
// Copy the GPO name
pchGPO = szGPO;
while (*pchTemp && (*pchTemp != L';'))
*pchGPO++ = *pchTemp++;
*pchGPO = L'\0';
// Add the object to the list view
MYLISTEL * pel = new MYLISTEL;
if (pel)
{
pel->szData = NULL;
pel->bDisabled = FALSE;
LPTSTR szFullGPOPath = GetFullPath(szGPO, m_hwndDlg);
if (szFullGPOPath)
{
ULONG ulNoChars = wcslen(szFullGPOPath) + 1;
pel->szData = new WCHAR[ulNoChars];
if (pel->szData)
{
hr = StringCchCopy(pel->szData, ulNoChars, szFullGPOPath);
ASSERT(SUCCEEDED(hr));
}
else
{
DebugMsg((DM_WARNING, TEXT("CBrowserPP::AddGPOsLinkedToObject: Failed to allocate memory for new full gpo path")));
LocalFree(szFullGPOPath);
delete pel;
continue;
}
LocalFree(szFullGPOPath);
}
else
{
DebugMsg((DM_WARNING, TEXT("CBrowserPP::AddGPOsLinkedToObject: Failed to get full gpo path")));
delete pel;
continue;
}
VariantInit(&varName);
// get the friendly display name
hr = OpenDSObject(pel->szData, IID_IADs,
(void **)&pADsGPO);
if (hr == HRESULT_FROM_WIN32(ERROR_DS_NO_SUCH_OBJECT))
{
delete pel;
continue;
}
if (SUCCEEDED(hr))
{
bstrNameProp = SysAllocString(GPO_NAME_PROPERTY);
if (bstrNameProp)
{
hr = pADsGPO->Get(bstrNameProp, &varName);
SysFreeString(bstrNameProp);
}
else
{
hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
}
pADsGPO->Release();
}
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("CBrowserPP::AddGPOsLinkedToObject: Couldn't get display name for %s with 0x%x"), pel->szData, hr));
pel->szName = new WCHAR[200];
if (pel->szName)
{
LoadString(g_hInstance, IDS_GPM_NOGPONAME, pel->szName, 200);
}
pel->bDisabled = TRUE;
}
else
{
ULONG ulNoChars = wcslen(varName.bstrVal) + 1;
pel->szName = new WCHAR[ulNoChars];
if (pel->szName)
{
hr = StringCchCopy(pel->szName, ulNoChars, varName.bstrVal);
ASSERT(SUCCEEDED(hr));
}
}
VariantClear(&varName);
pel->nType = ITEMTYPE_GPO;
AddElement(pel, index);
}
}
delete [] szGPO;
}
}
}
SysFreeString(bstrProperty);
}
VariantClear(&var);
fResult = TRUE;
Exit:
if (pADs)
{
pADs->Release();
}
SetCursor(hcur);
return fResult;
}
//+--------------------------------------------------------------------------
//
// Member: CBrowserPP::AddGPOsForDomain
//
// Synopsis: Adds all the GPOs in the specified domain to the list view
// control. The szData member of the list element structure
// contains the LDAP path of the GPO.
//
// The domain is indicated by the currently selected combobox
// element.
//
// Returns: TRUE - successful
// FALSE - error
//
// History: 04-30-1998 stevebl Modified from original routine
// written by EricFlo.
//
//---------------------------------------------------------------------------
BOOL CBrowserPP::AddGPOsForDomain()
{
LPTSTR lpDomain;
LPTSTR lpGPO;
INT iIndex;
VARIANT var;
VARIANT varGPO;
ULONG ulResult;
HRESULT hr = E_FAIL;
IADsPathname * pADsPathname = NULL;
IADs * pADs = NULL;
IADsContainer * pADsContainer = NULL;
IDispatch * pDispatch = NULL;
IEnumVARIANT *pVar = NULL;
BSTR bstrContainer = NULL;
BSTR bstrCommonName = NULL;
BSTR bstrDisplayName = NULL;
BSTR bstrGPO = NULL;
TCHAR szDisplayName[512];
TCHAR szCommonName[50];
MYLISTEL * pel;
ULONG ulNoChars;
//
// Test to see if we're focused on a forest
//
BOOL fForest = IsCurrentObjectAForest();
//
// Get the current domain name
//
lpDomain = GetCurrentDomain();
if (!lpDomain)
{
DebugMsg((DM_WARNING, TEXT("AddGPOsForDomain: NULL domain name.")));
return FALSE;
}
HCURSOR hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
//
// Create a pathname object we can work with
//
hr = CoCreateInstance(CLSID_Pathname, NULL, CLSCTX_INPROC_SERVER,
IID_IADsPathname, (LPVOID*)&pADsPathname);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("AddGPOsForDomain: Failed to create adspathname instance with 0x%x"), hr));
goto Exit;
}
//
// Add the domain name
//
BSTR bstrDomain = SysAllocString( lpDomain );
if ( bstrDomain == NULL )
{
DebugMsg((DM_WARNING, TEXT("AddGPOsForDomain: Failed to allocate BSTR memory.")));
hr = E_OUTOFMEMORY;
goto Exit;
}
hr = pADsPathname->Set (bstrDomain, ADS_SETTYPE_FULL);
SysFreeString( bstrDomain );
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("AddGPOsForDomain: Failed to set pathname with 0x%x"), hr));
goto Exit;
}
BSTR bstrFolder = NULL;
if (fForest)
{
//
// Add the configuration folder to the path
//
bstrFolder = SysAllocString( TEXT("CN=Configuration") );
}
else
{
//
// Add the system folder to the path
//
bstrFolder = SysAllocString( TEXT("CN=System") );
}
if ( bstrFolder == NULL )
{
DebugMsg((DM_WARNING, TEXT("AddGPOsForDomain: Failed to allocate BSTR memory.")));
hr = E_OUTOFMEMORY;
goto Exit;
}
hr = pADsPathname->AddLeafElement (bstrFolder);
SysFreeString( bstrFolder );
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("AddGPOsForDomain: Failed to add system folder with 0x%x"), hr));
goto Exit;
}
//
// Add the policies container to the path
//
BSTR bstrCNPolicies = SysAllocString( TEXT("CN=Policies") );
if ( bstrCNPolicies == NULL )
{
DebugMsg((DM_WARNING, TEXT("AddGPOsForDomain: Failed to allocate BSTR memory.")));
hr = E_OUTOFMEMORY;
goto Exit;
}
hr = pADsPathname->AddLeafElement (bstrCNPolicies);
SysFreeString( bstrCNPolicies );
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("AddGPOsForDomain: Failed to add policies folder with 0x%x"), hr));
goto Exit;
}
//
// Retreive the container path - this is the path to the policies folder
//
hr = pADsPathname->Retrieve (ADS_FORMAT_X500, &bstrContainer);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("AddGPOsForDomain: Failed to retreive container path with 0x%x"), hr));
goto Exit;
}
//
// Release the pathname object
//
pADsPathname->Release();
pADsPathname = NULL;
//
// Build an enumerator
//
hr = OpenDSObject(bstrContainer, IID_IADsContainer, (void **)&pADsContainer);
if (FAILED(hr))
{
if (hr != HRESULT_FROM_WIN32(ERROR_DS_NO_SUCH_OBJECT))
{
DebugMsg((DM_VERBOSE, TEXT("AddGPOsForDomain: Failed to get gpo container interface with 0x%x for object %s"),
hr, bstrContainer));
ReportError(m_hwndDlg, hr, IDS_FAILEDGPLINK);
}
goto Exit;
}
hr = ADsBuildEnumerator (pADsContainer, &pVar);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("AddGPOsForDomain: Failed to get enumerator with 0x%x"), hr));
goto Exit;
}
bstrCommonName = SysAllocString (L"cn");
if (!bstrCommonName)
{
DebugMsg((DM_WARNING, TEXT("AddGPOsForDomain: Failed to allocate memory with %d"), GetLastError()));
goto Exit;
}
bstrDisplayName = SysAllocString (GPO_NAME_PROPERTY);
if (!bstrDisplayName)
{
DebugMsg((DM_WARNING, TEXT("AddGPOsForDomain: Failed to allocate memory with %d"), GetLastError()));
goto Exit;
}
//
// Enumerate
//
while (TRUE)
{
BOOL fNeedDisplayName = FALSE;
VariantInit(&var);
hr = ADsEnumerateNext(pVar, 1, &var, &ulResult);
if (FAILED(hr))
{
DebugMsg((DM_VERBOSE, TEXT("AddGPOsForDomain: Failed to enumerator with 0x%x"), hr));
VariantClear (&var);
break;
}
if (S_FALSE == hr)
{
VariantClear (&var);
break;
}
//
// If var.vt isn't VT_DISPATCH, we're finished.
//
if (var.vt != VT_DISPATCH)
{
VariantClear (&var);
break;
}
//
// We found something, get the IDispatch interface
//
pDispatch = var.pdispVal;
if (!pDispatch)
{
DebugMsg((DM_VERBOSE, TEXT("AddGPOsForDomain: Failed to get IDispatch interface")));
goto LoopAgain;
}
//
// Now query for the IADs interface so we can get some
// properties from this GPO.
//
hr = pDispatch->QueryInterface(IID_IADs, (LPVOID *)&pADs);
if (FAILED(hr)) {
DebugMsg((DM_WARNING, TEXT("AddGPOsForDomain: QI for IADs failed with 0x%x"), hr));
goto LoopAgain;
}
//
// Get the display name
//
VariantInit(&varGPO);
hr = pADs->Get(bstrDisplayName, &varGPO);
if (FAILED(hr))
{
DebugMsg((DM_VERBOSE, TEXT("AddGPOsForDomain: Failed to get display name with 0x%x"),hr));
fNeedDisplayName = TRUE;
}
else
{
wcsncpy (szDisplayName, varGPO.bstrVal, (sizeof(szDisplayName) / sizeof(szDisplayName[0])) - 1);
}
VariantClear (&varGPO);
//
// Get the common name
//
VariantInit(&varGPO);
hr = pADs->Get(bstrCommonName, &varGPO);
if (FAILED(hr))
{
DebugMsg((DM_VERBOSE, TEXT("AddGPOsForDomain: Failed to get common name with 0x%x"),hr));
VariantClear (&varGPO);
pADs->Release();
goto LoopAgain;
}
hr = StringCchCopy (szCommonName, ARRAYSIZE(szCommonName), TEXT("CN="));
if (SUCCEEDED(hr))
{
hr = StringCchCat (szCommonName, ARRAYSIZE(szCommonName), varGPO.bstrVal);
}
//
// Clean up
//
VariantClear (&varGPO);
pADs->Release();
if (FAILED(hr))
{
goto LoopAgain;
}
//
// Create a pathname object so we can tack the common name
// onto the end of the LDAP path
//
hr = CoCreateInstance(CLSID_Pathname, NULL, CLSCTX_INPROC_SERVER,
IID_IADsPathname, (LPVOID*)&pADsPathname);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("AddGPOsForDomain: Failed to create adspathname instance with 0x%x"), hr));
goto LoopAgain;
}
//
// Add the LDAP path
//
hr = pADsPathname->Set (bstrContainer, ADS_SETTYPE_FULL);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("AddGPOsForDomain: Failed to set the ldap path with 0x%x"), hr));
goto LoopAgain;
}
//
// Add the GPO's common name
//
BSTR bstrTmpCommonName = SysAllocString( szCommonName );
if ( bstrTmpCommonName == NULL )
{
DebugMsg((DM_WARNING, TEXT("AddGPOsForDomain: Failed to allocate BSTR memory.")));
hr = E_OUTOFMEMORY;
goto LoopAgain;
}
hr = pADsPathname->AddLeafElement (bstrTmpCommonName);
SysFreeString( bstrTmpCommonName );
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("AddGPOsForDomain: Failed to add the common name with 0x%x"), hr));
goto LoopAgain;
}
//
// Retreive the gpo path
//
hr = pADsPathname->Retrieve (ADS_FORMAT_X500, &bstrGPO);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("AddGPOsForDomain: Failed to retreive gpo path with 0x%x"), hr));
goto LoopAgain;
}
//
// Make a copy of it
//
ulNoChars = wcslen(bstrGPO) + 1;
lpGPO = new WCHAR[ulNoChars];
if (!lpGPO)
{
DebugMsg((DM_WARNING, TEXT("AddGPOsForDomain: Failed to alloc memory for gpo path with 0x%x"),
GetLastError()));
goto LoopAgain;
}
hr = StringCchCopy (lpGPO, ulNoChars, bstrGPO);
ASSERT(SUCCEEDED(hr));
pel = new MYLISTEL;
if (pel)
{
if (fNeedDisplayName)
{
pel->szName = new WCHAR[wcslen(lpGPO) + 1];
if (pel->szName)
{
CopyAsFriendlyName(pel->szName, lpGPO);
}
}
else
{
ulNoChars = wcslen(szDisplayName) + 1;
pel->szName = new WCHAR[ulNoChars];
if (pel->szName)
{
hr = StringCchCopy(pel->szName, ulNoChars, szDisplayName);
ASSERT(SUCCEEDED(hr));
}
}
pel->szData = lpGPO;
pel->nType = ITEMTYPE_GPO;
pel->bDisabled = FALSE;
AddElement(pel, -1);
}
LoopAgain:
if (pADsPathname)
{
pADsPathname->Release();
pADsPathname = NULL;
}
if (bstrGPO)
{
SysFreeString (bstrGPO);
bstrGPO = NULL;
}
VariantClear (&var);
}
SendMessage (m_hList, LB_SETCURSEL, 0, 0);
Exit:
if (pVar)
{
ADsFreeEnumerator (pVar);
}
if (pADsPathname)
{
pADsPathname->Release();
}
if (pADsContainer)
{
pADsContainer->Release();
}
if (bstrContainer)
{
SysFreeString (bstrContainer);
}
if (bstrCommonName)
{
SysFreeString (bstrCommonName);
}
if (bstrDisplayName)
{
SysFreeString (bstrDisplayName);
}
if (lpDomain)
{
delete [] lpDomain;
}
SetCursor(hcur);
return TRUE;
}
//+--------------------------------------------------------------------------
//
// Member: CBrowserPP::AddChildContainers
//
// Synopsis: Adds the child domains and OUs for the currently selected object
//
// History: 05-006-1998 stevebl Created
//
//---------------------------------------------------------------------------
BOOL CBrowserPP::AddChildContainers()
{
LPOLESTR szObject = NULL;
HRESULT hr;
ULONG ulNoChars;
int iIndex = (int)SendMessage (m_hCombo, CB_GETCURSEL, 0, 0);
if (iIndex == CB_ERR)
{
DebugMsg((DM_WARNING, TEXT("CBrowserPP::AddChildContainers: No object selected.")));
return FALSE;
}
LOOKDATA * pdata = (LOOKDATA *) SendMessage (m_hCombo, CB_GETITEMDATA, iIndex, 0);
if (pdata)
{
if (ITEMTYPE_DOMAIN == pdata->nType)
{
// make sure that domains are resolved to a server
LPTSTR szServer = ExtractServerName(pdata->szData);
if (NULL == szServer)
{
BOOL bDCFound = FALSE;
LPWSTR szTemp = GetDCName(pdata->szName, NULL, NULL, TRUE, 0);
if (szTemp)
{
LPWSTR szFullPath = MakeFullPath(pdata->szData, szTemp);
if (szFullPath)
{
ulNoChars = wcslen(szFullPath)+1;
LPWSTR sz = new WCHAR[ulNoChars];
if (sz)
{
hr = StringCchCopy(sz, ulNoChars, szFullPath);
ASSERT(SUCCEEDED(hr));
delete [] pdata->szData;
pdata->szData = sz;
bDCFound = TRUE;
}
LocalFree(szFullPath);
}
LocalFree(szTemp);
}
if (!bDCFound)
{
DebugMsg((DM_WARNING, TEXT("CBrowserPP::AddChildContainers: Failed to get a DC name for %s"),
pdata->szName));
return FALSE;
}
}
else
{
LocalFree(szServer);
}
}
LOOKDATA * pChild = pdata->pChild;
while (pChild)
{
// Add child domains this way since ADsEnumerateNext doesn't
// seem to be giving them to us.
if (ITEMTYPE_DOMAIN == pChild->nType)
{
// got something we can work with
MYLISTEL * pel = new MYLISTEL;
if (pel)
{
memset(pel, 0, sizeof(MYLISTEL));
ulNoChars = wcslen(pChild->szData) + 1;
pel->szData = new OLECHAR[ulNoChars];
if (pel->szData)
{
hr = StringCchCopy(pel->szData, ulNoChars, pChild->szData);
ASSERT(SUCCEEDED(hr));
}
ulNoChars = wcslen(pChild->szName) + 1;
pel->szName = new OLECHAR[ulNoChars];
if (pel->szName)
{
hr = StringCchCopy(pel->szName, ulNoChars, pChild->szName);
ASSERT(SUCCEEDED(hr));
}
pel->bDisabled = FALSE;
pel->nType = ITEMTYPE_DOMAIN;
INT index = -1;
AddElement(pel, -1);
}
pChild = pChild->pSibling;
}
}
szObject = pdata->szData;
m_pPrevSel = pdata;
} else {
m_pPrevSel = NULL;
}
if ( ! szObject )
{
return FALSE;
}
IADsContainer * pADsContainer;
hr = OpenDSObject(szObject, IID_IADsContainer, (void **)&pADsContainer);
if (SUCCEEDED(hr))
{
IEnumVARIANT *pVar;
hr = ADsBuildEnumerator(pADsContainer, &pVar);
if (SUCCEEDED(hr))
{
VARIANT var;
VariantInit(&var);
ULONG ulResult;
while (SUCCEEDED(ADsEnumerateNext(pVar, 1, &var, &ulResult)))
{
if (0 == ulResult)
{
break;
}
if (var.vt == VT_DISPATCH)
{
// query for the IADs interface so we can get its properties
IADs * pDSObject;
hr = var.pdispVal->QueryInterface(IID_IADs, (LPVOID *)&pDSObject);
if (SUCCEEDED(hr))
{
BSTR bstr;
DWORD dwType = -1;
hr = pDSObject->get_Class(&bstr);
if (SUCCEEDED(hr))
{
if (0 == wcscmp(bstr, CLASSNAME_OU))
{
dwType = ITEMTYPE_OU;
}
else if (0 == wcscmp(bstr, CLASSNAME_DOMAIN))
{
dwType = ITEMTYPE_DOMAIN;
}
SysFreeString(bstr);
}
if (ITEMTYPE_DOMAIN == dwType || ITEMTYPE_OU == dwType)
{
// got something we can work with
MYLISTEL * pel = new MYLISTEL;
if (pel)
{
memset(pel, 0, sizeof(MYLISTEL));
hr = pDSObject->get_ADsPath(&bstr);
if (SUCCEEDED(hr))
{
ulNoChars = wcslen(bstr) + 1;
pel->szData = new OLECHAR[ulNoChars];
if (pel->szData)
{
hr = StringCchCopy(pel->szData, ulNoChars, bstr);
ASSERT(SUCCEEDED(hr));
}
pel->szName = new OLECHAR[wcslen(bstr) + 1];
if (pel->szName)
{
// Need to convert to a friendly name.
CopyAsFriendlyName(pel->szName, bstr);
}
SysFreeString(bstr);
}
pel->nType = dwType;
INT index = -1;
AddElement(pel, -1);
}
}
pDSObject->Release();
}
}
VariantClear(&var);
}
ADsFreeEnumerator(pVar);
}
pADsContainer->Release();
}
return TRUE;
}
//+--------------------------------------------------------------------------
//
// Member: CBrowserPP::RefreshDomains
//
// Synopsis: refreshes the listview for the "domains" page
//
// History: 04-30-1998 stevebl Created
//
//---------------------------------------------------------------------------
void CBrowserPP::RefreshDomains()
{
LONG lStyle;
ListView_DeleteAllItems(m_hList);
lStyle = GetWindowLong (m_hList, GWL_STYLE);
lStyle &= ~LVS_SORTASCENDING;
SetWindowLong (m_hList, GWL_STYLE, lStyle);
if (AddChildContainers())
{
AddGPOsLinkedToObject();
EnableWindow (m_hList, TRUE);
if (!(m_pGBI->dwFlags & GPO_BROWSE_DISABLENEW)) {
SendMessage (m_toolbar, TB_ENABLEBUTTON, (WPARAM) ID_NEWFOLDER, (LPARAM) MAKELONG(1, 0));
}
}
else
{
EnableWindow (m_hList, FALSE);
SendMessage (m_toolbar, TB_ENABLEBUTTON, (WPARAM) ID_NEWFOLDER, (LPARAM) MAKELONG(0, 0));
}
}
//+--------------------------------------------------------------------------
//
// Member: CBrowserPP::RefreshSites
//
// Synopsis: refreshes the listview for the "sites" page
//
// History: 04-30-1998 stevebl Created
//
//---------------------------------------------------------------------------
void CBrowserPP::RefreshSites()
{
LONG lStyle;
ListView_DeleteAllItems(m_hList);
lStyle = GetWindowLong (m_hList, GWL_STYLE);
lStyle &= ~LVS_SORTASCENDING;
SetWindowLong (m_hList, GWL_STYLE, lStyle);
AddGPOsLinkedToObject();
}
//+--------------------------------------------------------------------------
//
// Member: CBrowserPP::RefreshAll
//
// Synopsis: refreshes the listview for the "all" page
//
// History: 04-30-1998 stevebl Created
//
//---------------------------------------------------------------------------
void CBrowserPP::RefreshAll()
{
LONG lStyle;
ListView_DeleteAllItems(m_hList);
lStyle = GetWindowLong (m_hList, GWL_STYLE);
lStyle |= LVS_SORTASCENDING;
SetWindowLong (m_hList, GWL_STYLE, lStyle);
if (AddGPOsForDomain())
{
EnableWindow (m_hList, TRUE);
SendMessage (m_toolbar, TB_ENABLEBUTTON, (WPARAM) ID_NEWFOLDER, (LPARAM) MAKELONG(1, 0));
}
else
{
EnableWindow (m_hList, FALSE);
SendMessage (m_toolbar, TB_ENABLEBUTTON, (WPARAM) ID_NEWFOLDER, (LPARAM) MAKELONG(0, 0));
}
}
void CBrowserPP::SetButtonState()
{
if (ListView_GetNextItem (m_hList, -1, LVNI_ALL | LVNI_SELECTED) != -1)
{
EnableWindow (GetDlgItem(GetParent(m_hwndDlg), IDOK), TRUE);
}
else
{
EnableWindow (GetDlgItem(GetParent(m_hwndDlg), IDOK), FALSE);
}
}
BOOL CBrowserPP::OnInitDialog()
{
DWORD dwDescription;
switch (m_dwPageType)
{
case PAGETYPE_DOMAINS:
dwDescription = IDS_DOMAINDESCRIPTION;
break;
case PAGETYPE_SITES:
dwDescription = IDS_SITEDESCRIPTION;
break;
case PAGETYPE_ALL:
default:
dwDescription = IDS_ALLDESCRIPTION;
break;
}
WCHAR szDescription[MAX_PATH]; // this is a resource - size doesn't need to be dynamic
LoadString(g_hInstance, dwDescription, szDescription, MAX_PATH);
SetDlgItemText(m_hwndDlg, IDC_DESCRIPTION, szDescription);
m_hList = GetDlgItem(m_hwndDlg, IDC_LIST1);
m_ilSmall = ImageList_LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_16x16), SMALLICONSIZE, 0, RGB(255,0,255));
m_ilLarge = ImageList_LoadBitmap(g_hInstance, MAKEINTRESOURCE(IDB_32x32), LARGEICONSIZE, 0, RGB(255, 0 ,255));
m_hCombo = GetDlgItem(m_hwndDlg, IDC_COMBO1);
RECT rect;
GetClientRect(m_hList, &rect);
WCHAR szText[32];
int dxScrollBar = GetSystemMetrics(SM_CXVSCROLL);
if (PAGETYPE_ALL == m_dwPageType)
{
LV_COLUMN lvcol;
memset(&lvcol, 0, sizeof(lvcol));
lvcol.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
lvcol.fmt = LVCFMT_LEFT;
lvcol.cx = (rect.right - rect.left) - dxScrollBar;
LoadString(g_hInstance, IDS_NAMECOLUMN, szText, 32);
lvcol.pszText = szText;
ListView_InsertColumn(m_hList, 0, &lvcol);
}
else
{
LV_COLUMN lvcol;
memset(&lvcol, 0, sizeof(lvcol));
lvcol.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
lvcol.fmt = LVCFMT_LEFT;
int cx = ((rect.right - rect.left) - dxScrollBar)*2/3;
lvcol.cx = cx;
LoadString(g_hInstance, IDS_NAMECOLUMN, szText, 32);
lvcol.pszText = szText;
ListView_InsertColumn(m_hList, 0, &lvcol);
memset(&lvcol, 0, sizeof(lvcol));
lvcol.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
lvcol.fmt = LVCFMT_LEFT;
lvcol.cx = ((rect.right - rect.left) - dxScrollBar) - cx;
LoadString(g_hInstance, IDS_DOMAINCOLUMN, szText, 32);
lvcol.pszText = szText;
ListView_InsertColumn(m_hList, 1, &lvcol);
}
ListView_SetImageList(m_hList, m_ilSmall, LVSIL_SMALL);
ListView_SetImageList(m_hList, m_ilLarge, LVSIL_NORMAL);
SendMessage(m_hList, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_LABELTIP);
GetWindowRect(GetDlgItem(m_hwndDlg, IDC_STATIC1), &rect);
MapWindowPoints(NULL , m_hwndDlg, (LPPOINT) &rect , 2);
TBBUTTON rgButtons[3];
rgButtons[0].iBitmap = 0;
rgButtons[0].idCommand = ID_BACKBUTTON;
rgButtons[0].fsState = 0; // this button will be disabled by
// default and only enabled when there
// is something to back up to
//rgButtons[0].fsState = PAGETYPE_ALL == m_dwPageType ? 0 : TBSTATE_ENABLED;
rgButtons[0].fsStyle = TBSTYLE_BUTTON;
rgButtons[0].dwData = 0;
rgButtons[0].iString = 0;
rgButtons[1].iBitmap = 1;
rgButtons[1].idCommand = ID_NEWFOLDER;
rgButtons[1].fsStyle = TBSTYLE_BUTTON;
rgButtons[1].dwData = 0;
rgButtons[1].iString = 0;
if (PAGETYPE_ALL != m_dwPageType)
{
if (m_pGBI->dwFlags & GPO_BROWSE_DISABLENEW)
{
rgButtons[1].fsState = 0;
}
else
{
rgButtons[1].fsState = TBSTATE_ENABLED;
}
}
else
{
rgButtons[1].fsState =TBSTATE_ENABLED;
}
rgButtons[2].iBitmap = 2;
rgButtons[2].idCommand = ID_ROTATEVIEW;
rgButtons[2].fsState = TBSTATE_ENABLED ;
rgButtons[2].fsStyle = TBSTYLE_DROPDOWN;
rgButtons[2].dwData = 0;
rgButtons[2].iString = 0;
m_toolbar = CreateToolbarEx(m_hwndDlg,
WS_CHILD | WS_VISIBLE | CCS_NODIVIDER | CCS_NORESIZE | TBSTYLE_FLAT | TBSTYLE_TOOLTIPS,
IDR_TOOLBAR1,
4,
g_hInstance,
IDR_TOOLBAR1,
rgButtons,
3,
BUTTONSIZE,
BUTTONSIZE,
BUTTONSIZE,
BUTTONSIZE,
sizeof(TBBUTTON));
SendMessage(m_toolbar, TB_SETEXTENDEDSTYLE, TBSTYLE_EX_DRAWDDARROWS, TBSTYLE_EX_DRAWDDARROWS);
MoveWindow(m_toolbar, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, FALSE);
// Don't need to call Refresh in any of these because we're calling it in
// OnComboChange().
switch (m_dwPageType)
{
case PAGETYPE_DOMAINS:
FillDomainList();
SetInitialOU();
// RefreshDomains();
break;
case PAGETYPE_SITES:
SendMessage(m_hCombo, CB_RESETCONTENT, (WPARAM) 0, (LPARAM) 0);
FillSitesList();
// RefreshSites();
break;
default:
case PAGETYPE_ALL:
SendMessage(m_hCombo, CB_RESETCONTENT, (WPARAM) 0, (LPARAM) 0);
FillDomainList();
// RefreshAll();
break;
}
SetButtonState();
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
BOOL CBrowserPP::DoBackButton()
{
int iIndex = (int)SendMessage (m_hCombo, CB_GETCURSEL, 0, 0);
if (iIndex == CB_ERR)
{
DebugMsg((DM_WARNING, TEXT("CBrowserPP::DoBackButton: No object selected.")));
return FALSE;
}
LOOKDATA * pdata = (LOOKDATA *) SendMessage (m_hCombo, CB_GETITEMDATA, iIndex, 0);
if (pdata)
{
if (pdata->pParent)
{
// if this item has a parent then select it
SendMessage(m_hCombo, CB_SELECTSTRING, (WPARAM)-1, (LPARAM) (LPCTSTR) pdata->pParent);
// force everything to refresh
OnComboChange();
}
}
return FALSE;
}
BOOL CBrowserPP::DeleteGPO()
{
BOOL fSucceeded = FALSE;
BOOL fRemoveListEntry = FALSE;
int index = ListView_GetNextItem(m_hList, -1, LVNI_SELECTED);
if (-1 == index)
{
return FALSE;
}
LVITEM item;
memset(&item, 0, sizeof(item));
item.mask = LVIF_PARAM;
item.iItem = index;
ListView_GetItem(m_hList, &item);
MYLISTEL * pel = (MYLISTEL *)item.lParam;
LPGROUPPOLICYOBJECT pGPO = NULL;
HRESULT hr;
WCHAR szBuffer[100];
WCHAR szConfirm[MAX_FRIENDLYNAME + 100];
WCHAR szTitle[100];
if (pel->nType != ITEMTYPE_GPO)
{
goto CleanUp;
}
LoadString(g_hInstance, IDS_CONFIRMTITLE, szTitle, 100);
LoadString(g_hInstance, IDS_DELETECONFIRM, szBuffer, 100);
(void) StringCchPrintf (szConfirm, ARRAYSIZE(szConfirm), szBuffer, pel->szName);
if (IDNO == MessageBox(m_hwndDlg, szConfirm, szTitle, MB_YESNO | MB_ICONEXCLAMATION))
{
goto CleanUp;
}
// If we're on any page other than the "All" page then we need to break
// the association before we can delete the object.
if (m_dwPageType != PAGETYPE_ALL)
{
// break the association
LPOLESTR szContainer = GetCurrentObject();
if (szContainer)
{
DeleteLink(pel->szData, szContainer);
delete [] szContainer;
}
}
hr = CoCreateInstance(CLSID_GroupPolicyObject, NULL,
CLSCTX_SERVER, IID_IGroupPolicyObject,
(void **)&pGPO);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("CoCreateInstance failed with 0x%x\r\n"), hr));
goto Done;
}
// open GPO object without opening registry data
hr = pGPO->OpenDSGPO(pel->szData, 0);
if (FAILED(hr))
{
ReportError(m_hwndDlg, hr, IDS_FAILEDDS);
DebugMsg((DM_WARNING, TEXT("OpenDSGPO failed with 0x%x\r\n"), hr));
goto Done;
}
// delete it
hr = pGPO->Delete();
if (FAILED(hr))
{
ReportError(m_hwndDlg, hr, IDS_FAILEDDELETE);
DebugMsg((DM_WARNING, TEXT("Delete failed with 0x%x\r\n"), hr));
goto Done;
}
fRemoveListEntry = TRUE;
Done:
if (pGPO)
{
pGPO->Release();
}
// remove the list entry
if (fRemoveListEntry)
fSucceeded = ListView_DeleteItem(m_hList, index);
CleanUp:
return fSucceeded;
}
BOOL CBrowserPP::DoNewGPO()
{
BOOL fSucceeded = FALSE;
HRESULT hr;
LPGROUPPOLICYOBJECT pGPO = NULL;
BOOL fEdit = FALSE;
MYLISTEL * pel = NULL;
LPOLESTR szObject = GetCurrentObject();
LPOLESTR szDomain = GetCurrentDomain();
INT index = -1;
int cch = 0;
LPTSTR szFullPath = NULL;
LPTSTR szServerName = NULL;
DWORD dwOptions = 0;
if (NULL == szDomain)
{
goto Done;
}
if (NULL == szObject)
{
goto Done;
}
pel = new MYLISTEL;
if (NULL == pel)
{
DebugMsg((DM_WARNING, TEXT("CBrowserPP::DoNewGPO failed to allocate memory for GPO name")));
goto Done;
}
pel->bDisabled = FALSE;
pel->szData = NULL;
pel->szName = new OLECHAR[MAX_FRIENDLYNAME];
if (NULL == pel->szName)
{
DebugMsg((DM_WARNING, TEXT("CBrowserPP::DoNewGPO failed to allocate memory for GPO name")));
goto Done;
}
GetNewGPODisplayName (pel->szName, MAX_FRIENDLYNAME);
pel->nType = ITEMTYPE_GPO;
// Create a new GPO named "New Group Policy Object"
//
// Create a new GPO object to work with
//
hr = CoCreateInstance (CLSID_GroupPolicyObject, NULL,
CLSCTX_SERVER, IID_IGroupPolicyObject,
(void**)&pGPO);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("CoCreateInstance failed with 0x%x\r\n"), hr));
goto Done;
}
//
// Open the requested object without mounting the registry
//
#if FGPO_SUPPORT
if (IsCurrentObjectAForest())
{
dwOptions = GPO_OPEN_FOREST;
}
#endif
hr = pGPO->New(szDomain, pel->szName, dwOptions);
if (FAILED(hr))
{
ReportError(m_hwndDlg, hr, IDS_FAILEDNEW);
DebugMsg((DM_WARNING, TEXT("Failed to create GPO object with 0x%x\r\n"), hr));
goto Done;
}
// continue to try to allocate memory until either a big enough buffer is
// created to load the GPO path or we run out of memory
pel->szData = NULL;
do
{
if (pel->szData)
{
delete [] pel->szData;
}
cch += MAX_PATH;
pel->szData = new OLECHAR[cch];
if (NULL == pel->szData)
{
}
hr = pGPO->GetPath(pel->szData, cch);
} while (hr == E_OUTOFMEMORY);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("Failed to get GPO object path with 0x%x\r\n"), hr));
goto Done;
}
szServerName = ExtractServerName(szDomain);
szFullPath = MakeFullPath(pel->szData, szServerName);
if (szFullPath)
{
ULONG ulNoChars = wcslen(szFullPath) + 1;
delete [] pel->szData;
pel->szData = new OLECHAR[ulNoChars];
if (NULL == pel->szData)
{
DebugMsg((DM_WARNING, TEXT("CBrowserPP::DoNewGPO failed to allocate memory for GPO path")));
goto Done;
}
hr = StringCchCopy(pel->szData, ulNoChars, szFullPath);
ASSERT(SUCCEEDED(hr));
}
if (m_dwPageType != PAGETYPE_ALL)
{
// If we're not on the "All" page then we need to create a link.
CreateLink(pel->szData, szObject);
}
// Add the entry to the list view
index = AddElement(pel, -1);
fSucceeded = index != -1;
// It's been added so now we need to make sure we don't delete it below
pel = NULL;
// Record that we got this far
fEdit = TRUE;
Done:
if (pel)
{
if (pel->szData)
{
delete [] pel->szData;
}
if (pel->szName)
{
delete [] pel->szName;
}
delete pel;
}
if (pGPO)
pGPO->Release();
if (fEdit)
{
// Now trigger an edit of the entry
SetFocus(m_hList);
ListView_EditLabel(m_hList, index);
}
if (szServerName)
LocalFree(szServerName);
if (szFullPath)
LocalFree(szFullPath);
if (szDomain)
delete [] szDomain;
if (szObject)
delete [] szObject;
return fSucceeded;
}
BOOL CBrowserPP::CreateLink(LPOLESTR szObject, LPOLESTR szContainer)
{
HRESULT hr = CreateGPOLink(szObject, szContainer, FALSE);
if (SUCCEEDED(hr))
{
return TRUE;
}
ReportError(m_hwndDlg, hr, IDS_FAILEDLINK);
return FALSE;
}
BOOL CBrowserPP::DeleteLink(LPOLESTR szObject, LPOLESTR szContainer)
{
HRESULT hr = DeleteGPOLink(szObject, szContainer);
if (SUCCEEDED(hr))
{
return TRUE;
}
ReportError(m_hwndDlg, hr, IDS_FAILEDUNLINK);
return FALSE;
}
BOOL CBrowserPP::DoRotateView()
{
DWORD dwStyle = GetWindowLong(m_hList, GWL_STYLE);
DWORD dw = dwStyle & LVS_TYPEMASK;
switch (dw)
{
case LVS_ICON:
dw = LVS_SMALLICON;
break;
case LVS_SMALLICON:
dw = LVS_LIST;
break;
case LVS_REPORT:
dw = LVS_ICON;
break;
case LVS_LIST:
default:
dw = LVS_REPORT;
break;
}
dwStyle -= dwStyle & LVS_TYPEMASK;
dwStyle += dw;
SetWindowLong(m_hList, GWL_STYLE, dwStyle);
return TRUE;
}
void CBrowserPP::OnDetails()
{
DWORD dwStyle = GetWindowLong(m_hList, GWL_STYLE);
dwStyle -= dwStyle & LVS_TYPEMASK;
SetWindowLong(m_hList, GWL_STYLE, dwStyle + LVS_REPORT);
}
void CBrowserPP::OnList()
{
DWORD dwStyle = GetWindowLong(m_hList, GWL_STYLE);
dwStyle -= dwStyle & LVS_TYPEMASK;
SetWindowLong(m_hList, GWL_STYLE, dwStyle + LVS_LIST);
}
void CBrowserPP::OnLargeicons()
{
DWORD dwStyle = GetWindowLong(m_hList, GWL_STYLE);
dwStyle -= dwStyle & LVS_TYPEMASK;
SetWindowLong(m_hList, GWL_STYLE, dwStyle + LVS_ICON);
}
void CBrowserPP::OnSmallicons()
{
DWORD dwStyle = GetWindowLong(m_hList, GWL_STYLE);
dwStyle -= dwStyle & LVS_TYPEMASK;
SetWindowLong(m_hList, GWL_STYLE, dwStyle + LVS_SMALLICON);
}
void CBrowserPP::OnContextMenu(LPARAM lParam)
{
int i = ListView_GetNextItem(m_hList, -1, LVNI_SELECTED);
RECT rc;
POINT pt;
pt.x = ((int)(short)LOWORD(lParam));
pt.y = ((int)(short)HIWORD(lParam));
GetWindowRect (GetDlgItem (m_hwndDlg, IDC_LIST1), &rc);
if (!PtInRect (&rc, pt))
{
if ((lParam == (LPARAM) -1) && (i >= 0))
{
rc.left = LVIR_SELECTBOUNDS;
SendMessage (m_hList, LVM_GETITEMRECT, i, (LPARAM) &rc);
pt.x = rc.left + 8;
pt.y = rc.top + ((rc.bottom - rc.top) / 2);
ClientToScreen (m_hList, &pt);
}
else
{
pt.x = rc.left + ((rc.right - rc.left) / 2);
pt.y = rc.top + ((rc.bottom - rc.top) / 2);
}
}
// get the popup menu
HMENU hPopup;
hPopup = LoadMenu(g_hInstance, MAKEINTRESOURCE(IDR_LISTMENU));
HMENU hSubMenu = GetSubMenu(hPopup, 0);
if (i >= 0)
{
// item selected
// figure out what type it is
LVITEM item;
memset(&item, 0, sizeof(item));
item.mask = LVIF_PARAM;
item.iItem = i;
ListView_GetItem(m_hList, &item);
MYLISTEL * pel = (MYLISTEL *)item.lParam;
// get rid of the view menu and separator
RemoveMenu(hSubMenu, 0, MF_BYPOSITION);
RemoveMenu(hSubMenu, 0, MF_BYPOSITION);
// get rid of the arrange and line-up items
RemoveMenu(hSubMenu, 0, MF_BYPOSITION);
RemoveMenu(hSubMenu, 0, MF_BYPOSITION);
RemoveMenu(hSubMenu, 0, MF_BYPOSITION);
// get rid of the "new" menu item
RemoveMenu(hSubMenu, ID_NEW, MF_BYCOMMAND);
switch (pel->nType)
{
case ITEMTYPE_GPO:
if (pel->bDisabled)
{
// disable edit, rename, delete
EnableMenuItem(hSubMenu, ID_EDIT, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
EnableMenuItem(hSubMenu, ID_RENAME, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
EnableMenuItem(hSubMenu, ID_DELETE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
}
break;
default:
case ITEMTYPE_FOREST:
case ITEMTYPE_SITE:
case ITEMTYPE_DOMAIN:
case ITEMTYPE_OU:
// remove the edit menu item and the separator
RemoveMenu(hSubMenu, ID_EDIT, MF_BYCOMMAND);
RemoveMenu(hSubMenu, 0, MF_BYPOSITION);
// disable rename, delete and properties
EnableMenuItem(hSubMenu, ID_RENAME, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
EnableMenuItem(hSubMenu, ID_DELETE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
EnableMenuItem(hSubMenu, ID_PROPERTIES, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
break;
}
}
else
{
// no item selected
// get rid of the edit menu item
RemoveMenu(hSubMenu, ID_EDIT, MF_BYCOMMAND);
// get rid of the delete and rename items
RemoveMenu(hSubMenu, ID_DELETE, MF_BYCOMMAND);
RemoveMenu(hSubMenu, ID_RENAME, MF_BYCOMMAND);
if (PAGETYPE_ALL != m_dwPageType)
{
if (m_pGBI->dwFlags & GPO_BROWSE_DISABLENEW)
{
// get rid of the "new" menu item
RemoveMenu(hSubMenu, ID_NEW, MF_BYCOMMAND);
RemoveMenu(hSubMenu, 4, MF_BYPOSITION);
}
}
RemoveMenu(hSubMenu, (GetMenuItemCount(hSubMenu) - 1), MF_BYPOSITION);
RemoveMenu(hSubMenu, (GetMenuItemCount(hSubMenu) - 1), MF_BYPOSITION);
// set view radio button
UINT ui = ID_LIST;
DWORD dw = GetWindowLong(m_hList, GWL_STYLE) & LVS_TYPEMASK;
if (dw == LVS_ICON || dw == LVS_SMALLICON)
{
// Auto-Arrange means something in these views so we need to enable it
EnableMenuItem(hSubMenu, ID_ARRANGE_AUTO, MF_BYCOMMAND | MF_ENABLED);
// also need to make sure it's set correctly
if (LVS_AUTOARRANGE == (GetWindowLong(m_hList, GWL_STYLE) & LVS_AUTOARRANGE))
CheckMenuItem(hSubMenu, ID_ARRANGE_AUTO, MF_BYCOMMAND | MF_CHECKED);
}
switch (dw)
{
case LVS_ICON:
ui = ID_LARGEICONS;
break;
case LVS_SMALLICON:
ui = ID_SMALLICONS;
break;
case LVS_REPORT:
ui = ID_DETAILS;
break;
case LVS_LIST:
default:
ui = ID_LIST;
break;
}
CheckMenuRadioItem(hSubMenu, ui, ui, ui, MF_BYCOMMAND);
}
TrackPopupMenu(hSubMenu,
TPM_LEFTALIGN,
pt.x, pt.y,
0,
m_hwndDlg,
NULL);
DestroyMenu(hPopup);
}
void CBrowserPP::OnArrangeAuto()
{
DWORD dwStyle = GetWindowLong(m_hList, GWL_STYLE);
if (LVS_AUTOARRANGE == (dwStyle & LVS_AUTOARRANGE))
SetWindowLong(m_hList, GWL_STYLE, dwStyle - LVS_AUTOARRANGE);
else
SetWindowLong(m_hList, GWL_STYLE, dwStyle + LVS_AUTOARRANGE);
}
int CALLBACK CompareName(LPARAM lParam1, LPARAM lParam2, LPARAM lParamsort)
{
MYLISTEL * pel1 = (MYLISTEL *)lParam1;
MYLISTEL * pel2 = (MYLISTEL *)lParam2;
return _wcsicmp(pel1->szName, pel2->szName);
}
int CALLBACK CompareType(LPARAM lParam1, LPARAM lParam2, LPARAM lParamsort)
{
MYLISTEL * pel1 = (MYLISTEL *)lParam1;
MYLISTEL * pel2 = (MYLISTEL *)lParam2;
return pel1->nType - pel2->nType;
}
void CBrowserPP::OnArrangeByname()
{
ListView_SortItems(m_hList, CompareName, 0);
}
void CBrowserPP::OnArrangeBytype()
{
ListView_SortItems(m_hList, CompareType, 0);
}
void CBrowserPP::OnDelete()
{
DeleteGPO();
}
void CBrowserPP::OnEdit()
{
INT i;
HRESULT hr;
LVITEM item;
MYLISTEL * pel;
LPTSTR lpDomainName;
LPOLESTR pszDomain;
i = ListView_GetNextItem(m_hList, -1, LVNI_SELECTED);
if (i >= 0)
{
memset(&item, 0, sizeof(item));
item.mask = LVIF_PARAM;
item.iItem = i;
ListView_GetItem(m_hList, &item);
pel = (MYLISTEL *)item.lParam;
if (pel->nType == ITEMTYPE_GPO)
{
//
// Get the friendly domain name
//
pszDomain = GetDomainFromLDAPPath(pel->szData);
if (!pszDomain)
{
DebugMsg((DM_WARNING, TEXT("CBrowserPP::OnEdit: Failed to get domain name")));
return;
}
//
// Convert LDAP to dot (DN) style
//
hr = ConvertToDotStyle (pszDomain, &lpDomainName);
delete [] pszDomain;
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("CGroupPolicyObject::CreatePropertyPages: Failed to convert domain name with 0x%x"), hr));
return;
}
//
// Check if the GPO is in the same domain as GPM is focused on
//
if (!lstrcmpi(lpDomainName, m_szDomainName))
{
SpawnGPE (pel->szData, GPHintUnknown, m_szServerName, m_hwndDlg);
}
else
{
SpawnGPE (pel->szData, GPHintUnknown, NULL, m_hwndDlg);
}
LocalFree (lpDomainName);
}
}
}
void CBrowserPP::OnNew()
{
DoNewGPO();
}
void CBrowserPP::OnProperties()
{
INT iIndex;
LVITEM item;
HRESULT hr;
LPGROUPPOLICYOBJECT pGPO;
HPROPSHEETPAGE *hPages;
UINT i, uPageCount;
PROPSHEETHEADER psh;
iIndex = ListView_GetNextItem(m_hList, -1, LVNI_ALL | LVNI_SELECTED);
if (iIndex >= 0)
{
memset(&item, 0, sizeof(item));
item.mask = LVIF_PARAM;
item.iItem = iIndex;
ListView_GetItem(m_hList, &item);
MYLISTEL * pel = (MYLISTEL *)item.lParam;
if (pel && pel->nType == ITEMTYPE_GPO)
{
hr = CoCreateInstance (CLSID_GroupPolicyObject, NULL,
CLSCTX_SERVER, IID_IGroupPolicyObject,
(void**)&pGPO);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("CBrowserPP::OnProperties: CoCreateInstance failed with 0x%x\r\n"), hr));
return;
}
//
// Open the requested object without mounting the registry
//
hr = pGPO->OpenDSGPO(pel->szData, 0);
if (hr == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED))
{
hr = pGPO->OpenDSGPO(pel->szData, GPO_OPEN_READ_ONLY);
}
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("CBrowserPP::OnProperties: Failed to open GPO object with 0x%x\r\n"), hr));
ReportError(m_hwndDlg, hr, IDS_FAILEDDS);
return;
}
//
// Ask the GPO for the property sheet pages
//
hr = pGPO->GetPropertySheetPages (&hPages, &uPageCount);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("CBrowserPP::OnProperties: Failed to query property sheet pages with 0x%x."), hr));
pGPO->Release();
return;
}
//
// Display the property sheet
//
ZeroMemory (&psh, sizeof(psh));
psh.dwSize = sizeof(psh);
psh.dwFlags = PSH_PROPTITLE;
psh.hwndParent = m_hwndDlg;
psh.hInstance = g_hInstance;
psh.pszCaption = pel->szName;
psh.nPages = uPageCount;
psh.phpage = hPages;
PropertySheet (&psh);
LocalFree (hPages);
pGPO->Release();
}
}
}
void CBrowserPP::OnRefresh()
{
switch (m_dwPageType)
{
case PAGETYPE_DOMAINS:
RefreshDomains();
break;
case PAGETYPE_SITES:
RefreshSites();
break;
default:
case PAGETYPE_ALL:
RefreshAll();
break;
}
SetButtonState();
}
void CBrowserPP::OnRename()
{
//
// alow the rename only if it is possible to rename
//
int i = ListView_GetNextItem(m_hList, -1, LVNI_SELECTED);
if (i >= 0)
{
// item selected
// figure out what type it is
LVITEM item;
memset(&item, 0, sizeof(item));
item.mask = LVIF_PARAM;
item.iItem = i;
ListView_GetItem(m_hList, &item);
MYLISTEL * pel = (MYLISTEL *)item.lParam;
if ((pel) && (pel->nType == ITEMTYPE_GPO)
&& (!(pel->bDisabled))) {
ListView_EditLabel(m_hList, ListView_GetNextItem(m_hList, -1, LVNI_SELECTED));
}
}
}
void CBrowserPP::OnTopLineupicons()
{
ListView_Arrange(m_hList, LVA_SNAPTOGRID);
}
void CBrowserPP::OnBeginlabeleditList(NMHDR* pNMHDR, LRESULT* pResult)
{
LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
// Return FALSE to enable editing, TRUE to disable it
MYLISTEL * pel = (MYLISTEL *)pDispInfo->item.lParam;
*pResult = (pel->nType == ITEMTYPE_GPO) ? FALSE : TRUE;
}
void CBrowserPP::OnEndlabeleditList(NMHDR* pNMHDR, LRESULT* pResult)
{
*pResult = FALSE;
LPGROUPPOLICYOBJECT pGPO = NULL;
HRESULT hr;
LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
if (NULL == pDispInfo->item.pszText)
{
// user cancelled edit
return;
}
if (TEXT('\0') == (*pDispInfo->item.pszText))
{
// user entered an empty string
return;
}
MYLISTEL * pel = (MYLISTEL *)pDispInfo->item.lParam;
if (0 ==wcscmp(pDispInfo->item.pszText, pel->szName))
{
// user didn't change anything
return;
}
LPWSTR sz = new WCHAR[wcslen(pDispInfo->item.pszText)+1];
if (NULL == sz)
{
*pResult = FALSE;
goto Done;
return;
}
hr = CoCreateInstance(CLSID_GroupPolicyObject, NULL,
CLSCTX_SERVER, IID_IGroupPolicyObject,
(void **)&pGPO);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("CoCreateInstance failed with 0x%x\r\n"), hr));
goto Done;
}
// open GPO object without opening registry data
hr = pGPO->OpenDSGPO(pel->szData, 0);
if (FAILED(hr))
{
ReportError(m_hwndDlg, hr, IDS_FAILEDDS);
DebugMsg((DM_WARNING, TEXT("OpenDSGPO failed with 0x%x\r\n"), hr));
goto Done;
}
// rename it
hr = pGPO->SetDisplayName(pDispInfo->item.pszText);
if (FAILED(hr))
{
ReportError(m_hwndDlg, hr, IDS_FAILEDSETNAME);
DebugMsg((DM_WARNING, TEXT("SetDisplayName failed with 0x%x\r\n"), hr));
goto Done;
}
// requery for the name
hr = pGPO->GetDisplayName(sz, (wcslen(pDispInfo->item.pszText)+1));
if (FAILED(hr))
{
ReportError(m_hwndDlg, hr, IDS_FAILEDSETNAME);
DebugMsg((DM_WARNING, TEXT("GetDisplayName failed with 0x%x\r\n"), hr));
goto Done;
}
delete [] pel->szName;
pel->szName = sz;
sz = NULL;
// return TRUE to accept the rename, FALSE to reject it
*pResult = TRUE;
PostMessage (m_hwndDlg, WM_REFRESHDISPLAY, (WPARAM) pDispInfo->item.iItem, 0);
Done:
if (sz)
{
delete [] sz;
}
if (pGPO)
{
pGPO->Release();
}
}
void CBrowserPP::OnBegindragList(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
*pResult = 0;
}
void CBrowserPP::OnDeleteitemList(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
MYLISTEL * pel = (MYLISTEL *)pNMListView->lParam;
if (pel)
{
if (pel->szName)
{
delete [] pel->szName;
}
if (pel->szData)
{
delete [] pel->szData;
}
delete pel;
}
*pResult = 0;
}
void CBrowserPP::OnDoubleclickList(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
if (pNMListView->iItem >= 0)
{
// item selected
PropSheet_PressButton(GetParent(m_hwndDlg), PSBTN_OK);
}
*pResult = 0;
}
void CBrowserPP::OnColumnclickList(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
switch (pNMListView->iSubItem)
{
case 0:
ListView_SortItems(m_hList, CompareName, 0);
break;
case 1:
default:
ListView_SortItems(m_hList, CompareType, 0);
break;
}
*pResult = 0;
}
void CBrowserPP::OnKeyDownList(NMHDR * pNMHDR, LRESULT * pResult)
{
LV_KEYDOWN * pnkd = (LV_KEYDOWN *)pNMHDR;
switch (pnkd->wVKey)
{
case VK_F5:
OnRefresh();
break;
case VK_F2:
OnRename();
break;
case VK_DELETE:
OnDelete();
break;
case VK_BACK:
DoBackButton();
break;
case VK_RETURN:
OnProperties();
break;
default:
break;
}
}
void CBrowserPP::OnItemChanged(NMHDR * pNMHDR, LRESULT * pResult)
{
SetButtonState();
}
void CBrowserPP::TrimComboBox()
{
LOOKDATA * pdataSelected = NULL;
int iCount;
// first check to see if something is selected
int iIndex = (int)SendMessage (m_hCombo, CB_GETCURSEL, 0, 0);
if (iIndex != CB_ERR)
{
// something's selected, get a pointer to it's data
pdataSelected = (LOOKDATA *) SendMessage (m_hCombo, CB_GETITEMDATA, iIndex, 0);
// check if the user selected the same thing again
if (m_pPrevSel && (m_pPrevSel == pdataSelected))
{
return;
}
// if it has a parent then enable the back button
SendMessage(m_toolbar, TB_ENABLEBUTTON, (WPARAM) ID_BACKBUTTON, (LPARAM)MAKELONG(NULL != pdataSelected->pParent, 0));
}
// If the child of the selected object is an OU then delete all of it's children
// otherwise delete ALL OUs from the list.
if (pdataSelected)
{
if (pdataSelected->pChild)
{
if (ITEMTYPE_OU == pdataSelected->pChild->nType)
{
// delete all of its children
goto DeleteChildren;
}
}
}
iCount = (int)SendMessage(m_hCombo, CB_GETCOUNT, 0, 0);
iIndex = 0;
while (iIndex < iCount)
{
// find the first entry that has an OU for a child.
pdataSelected = (LOOKDATA *) SendMessage (m_hCombo, CB_GETITEMDATA, iIndex, 0);
if (pdataSelected)
{
if (pdataSelected->pChild)
{
if (ITEMTYPE_OU == pdataSelected->pChild->nType)
{
DeleteChildren:
LOOKDATA * pChild = pdataSelected->pChild;
pdataSelected->pChild = pChild->pSibling;
while (pChild)
{
iIndex = (int)SendMessage(m_hCombo, CB_FINDSTRING, iIndex, (LPARAM)(LPCTSTR*)pChild);
if (iIndex != CB_ERR)
{
pChild = pChild->pChild;
SendMessage(m_hCombo, CB_DELETESTRING, iIndex, 0);
}
else
{
pChild = NULL;
}
}
return;
}
}
}
iIndex++;
}
}
void CBrowserPP::OnComboChange()
{
switch (m_dwPageType)
{
case PAGETYPE_DOMAINS:
{
TrimComboBox();
}
// fall through to refresh the list view
case PAGETYPE_SITES:
case PAGETYPE_ALL:
default:
OnRefresh();
break;
}
}
BOOL CBrowserPP::OnSetActive()
{
*m_ppActive = this;
OnRefresh();
return TRUE;
}
BOOL CBrowserPP::OnApply()
{
if (*m_ppActive == (void *) this)
{
// perform the proper task on the selected item
int i = ListView_GetNextItem(m_hList, -1, LVNI_SELECTED);
if (i >= 0)
{
LVITEM item;
memset(&item, 0, sizeof(item));
item.mask = LVIF_PARAM;
item.iItem = i;
ListView_GetItem(m_hList, &item);
MYLISTEL * pel = (MYLISTEL *)item.lParam;
switch (pel->nType)
{
case ITEMTYPE_GPO:
m_pGBI->gpoType = GPOTypeDS;
wcsncpy(m_pGBI->lpDSPath, pel->szData, m_pGBI->dwDSPathSize);
if (m_pGBI->lpName)
{
wcsncpy(m_pGBI->lpName, pel->szName, m_pGBI->dwNameSize);
}
m_pGBI->gpoHint = GPHintUnknown;
break;
default:
case ITEMTYPE_FOREST:
case ITEMTYPE_SITE:
case ITEMTYPE_DOMAIN:
// change the focus
{
LOOKDATA * pdataSelected = NULL;
// first make sure something is selected
int iIndex = (int)SendMessage (m_hCombo, CB_GETCURSEL, 0, 0);
if (iIndex != CB_ERR)
{
// something's selected, get a pointer to it's data
pdataSelected = (LOOKDATA *) SendMessage (m_hCombo, CB_GETITEMDATA, iIndex, 0);
if (pdataSelected)
{
// Now walk its children until we find a match
pdataSelected = pdataSelected->pChild;
while (pdataSelected)
{
if (0 == wcscmp(pdataSelected->szData, pel->szData))
{
iIndex = (int)SendMessage(m_hCombo, CB_FINDSTRING, iIndex, (LPARAM) (LPCTSTR)pdataSelected);
if (iIndex != CB_ERR)
{
SendMessage(m_hCombo, CB_SETCURSEL, iIndex, 0);
// Enable the back-button
SendMessage(m_toolbar, TB_ENABLEBUTTON, (WPARAM) ID_BACKBUTTON, (LPARAM) MAKELONG(TRUE, 0));
}
break;
}
pdataSelected = pdataSelected->pSibling;
}
}
}
}
OnRefresh();
return FALSE; // don't allow propsheet to close
case ITEMTYPE_OU:
// Add the new object to combobox and change the focus.
{
LOOKDATA * pdataSelected = NULL;
// first make sure something is selected
int iIndex = (int)SendMessage (m_hCombo, CB_GETCURSEL, 0, 0);
if (iIndex != CB_ERR)
{
// something's selected, get a pointer to it's data
pdataSelected = (LOOKDATA *) SendMessage (m_hCombo, CB_GETITEMDATA, iIndex, 0);
if (pdataSelected)
{
LOOKDATA * pNew = new LOOKDATA;
if (pNew)
{
ULONG ulNoCharsName = wcslen(pel->szName)+1;
pNew->szName = new WCHAR[ulNoCharsName];
if (pNew->szName)
{
ULONG ulNoCharsData = wcslen(pel->szData)+1;
pNew->szData = new WCHAR[ulNoCharsData];
if (pNew->szData)
{
HRESULT hr;
hr = StringCchCopy(pNew->szName, ulNoCharsName, pel->szName);
ASSERT(SUCCEEDED(hr));
hr = StringCchCopy(pNew->szData, ulNoCharsData, pel->szData);
ASSERT(SUCCEEDED(hr));
pNew->nIndent = pdataSelected->nIndent + 1;
pNew->nType = ITEMTYPE_OU;
pNew->pParent = pdataSelected;
pNew->pSibling = pdataSelected->pChild;
pNew->pChild = NULL;
pdataSelected ->pChild = pNew;
SendMessage(m_hCombo, CB_INSERTSTRING, (WPARAM) iIndex + 1, (LPARAM) (LPCTSTR) pNew);
SendMessage(m_hCombo, CB_SETCURSEL, iIndex + 1, 0);
// Enable the back-button
SendMessage(m_toolbar, TB_ENABLEBUTTON, (WPARAM) ID_BACKBUTTON, (LPARAM) MAKELONG(TRUE, 0));
}
else
{
delete [] pNew->szName;
delete pNew;
}
}
else
{
delete pNew;
}
}
}
}
}
OnRefresh();
return FALSE; // don't allow propsheet to close
}
return TRUE;
}
else
return FALSE; // don't allow propsheet to close
}
return TRUE;
}
BOOL CBrowserPP::DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
BOOL fReturn = FALSE;
m_hwndDlg = hwndDlg;
switch (uMsg)
{
case WM_INITDIALOG:
{
return OnInitDialog();
}
break;
case WM_NOTIFY:
{
LPNMHDR pnmh = (LPNMHDR) lParam;
LRESULT lResult = 0;
switch (pnmh->code)
{
case NM_KEYDOWN:
{
LPNMKEY pnkd = (LPNMKEY)pnmh;
if (VK_F5 == pnkd->nVKey)
{
OnRefresh();
}
}
break;
case PSN_SETACTIVE:
OnSetActive();
break;
case PSN_APPLY:
lResult = OnApply() ? PSNRET_NOERROR : PSNRET_INVALID_NOCHANGEPAGE;
fReturn = TRUE;
break;
case NM_DBLCLK:
if (IDC_LIST1 == wParam)
{
OnDoubleclickList(pnmh, &lResult);
fReturn = TRUE;
}
break;
case LVN_BEGINLABELEDIT:
OnBeginlabeleditList(pnmh, &lResult);
fReturn = TRUE;
break;
case LVN_ENDLABELEDIT:
OnEndlabeleditList(pnmh, &lResult);
fReturn = TRUE;
break;
case LVN_BEGINDRAG:
OnBegindragList(pnmh, &lResult);
fReturn = TRUE;
break;
case LVN_DELETEITEM:
OnDeleteitemList(pnmh, &lResult);
fReturn = TRUE;
break;
case LVN_COLUMNCLICK:
OnColumnclickList(pnmh, &lResult);
fReturn = TRUE;
break;
case LVN_KEYDOWN:
OnKeyDownList(pnmh, &lResult);
break;
case LVN_ITEMCHANGED:
OnItemChanged(pnmh, &lResult);
break;
case TBN_DROPDOWN:
{
RECT r;
SendMessage(m_toolbar, TB_GETRECT, ((TBNOTIFY *)lParam)->iItem, (LPARAM)&r);
MapWindowPoints(m_toolbar, NULL, (POINT *)&r, 2);
HMENU hPopup;
hPopup = LoadMenu(g_hInstance, MAKEINTRESOURCE(IDR_LISTMENU));
if ( ! hPopup )
{
break;
}
UINT ui = ID_LIST;
DWORD dw = GetWindowLong(m_hList, GWL_STYLE) & LVS_TYPEMASK;
switch (dw)
{
case LVS_ICON:
ui = ID_LARGEICONS;
break;
case LVS_SMALLICON:
ui = ID_SMALLICONS;
break;
case LVS_REPORT:
ui = ID_DETAILS;
break;
case LVS_LIST:
default:
ui = ID_LIST;
break;
}
HMENU hSubMenu = GetSubMenu(GetSubMenu(hPopup, 0), 0);
CheckMenuRadioItem(hSubMenu, ui, ui, ui, MF_BYCOMMAND);
TrackPopupMenu(hSubMenu,
TPM_LEFTALIGN,
r.left, r.bottom,
0,
m_hwndDlg,
&r);
fReturn = TRUE;
DestroyMenu(hPopup);
break;
}
break;
case TTN_GETDISPINFO:
{
LPNMTTDISPINFO pDI = (LPNMTTDISPINFO) lParam;
UINT id = 0;
if (pDI->hdr.idFrom == ID_BACKBUTTON)
id = IDS_TOOLTIP_BACK;
else if (pDI->hdr.idFrom == ID_NEWFOLDER)
id = IDS_TOOLTIP_NEW;
else if (pDI->hdr.idFrom == ID_ROTATEVIEW)
id = IDS_TOOLTIP_ROTATE;
if (id)
LoadString (g_hInstance, id, pDI->szText, 80);
else
pDI->szText[0] = TEXT('\0');
fReturn = TRUE;
}
break;
default:
break;
}
SetWindowLongPtr(m_hwndDlg, DWLP_MSGRESULT, lResult);
}
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_COMBO1:
if (CBN_SELCHANGE == HIWORD(wParam))
{
OnComboChange();
}
break;
case ID_BACKBUTTON:
return DoBackButton();
case ID_NEWFOLDER:
return DoNewGPO();
case ID_ROTATEVIEW:
return DoRotateView();
case ID_DETAILS:
OnDetails();
fReturn = TRUE;
break;
case ID_LIST:
OnList();
fReturn = TRUE;
break;
case ID_LARGEICONS:
OnLargeicons();
fReturn = TRUE;
break;
case ID_SMALLICONS:
OnSmallicons();
fReturn = TRUE;
break;
case ID_ARRANGE_AUTO:
OnArrangeAuto();
fReturn = TRUE;
break;
case ID_ARRANGE_BYNAME:
OnArrangeByname();
fReturn = TRUE;
break;
case ID_ARRANGE_BYTYPE:
OnArrangeBytype();
fReturn = TRUE;
break;
case ID_DELETE:
OnDelete();
fReturn = TRUE;
break;
case ID_EDIT:
OnEdit();
fReturn = TRUE;
break;
case ID_NEW:
OnNew();
fReturn = TRUE;
break;
case ID_PROPERTIES:
OnProperties();
fReturn = TRUE;
break;
case ID_REFRESH:
OnRefresh();
fReturn = TRUE;
break;
case ID_RENAME:
OnRename();
fReturn = TRUE;
break;
case ID_TOP_LINEUPICONS:
OnTopLineupicons();
fReturn = TRUE;
break;
default:
break;
}
break;
case WM_CONTEXTMENU:
fReturn = TRUE;
if ((HWND)wParam != m_toolbar)
{
if (GetDlgItem(hwndDlg, IDC_LIST1) == (HWND)wParam)
{
OnContextMenu(lParam);
}
else
{
// right mouse click
switch (m_dwPageType)
{
case PAGETYPE_DOMAINS:
WinHelp((HWND) wParam, HELP_FILE, HELP_CONTEXTMENU,
(ULONG_PTR) (LPSTR) aBrowserDomainHelpIds);
break;
case PAGETYPE_SITES:
WinHelp((HWND) wParam, HELP_FILE, HELP_CONTEXTMENU,
(ULONG_PTR) (LPSTR) aBrowserSiteHelpIds);
break;
case PAGETYPE_ALL:
WinHelp((HWND) wParam, HELP_FILE, HELP_CONTEXTMENU,
(ULONG_PTR) (LPSTR) aBrowserAllHelpIds);
break;
}
}
}
break;
case WM_HELP:
// F1 help
if (((LPHELPINFO) lParam)->iCtrlId != IDR_TOOLBAR1)
{
switch (m_dwPageType)
{
case PAGETYPE_DOMAINS:
WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, HELP_FILE, HELP_WM_HELP,
(ULONG_PTR) (LPSTR) aBrowserDomainHelpIds);
break;
case PAGETYPE_SITES:
WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, HELP_FILE, HELP_WM_HELP,
(ULONG_PTR) (LPSTR) aBrowserSiteHelpIds);
break;
case PAGETYPE_ALL:
WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, HELP_FILE, HELP_WM_HELP,
(ULONG_PTR) (LPSTR) aBrowserAllHelpIds);
break;
}
}
fReturn = TRUE;
break;
case WM_DRAWITEM:
if (IDC_COMBO1 == wParam)
{
DrawItem((LPDRAWITEMSTRUCT)lParam);
fReturn = TRUE;
}
break;
case WM_MEASUREITEM:
if (IDC_COMBO1 == wParam)
{
MeasureItem((LPMEASUREITEMSTRUCT)lParam);
fReturn = TRUE;
}
break;
case WM_COMPAREITEM:
if (IDC_COMBO1 == wParam)
{
int iReturn = CompareItem((LPCOMPAREITEMSTRUCT)lParam);
SetWindowLongPtr(m_hwndDlg, DWLP_MSGRESULT, iReturn);
fReturn = TRUE;
}
break;
case WM_DELETEITEM:
if (IDC_COMBO1 == wParam)
{
DeleteItem((LPDELETEITEMSTRUCT)lParam);
fReturn = TRUE;
}
break;
case WM_REFRESHDISPLAY:
{
MYLISTEL * pel;
LVITEM item;
ZeroMemory (&item, sizeof(item));
item.mask = LVIF_PARAM;
item.iItem = (INT) wParam;
if (ListView_GetItem(m_hList, &item))
{
pel = (MYLISTEL *)item.lParam;
ListView_SetItemText(m_hList, (INT)wParam, 0, pel->szName);
}
}
break;
default:
break;
}
return fReturn;
}
void CBrowserPP::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
// DRAWITEMSTRUCT:
// UINT CtlType // type of the control
// UINT CtlID; // ID of the control
// UINT itemID; // index of the item
// UINT itemAction;
// UINT itemState;
// HWND hwndItem;
// HDC hDC;
// RECT rcItem;
// DWORD itemData; // user-defined data
if (-1 != lpDrawItemStruct->itemID)
{
LOOKDATA * pdata = (LOOKDATA *)lpDrawItemStruct->itemData;
POINT pt;
INT iIndex;
if (pdata->nType == ITEMTYPE_FOREST)
{
iIndex = 10;
}
else if (pdata->nType == ITEMTYPE_SITE)
{
iIndex = 6;
}
else if (pdata->nType == ITEMTYPE_DOMAIN)
{
iIndex = 7;
}
else
{
iIndex = 0;
}
pt.x = lpDrawItemStruct->rcItem.left;
BOOL fSelected = ODS_SELECTED == (ODS_SELECTED & lpDrawItemStruct->itemState);
BOOL fComboBoxEdit = ODS_COMBOBOXEDIT != (ODS_COMBOBOXEDIT & lpDrawItemStruct->itemState);
if (fComboBoxEdit)
pt.x += (INDENT * pdata->nIndent);
pt.y = lpDrawItemStruct->rcItem.top;
ImageList_Draw(m_ilSmall, iIndex, lpDrawItemStruct->hDC, pt.x, pt.y, fSelected ? ILD_SELECTED : ILD_NORMAL);
SIZE size;
GetTextExtentPoint32(lpDrawItemStruct->hDC, pdata->szName, wcslen(pdata->szName), &size);
COLORREF crBk;
COLORREF crText;
if (fSelected)
{
crBk = GetBkColor(lpDrawItemStruct->hDC);
crText = GetTextColor(lpDrawItemStruct->hDC);
SetBkColor(lpDrawItemStruct->hDC, GetSysColor(COLOR_HIGHLIGHT));
SetTextColor(lpDrawItemStruct->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
}
// NOTE, SMALLICONSIZE + 1 is used here to ensure it rounds UP
// instead of down when centering the text. (It looks better this
// way.)
// Adding 18 to the x coord spaces us past the icon.
ExtTextOut(lpDrawItemStruct->hDC, pt.x + (SMALLICONSIZE + 2), pt.y + (((SMALLICONSIZE + 1) - size.cy) / 2), ETO_CLIPPED, &lpDrawItemStruct->rcItem, pdata->szName, wcslen(pdata->szName), NULL);
if (fSelected)
{
SetBkColor(lpDrawItemStruct->hDC, crBk);
SetTextColor(lpDrawItemStruct->hDC, crText);
}
}
}
void CBrowserPP::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
// MEASUREITEMSTRUCT:
// UINT CtlType // type of the control
// UINT CtlID; // ID of the control
// UINT itemID; // index of the item
// UINT itemWidth; // width of item in pixels
// UINT itemHeight; // height of item in pixels
// DWORD itemData; // user-defined data
lpMeasureItemStruct->itemHeight = SMALLICONSIZE;
}
int CBrowserPP::CompareItem(LPCOMPAREITEMSTRUCT lpCompareItemStruct)
{
// COMPAREITEMSTRUCT:
// UINT CtlType // type of the control
// UINT CtlID; // ID of the control
// HWND hwndItem; // handle of the control
// UINT itemID; // index of the item
// DWORD itemData1; // user-defined data
// UINT itemID2; // index of the second item
// DWORD itemData2; // user-defined data
// I'm not doing any sorting.
return 0;
}
void CBrowserPP::DeleteItem(LPDELETEITEMSTRUCT lpDeleteItemStruct)
{
LOOKDATA * pdata = (LOOKDATA *)lpDeleteItemStruct->itemData;
if (NULL != pdata)
{
if (NULL != pdata->szName)
{
delete [] pdata->szName;
}
if (NULL != pdata->szData)
{
delete [] pdata->szData;
}
delete pdata;
}
}
LPTSTR CBrowserPP::GetFullPath (LPTSTR lpPath, HWND hParent)
{
LPTSTR lpFullPath = NULL, lpDomainName = NULL;
LPTSTR lpGPDCName;
LPOLESTR pszDomain;
HRESULT hr;
//
// Get the friendly domain name
//
pszDomain = GetDomainFromLDAPPath(lpPath);
if (!pszDomain)
{
DebugMsg((DM_WARNING, TEXT("CBrowserPP::GetFullPath: Failed to get domain name")));
return NULL;
}
//
// Convert LDAP to dot (DN) style
//
hr = ConvertToDotStyle (pszDomain, &lpDomainName);
delete [] pszDomain;
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("CBrowserPP::GetFullPath: Failed to convert domain name with 0x%x"), hr));
return NULL;
}
if (!lstrcmpi(lpDomainName, m_szDomainName))
{
//
// Make the full path
//
lpFullPath = MakeFullPath (lpPath, m_szServerName);
if (!lpFullPath)
{
DebugMsg((DM_WARNING, TEXT("CBrowserPP::GetFullPath: Failed to build new DS object path")));
goto Exit;
}
}
else
{
//
// Get the GPO DC for this domain
//
lpGPDCName = GetDCName (lpDomainName, NULL, hParent, TRUE, 0);
if (!lpGPDCName)
{
DebugMsg((DM_WARNING, TEXT("CBrowserPP::GetFullPath: Failed to get DC name for %s"),
lpDomainName));
goto Exit;
}
//
// Make the full path
//
lpFullPath = MakeFullPath (lpPath, lpGPDCName);
LocalFree (lpGPDCName);
if (!lpFullPath)
{
DebugMsg((DM_WARNING, TEXT("CBrowserPP::GetFullPath: Failed to build new DS object path")));
goto Exit;
}
}
Exit:
if (lpDomainName)
{
LocalFree (lpDomainName);
}
return lpFullPath;
}