Events
May 19, 6 PM - May 23, 12 AM
Calling all developers, creators, and AI innovators to join us in Seattle @Microsoft Build May 19-22.
Register todayThis browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
The following code example can be used to implement an Active Directory property sheet extension.
The following C++ code example can be used to implement the IShellExtInit methods.
/**************************************************************************
CPropSheetExt::Initialize()
**************************************************************************/
STDMETHODIMP CPropSheetExt::Initialize( LPCITEMIDLIST pidlFolder,
IDataObject *pDataObj,
HKEY hKeyProgId)
{
STGMEDIUM stm;
FORMATETC fe;
HRESULT hr = S_OK;
if(NULL == pDataObj)
{
return E_INVALIDARG;
}
hr = pDataObj->QueryInterface(IID_IDataObject, (LPVOID*)&m_pdo);
if(FAILED(hr))
{
return hr;
}
fe.cfFormat = RegisterClipboardFormat(CFSTR_DSOBJECTNAMES);
fe.ptd = NULL;
fe.dwAspect = DVASPECT_CONTENT;
fe.lindex = -1;
fe.tymed = TYMED_HGLOBAL;
hr = m_pdo->GetData(&fe, &stm);
if(SUCCEEDED(hr))
{
LPDSOBJECTNAMES pdson = (LPDSOBJECTNAMES)GlobalLock(stm.hGlobal);
if(pdson)
{
LPWSTR pwszName = (LPWSTR)((LPBYTE)pdson + pdson->aObjects[0].offsetName);
m_pwszADsPath = (LPWSTR)GlobalAlloc(GPTR, (lstrlenW(pwszName) + 1) * sizeof(WCHAR));
if(m_pwszADsPath)
{
wcscpy_s(m_pwszADsPath, pwszName);
}
LPWSTR pwszClass = (LPWSTR)((LPBYTE)pdson + pdson->aObjects[0].offsetClass);
pwszClass = NULL;
GlobalUnlock(stm.hGlobal);
}
ReleaseStgMedium(&stm);
}
m_hwndNotifyObj = CreateADsNotificationObject(pDataObj);
if(m_hwndNotifyObj)
{
ADSPROPINITPARAMS InitParams;
hr = GetADsPageInfo(m_hwndNotifyObj, &InitParams);
if(SUCCEEDED(hr))
{
if(InitParams.pDsObj)
{
hr = InitParams.pDsObj->QueryInterface( IID_IDirectoryObject,
(LPVOID*) & m_pDirObj);
}
}
}
fe.cfFormat = RegisterClipboardFormat(CFSTR_DS_DISPLAY_SPEC_OPTIONS);
fe.ptd = NULL;
fe.dwAspect = DVASPECT_CONTENT;
fe.lindex = -1;
fe.tymed = TYMED_HGLOBAL;
hr = pDataObj->GetData(&fe, &stm);
if(SUCCEEDED(hr))
{
PDSDISPLAYSPECOPTIONS pdso;
pdso = (PDSDISPLAYSPECOPTIONS)GlobalLock(stm.hGlobal);
if(pdso)
{
DWORD dwBytes = GlobalSize(stm.hGlobal);
m_pDispSpecOpts = (PDSDISPLAYSPECOPTIONS)GlobalAlloc(GPTR, dwBytes);
if(m_pDispSpecOpts)
{
CopyMemory(m_pDispSpecOpts, pdso, dwBytes);
}
GlobalUnlock(stm.hGlobal);
}
ReleaseStgMedium(&stm);
}
return hr;
}
The following C++ code example can be used to implement the IShellPropSheetExt methods.
/**************************************************************************
CPropSheetExt::AddPages()
**************************************************************************/
STDMETHODIMP CPropSheetExt::AddPages( LPFNADDPROPSHEETPAGE pfnAddPage,
LPARAM lParam)
{
PROPSHEETPAGE psp;
HPROPSHEETPAGE hPage;
psp.dwSize = sizeof(psp);
psp.dwFlags = PSP_USETITLE | PSP_USECALLBACK;
psp.hInstance = g_hInst;
psp.pszTemplate = MAKEINTRESOURCE(IDD_PAGEDLG);
psp.hIcon = 0;
psp.pszTitle = g_szPageTitle;
psp.pfnDlgProc = (DLGPROC)PageDlgProc;
psp.pcRefParent = NULL;
psp.pfnCallback = PageCallbackProc;
//pass the object pointer to the dialog box
psp.lParam = (LPARAM)this;
hPage = CreatePropertySheetPage(&psp);
if(hPage)
{
if(pfnAddPage(hPage, lParam))
{
/*
Maintain this object until the page is released in
PageCallbackProc.
*/
this->AddRef();
return S_OK;
}
else
{
DestroyPropertySheetPage(hPage);
}
}
else
{
return E_OUTOFMEMORY;
}
return E_FAIL;
}
/**************************************************************************
CPropSheetExt::ReplacePage()
**************************************************************************/
STDMETHODIMP CPropSheetExt::ReplacePage( UINT uPageID,
LPFNADDPROPSHEETPAGE lpfnAddPage,
LPARAM lParam)
{
return E_NOTIMPL;
}
The following C++ code example can be used to implement the utility methods and functions used in the previous code example.
HWND CreateADsNotificationObject(IDataObject *pDataObject)
{
STGMEDIUM stm;
FORMATETC fe;
HRESULT hr;
HWND hwndNotifyObject = NULL;
/*
The "DsAdminMultiSelectClipFormat" clipboard format is supported by the
data object if the Active Directory Users and Computers snap-in supports
multi-selection property sheets.
*/
fe.cfFormat = RegisterClipboardFormat(TEXT("DsAdminMultiSelectClipFormat"));
fe.ptd = NULL;
fe.dwAspect = DVASPECT_CONTENT;
fe.lindex = -1;
fe.tymed = TYMED_HGLOBAL;
hr = pDataObject->GetData(&fe, &stm);
if (SUCCEEDED(hr))
{
PWSTR pwzUniqueID = (LPWSTR)GlobalLock(stm.hGlobal);
if (pwzUniqueID)
{
hr = ADsPropCreateNotifyObj(pDataObject, pwzUniqueID, &hwndNotifyObject);
GlobalUnlock(stm.hGlobal);
}
ReleaseStgMedium(&stm);
}
else
{
fe.cfFormat = RegisterClipboardFormat(CFSTR_DSOBJECTNAMES);
fe.ptd = NULL;
fe.dwAspect = DVASPECT_CONTENT;
fe.lindex = -1;
fe.tymed = TYMED_HGLOBAL;
hr = pDataObject->GetData(&fe, &stm);
if(SUCCEEDED(hr))
{
LPDSOBJECTNAMES pdson = (LPDSOBJECTNAMES)GlobalLock(stm.hGlobal);
if(pdson)
{
LPWSTR pwszName = (LPWSTR)((LPBYTE)pdson + pdson->aObjects[0].offsetName);
hr = ADsPropCreateNotifyObj(pDataObject, pwszName, &hwndNotifyObject);
GlobalUnlock(stm.hGlobal);
}
ReleaseStgMedium(&stm);
}
}
return hwndNotifyObject;
}
/**************************************************************************
GetADsPageInfo()
**************************************************************************/
HRESULT GetADsPageInfo(HWND hwndNotifyObject, ADSPROPINITPARAMS *pip)
{
if(!IsWindow(hwndNotifyObject))
{
return E_INVALIDARG;
}
ADSPROPINITPARAMS InitParams;
InitParams.dwSize = sizeof(ADSPROPINITPARAMS);
if(ADsPropGetInitInfo(hwndNotifyObject, &InitParams))
{
*pip = InitParams;
return InitParams.hr;
}
return E_FAIL;
}
/**************************************************************************
CPropSheetExt::PageDlgProc
**************************************************************************/
#define THIS_POINTER_PROP TEXT("ThisPointerProperty")
BOOL CALLBACK CPropSheetExt::PageDlgProc( HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
// Get the object pointer.
CPropSheetExt *pExt = (CPropSheetExt*)GetProp(hWnd, THIS_POINTER_PROP);
switch(uMsg)
{
case WM_INITDIALOG:
{
/*
Get the pointer to the object. This is contained in the LPARAM of
the PROPSHEETPAGE structure.
*/
LPPROPSHEETPAGE pPage = (LPPROPSHEETPAGE)lParam;
if(pPage)
{
pExt = (CPropSheetExt*)pPage->lParam;
if(pExt)
{
// Set the page window handle in the object.
pExt->m_hwndPage = hWnd;
// Store the object pointer with this particular page dialog.
SetProp(hWnd, THIS_POINTER_PROP, (HANDLE)pExt);
ADsPropSetHwnd(pExt->m_hwndNotifyObj, hWnd, g_szPageTitle);
// Forward the message to the message handler.
return pExt->OnInitDialog(wParam, lParam);
}
}
}
break;
case WM_NOTIFY:
if(pExt)
{
// Forward the message to the message handler.
return pExt->OnNotify(wParam, lParam);
}
break;
case WM_COMMAND:
if(pExt)
{
// Forward the message to the message handler.
return pExt->OnCommand(wParam, lParam);
}
return FALSE;
case WM_DESTROY:
if(pExt)
{
// Forward the message to the message handler.
pExt->OnDestroy();
}
// Remove the property from the page.
RemoveProp(hWnd, THIS_POINTER_PROP);
break;
}
return FALSE;
}
/**************************************************************************
CPropSheetExt::PageCallbackProc()
This function is called when the page is created and released. This is
even called if the page is never actually displayed.
**************************************************************************/
UINT CALLBACK CPropSheetExt::PageCallbackProc( HWND hWnd,
UINT uMsg,
LPPROPSHEETPAGE ppsp)
{
switch(uMsg)
{
case PSPCB_CREATE:
// Must return TRUE to create the page.
return TRUE;
case PSPCB_RELEASE:
{
/*
Release the object. This is called even if the page dialog was
never actually created.
*/
CPropSheetExt *pPropSheetExt = (CPropSheetExt*)ppsp->lParam;
if(pPropSheetExt)
{
if(IsWindow(pPropSheetExt->m_hwndNotifyObj))
{
SendMessage(pPropSheetExt->m_hwndNotifyObj,
WM_ADSPROP_NOTIFY_EXIT,
0,
0);
pPropSheetExt->m_hwndNotifyObj = NULL;
}
pPropSheetExt->Release();
}
}
break;
}
return FALSE;
}
Events
May 19, 6 PM - May 23, 12 AM
Calling all developers, creators, and AI innovators to join us in Seattle @Microsoft Build May 19-22.
Register today