|
|
#include "pch.h"
#pragma hdrstop
/*-----------------------------------------------------------------------------
/ Helper functions used by all /----------------------------------------------------------------------------*/
//
// Given a cache entry return a BOOL indicating if the class is really a container
// or not, we find this from both the schema and the display specifier.
//
BOOL _IsClassContainer(LPCLASSCACHEENTRY pClassCacheEntry, BOOL fIgnoreTreatAsLeaf) { BOOL fClassIsContainer = FALSE;
TraceEnter(TRACE_CACHE, "_IsClassContainer");
// default to the treat as leaf flag, note that this is always
// valid as it defaults to the schema value if it is not defined
// in the display specifier.
Trace(TEXT("fIsContainer is %scached and is %d"), pClassCacheEntry->dwCached & CLASSCACHE_CONTAINER ? TEXT(""):TEXT("not "), pClassCacheEntry->fIsContainer);
Trace(TEXT("fTreatAsLeaf is %scached and is %d"), pClassCacheEntry->dwCached & CLASSCACHE_TREATASLEAF ? TEXT(""):TEXT("not "), pClassCacheEntry->fTreatAsLeaf);
if ( !(pClassCacheEntry->dwCached & (CLASSCACHE_CONTAINER|CLASSCACHE_TREATASLEAF)) ) { TraceMsg("Neither container or treat as leaf is cached, therefore returning"); fClassIsContainer = TRUE; goto exit_gracefully; }
if ( fIgnoreTreatAsLeaf ) { if ( !(pClassCacheEntry->dwCached & CLASSCACHE_CONTAINER) ) { TraceMsg("Object doesn't have the container flag cached"); goto exit_gracefully; }
fClassIsContainer = pClassCacheEntry->fIsContainer; goto exit_gracefully; }
if ( !(pClassCacheEntry->dwCached & CLASSCACHE_TREATASLEAF) ) { if ( !(pClassCacheEntry->dwCached & CLASSCACHE_CONTAINER) ) { TraceMsg("Object doesn't have the treat as leaf flag cached"); goto exit_gracefully; }
fClassIsContainer = pClassCacheEntry->fIsContainer; goto exit_gracefully; }
fClassIsContainer = pClassCacheEntry->fTreatAsLeaf;
exit_gracefully:
TraceLeaveValue(fClassIsContainer); }
/*-----------------------------------------------------------------------------
/ COM API's exposed for accessing display specifiers. /----------------------------------------------------------------------------*/
class CDsDisplaySpecifier : public IDsDisplaySpecifier { private: LONG _cRef; DWORD _dwFlags; LPWSTR _pszServer; LPWSTR _pszUserName; LPWSTR _pszPassword; LANGID _langid;
HRESULT _GetClassCacheInfo(LPCWSTR pszClassName, LPCWSTR pszADsPath, DWORD dwFlags, CLASSCACHEENTRY **ppcce);
public: CDsDisplaySpecifier(); ~CDsDisplaySpecifier();
// *** IUnknown ***
STDMETHODIMP_(ULONG) AddRef(); STDMETHODIMP_(ULONG) Release(); STDMETHODIMP QueryInterface(REFIID riid, LPVOID FAR *ppv);
// *** IDsDisplaySpecifier ***
STDMETHOD(SetServer)(LPCWSTR pszServer, LPCWSTR pszUserName, LPCWSTR pszPassword, DWORD dwFlags); STDMETHOD(SetLanguageID)(LANGID langid); STDMETHOD(GetDisplaySpecifier)(LPCWSTR pszObjectClass, REFIID riid, void **ppv); STDMETHOD(GetIconLocation)(LPCWSTR pszObjectClass, DWORD dwFlags, LPWSTR pszBuffer, INT cchBuffer, INT *presid); STDMETHOD_(HICON, GetIcon)(LPCWSTR pszObjectClass, DWORD dwFlags, INT cxIcon, INT cyIcon); STDMETHOD(GetFriendlyClassName)(LPCWSTR pszObjectClass, LPWSTR pszBuffer, INT cchBuffer); STDMETHOD(GetFriendlyAttributeName)(LPCWSTR pszObjectClass, LPCWSTR pszAttributeName, LPWSTR pszBuffer, UINT cchBuffer); STDMETHOD_(BOOL, IsClassContainer)(LPCWSTR pszObjectClass, LPCWSTR pszADsPath, DWORD dwFlags); STDMETHOD(GetClassCreationInfo)(LPCWSTR pszObjectClass, LPDSCLASSCREATIONINFO* ppdscci); STDMETHOD(EnumClassAttributes)(LPCWSTR pszObjectClass, LPDSENUMATTRIBUTES pcbEnum, LPARAM lParam); STDMETHOD_(ADSTYPE, GetAttributeADsType)(LPCWSTR pszAttributeName); };
//
// construction/destruction
//
CDsDisplaySpecifier::CDsDisplaySpecifier() : _cRef(1), _dwFlags(0), _pszServer(NULL), _pszUserName(NULL), _pszPassword(NULL), _langid(GetUserDefaultUILanguage()) { DllAddRef(); }
CDsDisplaySpecifier::~CDsDisplaySpecifier() { LocalFreeStringW(&_pszServer); LocalFreeStringW(&_pszUserName); LocalFreeStringW(&_pszPassword); DllRelease(); }
// IUnknown
ULONG CDsDisplaySpecifier::AddRef() { return InterlockedIncrement(&_cRef); }
ULONG CDsDisplaySpecifier::Release() { if (InterlockedDecrement(&_cRef)) return _cRef;
delete this; return 0; }
HRESULT CDsDisplaySpecifier::QueryInterface(REFIID riid, void **ppv) { static const QITAB qit[] = { QITABENT(CDsDisplaySpecifier, IDsDisplaySpecifier), // IID_IDsDisplaySpecifier
{0, 0 }, }; return QISearch(this, qit, riid, ppv); }
// handle create instance
STDAPI CDsDisplaySpecifier_CreateInstance(IUnknown* punkOuter, IUnknown** ppunk, LPCOBJECTINFO poi) { CDsDisplaySpecifier *pdds = new CDsDisplaySpecifier(); if ( !pdds ) return E_OUTOFMEMORY;
HRESULT hres = pdds->QueryInterface(IID_IUnknown, (void **)ppunk); pdds->Release(); return hres; }
//
// Class cache helper functions
//
HRESULT CDsDisplaySpecifier::_GetClassCacheInfo(LPCWSTR pszObjectClass, LPCWSTR pszADsPath, DWORD dwFlags, CLASSCACHEENTRY **ppcce) { CLASSCACHEGETINFO ccgi = { 0 };
ccgi.dwFlags = dwFlags; ccgi.pObjectClass = (LPWSTR)pszObjectClass; ccgi.pPath = (LPWSTR)pszADsPath; ccgi.pServer = _pszServer; ccgi.pUserName = _pszUserName; ccgi.pPassword = _pszPassword;
if ( _dwFlags & DSSSF_SIMPLEAUTHENTICATE ) ccgi.dwFlags |= CLASSCACHE_SIMPLEAUTHENTICATE;
if ( _dwFlags & DSSSF_DSAVAILABLE ) ccgi.dwFlags |= CLASSCACHE_DSAVAILABLE; return ClassCache_GetClassInfo(&ccgi, ppcce); }
/*-----------------------------------------------------------------------------
/ IDsDisplaySpecifier::SetServer / ------------------------------ / To allow us to re-target other servers in the domains we allow the / owner of an IDsDisplaySpecifier object to set the prefered server, / this consists of the server name, the user name and the password. / / NTRAID 455406: Currently the password is stored clear text with the object, / this should be fixed - daviddv (10oct98) / / In: / pServer => server to use / pUserName => user name to be used / pPassword => password to be used / dwFlags => flags for this call / / Out: HRESULT /----------------------------------------------------------------------------*/ STDMETHODIMP CDsDisplaySpecifier::SetServer(LPCWSTR pszServer, LPCWSTR pszUserName, LPCWSTR pszPassword, DWORD dwFlags) { HRESULT hres = S_OK; USES_CONVERSION;
TraceEnter(TRACE_CACHE, "CDsDisplaySpecifier::SetServer"); Trace(TEXT("pszServer %s"), pszServer ? W2CT(pszServer):TEXT("<none>")); Trace(TEXT("pszUserName %s"), pszUserName ? W2CT(pszUserName):TEXT("<none>")); Trace(TEXT("pszPassword %s"), pszPassword ? W2CT(pszPassword):TEXT("<none>"));
// free previous credential information
LocalFreeStringW(&_pszServer); LocalFreeStringW(&_pszUserName); LocalFreeStringW(&_pszPassword);
// allocate as required the new ones
_dwFlags = dwFlags;
hres = LocalAllocStringW(&_pszServer, pszServer); if ( SUCCEEDED(hres) ) hres = LocalAllocStringW(&_pszUserName, pszUserName); if ( SUCCEEDED(hres) ) hres = LocalAllocStringW(&_pszPassword, pszPassword);
// and tidy up if we failed
if ( FAILED(hres ) ) { LocalFreeStringW(&_pszServer); LocalFreeStringW(&_pszUserName); LocalFreeStringW(&_pszPassword); }
TraceLeaveResult(hres); }
/*-----------------------------------------------------------------------------
/ IDsDisplaySpecifier::SetLanguageID / ---------------------------------- / Display specifiers are localised, by default we use the process locale / read from GetLocale during object creation. This call allows the / locale to be set. / / In: / langid == LANGID to be used for display specifier look up. If this / value is zero then we read using GetUserDefaultUILanguage() and set / accordingly. / Out: HRESULT /----------------------------------------------------------------------------*/ STDMETHODIMP CDsDisplaySpecifier::SetLanguageID(LANGID langid) { TraceEnter(TRACE_CACHE, "CDsDisplaySpecifier::SetLanguageID"); Trace(TEXT("lcid %0x8"), langid);
if ( !langid ) langid = GetUserDefaultUILanguage();
_langid = langid; // can hardly go wrong...
TraceLeaveResult(S_OK); }
/*-----------------------------------------------------------------------------
/ IDsDisplaySpecifier::GetDisplaySpecifier / ---------------------------------------- / Bind to the display specifier for a given class, try the users / locale, then the default locale calling ADsOpenObject as we / go. We use the specifier server, username and password. / / In: / pszObjectClass => object class to look up / riid, ppv => used to retrieve the COM object / / Out: HRESULT /----------------------------------------------------------------------------*/ STDMETHODIMP CDsDisplaySpecifier::GetDisplaySpecifier(LPCWSTR pszObjectClass, REFIID riid, void **ppv) { HRESULT hres; CLASSCACHEGETINFO ccgi = { 0 }; USES_CONVERSION;
TraceEnter(TRACE_CACHE, "CDsDisplaySpecifier::GetDisplaySpecifer"); Trace(TEXT("pszObjectClass: %s"), pszObjectClass ? W2CT(pszObjectClass):TEXT("<none>"));
// fill out the display specifier record
ccgi.pObjectClass = (LPWSTR)pszObjectClass; ccgi.pServer = (LPWSTR)_pszServer; ccgi.pUserName = (LPWSTR)_pszUserName; ccgi.pPassword = (LPWSTR)_pszPassword; ccgi.langid = _langid;
hres = ::GetDisplaySpecifier(&ccgi, riid, ppv); FailGracefully(hres, "Failed when calling GetDisplaySpecifier");
exit_gracefully:
TraceLeaveResult(hres); }
/*-----------------------------------------------------------------------------
/ IDsDisplaySpecifier::GetFriendlyClassName / ----------------------------------------- / Retrieve the localised (friendly) name for an LDAP object class. If / the display specifier doesn't give a friendly name for the class / then we return the name we were originally given. / / In: / pszObjectClass => object class to look up / pszBuffer, cchBuffer = buffer to recieve the string / / Out: HRESULT /----------------------------------------------------------------------------*/ STDMETHODIMP CDsDisplaySpecifier::GetFriendlyClassName(LPCWSTR pszObjectClass, LPWSTR pszBuffer, INT cchBuffer) { HRESULT hres; LPCLASSCACHEENTRY pcce = NULL; USES_CONVERSION;
TraceEnter(TRACE_CACHE, "CDsDisplaySpecifier::GetFriendlyClassName"); if ( !pszObjectClass || !pszBuffer ) ExitGracefully(hres, E_INVALIDARG, "No class, or no buffer failure");
Trace(TEXT("pszObjectClass: %s"), W2CT(pszObjectClass));
// fetch a record from the cache, if we found it then set pszObjectClass
// to be the friendly class name, otherwise we just return the class
// name we were given.
hres = _GetClassCacheInfo(pszObjectClass, NULL, CLASSCACHE_FRIENDLYNAME, &pcce); FailGracefully(hres, "Failed to get class information from cache");
if ( pcce->dwCached & CLASSCACHE_FRIENDLYNAME) { Trace(TEXT("Friendly class name: %s"), W2CT(pcce->pFriendlyClassName)); pszObjectClass = pcce->pFriendlyClassName; }
StrCpyNW(pszBuffer, pszObjectClass, cchBuffer); hres = S_OK;
exit_gracefully:
ClassCache_ReleaseClassInfo(&pcce);
TraceLeaveResult(hres); }
/*-----------------------------------------------------------------------------
/ IDsDisplaySpecifier::GetFriendlyAttributeName / --------------------------------------------- / Lookup the classes display speifier, then check the attributeNames property / for a property name pair that matches the given attribute name. With / this information return that name to the caller, if that fails then / return the original name. / / In: / pszObjectClass -> class name to look up in the cache / pszAttributeName -> attribute name to look up in the cache / pszBuffer -> buffer to be filled / cchBuffer = size of the buffer / / Out: HRESULT /----------------------------------------------------------------------------*/ STDMETHODIMP CDsDisplaySpecifier::GetFriendlyAttributeName(LPCWSTR pszObjectClass, LPCWSTR pszAttributeName, LPWSTR pszBuffer, UINT cchBuffer) { HRESULT hres; LPCLASSCACHEENTRY pcce = NULL; INT index; USES_CONVERSION;
TraceEnter(TRACE_CACHE, "DsGetFriendlyAttributeName"); if ( !pszObjectClass || !pszAttributeName || !pszBuffer || !cchBuffer ) ExitGracefully(hres, E_INVALIDARG, "Bad class/attribute/return buffer");
Trace(TEXT("pszbjectClass: %s"), W2CT(pszObjectClass)); Trace(TEXT("pszAttributeName: %s"), W2CT(pszAttributeName)); Trace(TEXT("pszBuffer %x, cchBuffer %d"), pszBuffer, cchBuffer);
hres = _GetClassCacheInfo(pszObjectClass, NULL, CLASSCACHE_ATTRIBUTENAMES, &pcce); FailGracefully(hres, "Failed to get class information from cache");
if ( pcce->dwCached & CLASSCACHE_ATTRIBUTENAMES ) { ATTRIBUTENAME an = { 0 }; an.pName = (LPWSTR)pszAttributeName;
index = DPA_Search(pcce->hdpaAttributeNames, &an, 0, _CompareAttributeNameCB, NULL, DPAS_SORTED); if ( index != -1 ) { LPATTRIBUTENAME pAN = (LPATTRIBUTENAME)DPA_GetPtr(pcce->hdpaAttributeNames, index);
if (pAN) { pszAttributeName = pAN->pDisplayName; TraceAssert(pszAttributeName); } } }
StrCpyNW(pszBuffer, pszAttributeName, cchBuffer); hres = S_OK;
exit_gracefully:
ClassCache_ReleaseClassInfo(&pcce);
TraceLeaveResult(hres); }
/*-----------------------------------------------------------------------------
/ IDsDisplaySpecifier::IsClassContainer / ------------------------------------- / Return TRUE/FALSE indicating if the specified object class is a container, / we determine this both from the schema and the display specifier. / / The schema indicates if the class can container other objects, if so / then the object is a container. In the display specifier we have / an attribute "treatAsLeaf" which we use to override this setting, this / is used both from the admin tools and client UI. / / In: / pszObjectClass => object class to look up / pszADsPath => ADsPath of an object in the DS we can bind to and fetch / schema information from. / dwFlags => flags controlling this API: / DSICCF_IGNORETREATASLEAF = 1 => return schema attribute only, don't / override with treatAsLeaf attribute / from display specifier. / Out: BOOL /----------------------------------------------------------------------------*/ STDMETHODIMP_(BOOL) CDsDisplaySpecifier::IsClassContainer(LPCWSTR pszObjectClass, LPCWSTR pszADsPath, DWORD dwFlags) { HRESULT hres; BOOL fres = FALSE; LPCLASSCACHEENTRY pcce = NULL; USES_CONVERSION;
TraceEnter(TRACE_CACHE, "CDsDisplaySpecifier::IsClassContainer");
if ( !pszObjectClass ) ExitGracefully(hres, E_INVALIDARG, "No object class failure");
Trace(TEXT("pszObjectClass: %s"), W2CT(pszObjectClass)); Trace(TEXT("dwFlags %x"), dwFlags);
hres = _GetClassCacheInfo(pszObjectClass,pszADsPath, CLASSCACHE_CONTAINER|CLASSCACHE_TREATASLEAF, &pcce); FailGracefully(hres, "Failed to get class information from cache"); fres = _IsClassContainer(pcce, dwFlags & DSICCF_IGNORETREATASLEAF); Trace(TEXT("_IsClassContainer returns %d"), fres);
exit_gracefully:
ClassCache_ReleaseClassInfo(&pcce);
TraceLeaveValue(fres); }
/*-----------------------------------------------------------------------------
/ IDsDisplaySpecifier::GetIconLocation / ------------------------------------ / Fetch the location of an icon from the DS, returning both the filename and / the resource ID as required. The caller can then load the image, or / display this information in a dialog. / / In: / pszObjectClass => class to retrieve for / dwFlags = flags for extraction: / / One of the following: / DSGIF_ISNORMAL => standard icon, or, / DSGIF_OPEN => open icon (open folders etc), or, / DSGIF_DISABLED => disabled icon (eg. disabled user account). / / Combined with any of the: / DSGIF_GETDEFAULTICON => if no icon exists for this object, return the default document / icon from shell32. / / pszBuffer, cchBuffer => buffer to recieve the filename / presid => receives the resource id, +ve for index, -ve for resource / / Out: / HRESULT /----------------------------------------------------------------------------*/ STDMETHODIMP CDsDisplaySpecifier::GetIconLocation(LPCWSTR pszObjectClass, DWORD dwFlags, LPWSTR pszBuffer, INT cchBuffer, INT* presid) { HRESULT hres; LPCLASSCACHEENTRY pcce = NULL; USES_CONVERSION;
TraceEnter(TRACE_CACHE, "CDsDisplaySpecifier::GetIconLocation");
if ( !pszObjectClass || !pszBuffer ) ExitGracefully(hres, E_INVALIDARG, "No object class/buffer failure");
Trace(TEXT("pszObjectClass: %s"), W2CT(pszObjectClass)); Trace(TEXT("dwFlags %x"), dwFlags);
hres = _GetClassCacheInfo(pszObjectClass, NULL, CLASSCACHE_ICONS, &pcce); FailGracefully(hres, "Failed to get class information from cache");
hres = _GetIconLocation(pcce, dwFlags, pszBuffer, cchBuffer, presid); FailGracefully(hres, "Failed calling GetIconLocation");
exit_gracefully:
ClassCache_ReleaseClassInfo(&pcce);
TraceLeaveResult(hres); }
/*-----------------------------------------------------------------------------
/ IDsDisplaySpecifier::GetIcon / ---------------------------- / Load the icon for the object class given. Icon information is stored in the / display specifier, we support 15 different states (open, closed, disabled etc). / / We look up the resource name from the DS and we then call PrivateExtractIcons / to load the object from the file. / / In: / pszObjectClass => class to retrieve for / dwFlags = flags for extraction: / / One of the following: / DSGIF_ISNORMAL => standard icon, or, / DSGIF_OPEN => open icon (open folders etc), or, / DSGIF_DISABLED => disabled icon (eg. disabled user account). / / Combined with any of the: / DSGIF_GETDEFAULTICON => if no icon exists for this object, return the default document / icon from shell32. / / cxImage, cyImage = size of image to load / / Out: / HICON / == NULL if failed /----------------------------------------------------------------------------*/ STDMETHODIMP_(HICON) CDsDisplaySpecifier::GetIcon(LPCWSTR pszObjectClass, DWORD dwFlags, INT cxImage, INT cyImage) { HRESULT hres; HICON hIcon = NULL; WCHAR szBuffer[MAX_PATH]; INT resid; USES_CONVERSION;
TraceEnter(TRACE_CACHE, "CDsDisplaySpecifier::GetIcon"); if ( !pszObjectClass ) ExitGracefully(hres, E_INVALIDARG, "no object class specified");
Trace(TEXT("pszObjectClass %s, dwFlags %x, cxImage %d, cyImage %d"), W2CT(pszObjectClass), dwFlags, cxImage, cyImage);
hres = GetIconLocation(pszObjectClass, dwFlags, szBuffer, ARRAYSIZE(szBuffer), &resid); FailGracefully(hres, "Failed when calling GetIconLocation");
if ( hres == S_OK ) { Trace(TEXT("Calling PrivateExtractIcons on %s,%d"), W2CT(szBuffer), resid);
if ( 1 != PrivateExtractIcons(szBuffer, resid, cxImage, cyImage, &hIcon, NULL, 1, LR_LOADFROMFILE) ) ExitGracefully(hres, E_FAIL, "Failed to load the icon given its path etc");
hres = S_OK; // success
}
exit_gracefully:
if ( !hIcon && (dwFlags & DSGIF_GETDEFAULTICON) ) { //
// failed to load the icon and they really want the default document, so give it to them
//
TraceMsg("Failed to load the icon, so picking up default document image");
if ( 1 != PrivateExtractIcons(L"shell32.dll", -1, cxImage, cyImage, &hIcon, NULL, 1, LR_LOADFROMFILE) ) { TraceMsg("Failed to load the default document icon from shell32"); } }
TraceLeaveValue(hIcon); }
/*-----------------------------------------------------------------------------
/ IDsDisplaySpecifier::GetClassCreationInfo / ----------------------------------------- / Given an object class return the CLSIDs of the objects that make up / its creation wizard. / / In: / pszObjectClass -> class to enumerate from / ppdscci -> DSCREATECLASSINFO structure pointer to fill / / Out: HRESULT /----------------------------------------------------------------------------*/ STDMETHODIMP CDsDisplaySpecifier::GetClassCreationInfo(LPCWSTR pszObjectClass, LPDSCLASSCREATIONINFO* ppdscci) { HRESULT hres; LPDSCLASSCREATIONINFO pdscci = NULL; LPCLASSCACHEENTRY pcce = NULL; DWORD cbStruct = SIZEOF(DSCLASSCREATIONINFO); INT i; USES_CONVERSION;
TraceEnter(TRACE_CACHE, "CDsDisplaySpecifer::GetClassCreationInfo");
if ( !pszObjectClass || !ppdscci ) ExitGracefully(hres, E_INVALIDARG, "No object class/pdscci passed"); // call the caching code to retrieve the creation wizard information
hres = _GetClassCacheInfo(pszObjectClass, NULL, CLASSCACHE_CREATIONINFO, &pcce); FailGracefully(hres, "Failed to get class information from cache");
// now allocate the creation wizard structure and pass it to the
// caller with the information filled in.
if ( pcce->hdsaWizardExtn ) cbStruct += SIZEOF(GUID)*(DSA_GetItemCount(pcce->hdsaWizardExtn)-1); // -1 as structure already has 1 in the array!
Trace(TEXT("Allocating creationg structure: cbStruct %d"), cbStruct);
pdscci = (LPDSCLASSCREATIONINFO)LocalAlloc(LPTR, cbStruct); if ( !pdscci ) ExitGracefully(hres, E_OUTOFMEMORY, "Failed to allocate return structure");
//pdscci->dwFlags = 0;
//pdscci->clsidWizardDialog = { 0 };
//pdscci->clsidWizardPimaryPage = { 0 };
//pdscci->cWizardExtensions = 0;
//pdscci->aWizardExtensions = { 0 };
if ( pcce->dwCached & CLASSCACHE_WIZARDDIALOG ) { TraceGUID("clsidWizardDialog is ", pcce->clsidWizardDialog); pdscci->dwFlags |= DSCCIF_HASWIZARDDIALOG; pdscci->clsidWizardDialog = pcce->clsidWizardDialog; }
if ( pcce->dwCached & CLASSCACHE_WIZARDPRIMARYPAGE ) { TraceGUID("clsidWizardPrimaryPage is ", pcce->clsidWizardPrimaryPage); pdscci->dwFlags |= DSCCIF_HASWIZARDPRIMARYPAGE; pdscci->clsidWizardPrimaryPage = pcce->clsidWizardPrimaryPage; }
if ( pcce->hdsaWizardExtn ) { pdscci->cWizardExtensions = DSA_GetItemCount(pcce->hdsaWizardExtn); Trace(TEXT("Class has %d wizard extensions"), pdscci->cWizardExtensions);
for ( i = 0 ; i < DSA_GetItemCount(pcce->hdsaWizardExtn) ; i++ ) { LPGUID pGUID = (LPGUID)DSA_GetItemPtr(pcce->hdsaWizardExtn, i); TraceAssert(pGUID);
TraceGUID("Wizard extension %d is ", *pGUID); pdscci->aWizardExtensions[i] = *pGUID; } }
hres = S_OK; // success
exit_gracefully:
ClassCache_ReleaseClassInfo(&pcce);
// it failed, therefore release pInfo if we have one, before setting
// the return pointer for the caller.
if ( FAILED(hres) && pdscci ) { TraceMsg("Failed, so freeing info structure"); LocalFree(pdscci); pdscci = NULL; }
if ( ppdscci ) { Trace(TEXT("Setting ppInfo to %08x"), pdscci); *ppdscci = pdscci; }
TraceLeaveResult(hres); }
/*-----------------------------------------------------------------------------
/ IDsDisplaySpecifier::EnumClassAttributes / ---------------------------------------- / Enumerate all the attributes and their friendly names for the given object class. / The code looks up the display specifier and then calls given callback for each one, / passing the attribute name and its given "friendly name". / / In: / pszObjectClass -> class to enumerate from / pEnumCB -> callback function to enumerate to / lParam = lParam to pass to the CB fucntion / / Out: HRESULT /----------------------------------------------------------------------------*/
// NTRAID 455406: this should return an enumerator
typedef struct { LPDSENUMATTRIBUTES pcbEnum; LPARAM lParam; } CLASSENUMCBSTATE, * LPCLASSENUMCBSTATE;
INT _EnumClassAttributesCB(LPVOID p, LPVOID pData) { LPATTRIBUTENAME pAttributeName = (LPATTRIBUTENAME)p; LPCLASSENUMCBSTATE pState = (LPCLASSENUMCBSTATE)pData; return SUCCEEDED(pState->pcbEnum(pState->lParam, pAttributeName->pName, pAttributeName->pDisplayName, pAttributeName->dwFlags)); }
STDMETHODIMP CDsDisplaySpecifier::EnumClassAttributes(LPCWSTR pszObjectClass, LPDSENUMATTRIBUTES pcbEnum, LPARAM lParam) { HRESULT hres; LPCLASSCACHEENTRY pcce = NULL; USES_CONVERSION;
TraceEnter(TRACE_CACHE, "CDsDisplaySpecifier::EnumClassAttributes"); if ( !pszObjectClass || !pcbEnum ) ExitGracefully(hres, E_INVALIDARG, "Bad class/cb function");
Trace(TEXT("pszObjectClass: %s"), W2CT(pszObjectClass));
// call the cache code to pick up the friendly name, having done this we
// can then copy it to the user buffer
hres = _GetClassCacheInfo(pszObjectClass, NULL, CLASSCACHE_ATTRIBUTENAMES, &pcce); FailGracefully(hres, "Failed to get class information from cache");
if ( pcce->dwCached & CLASSCACHE_ATTRIBUTENAMES ) { CLASSENUMCBSTATE state = { pcbEnum, lParam }; DPA_EnumCallback(pcce->hdpaAttributeNames, _EnumClassAttributesCB, &state); }
hres = S_OK;
exit_gracefully:
ClassCache_ReleaseClassInfo(&pcce);
TraceLeaveResult(hres); }
/*-----------------------------------------------------------------------------
/ IDsDisplaySpecifier::GetAttributeADsType / ---------------------------------------- / Look up the given attribute for its ADsType. / / In: / pszAttributeName = attribute to look up / / Out: / ADSTYPE /----------------------------------------------------------------------------*/ STDMETHODIMP_(ADSTYPE) CDsDisplaySpecifier::GetAttributeADsType(LPCWSTR pszAttributeName) { TraceEnter(TRACE_CACHE, "CDsDisplaySpecifier::GetAttributeADsType");
CLASSCACHEGETINFO ccgi = { 0 }; ccgi.pServer = _pszServer; ccgi.pUserName = _pszUserName; ccgi.pPassword = _pszPassword;
if ( _dwFlags & DSSSF_SIMPLEAUTHENTICATE ) ccgi.dwFlags |= CLASSCACHE_SIMPLEAUTHENTICATE;
if ( _dwFlags & DSSSF_DSAVAILABLE ) ccgi.dwFlags |= CLASSCACHE_DSAVAILABLE;
ADSTYPE adt = ClassCache_GetADsTypeFromAttribute(&ccgi, pszAttributeName); TraceLeaveValue(adt); }
/*-----------------------------------------------------------------------------
/ Externally exported cache APIs /----------------------------------------------------------------------------*/
CDsDisplaySpecifier g_dsDisplaySpecifier;
//
// these are exported for backwards compatiblity. We used to expose a series
// of DsXXX APIs which dsquery, dsfolder and dsadmin all called. We have
// now migrated these to a COM interface.
//
STDAPI_(HICON) DsGetIcon(DWORD dwFlags, LPWSTR pszObjectClass, INT cxImage, INT cyImage) { return g_dsDisplaySpecifier.GetIcon(pszObjectClass, dwFlags, cxImage, cyImage); }
STDAPI DsGetFriendlyClassName(LPWSTR pszObjectClass, LPWSTR pszBuffer, UINT cchBuffer) { return g_dsDisplaySpecifier.GetFriendlyClassName(pszObjectClass, pszBuffer, cchBuffer); }
|