//+-------------------------------------------------------------------------- // // 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; }