COMMON.CPP
/*++ 
 
Copyright (c) 1996 Microsoft Corporation 
 
Module Name: 
 
    Common.cpp 
 
Abstract: 
 
    Contains routines and properties that are common to 
    all tshirt objects. thsirt objects get the routines and 
    properties through C++ inheritance. 
 
Author: 
 
Environment: 
 
    User mode 
 
Revision History : 
 
--*/ 
#include "adssmp.h" 
#pragma hdrstop 
 
 
FILTERS Filters[] = { 
                    {L"organizational unit", SampleDS_OU_ID}, 
                    {L"class", SampleDS_CLASS_ID}, 
                    {L"property", SampleDS_PROPERTY_ID} 
                  }; 
 
#define MAX_FILTERS  (sizeof(Filters)/sizeof(FILTERS)) 
 
PFILTERS  gpFilters = Filters; 
DWORD gdwMaxFilters = MAX_FILTERS; 
 
extern WCHAR * g_szProviderName; 
 
HRESULT 
xx_put_BSTR(BSTR* lppItemName, BSTR lpName) 
{ 
    if (*lppItemName) { 
        SysFreeString(*lppItemName); 
        *lppItemName = NULL; 
    } 
 
    if (!lpName) { 
        RRETURN(S_OK); 
    } 
 
    *lppItemName = SysAllocString(lpName); 
 
    if (!*lppItemName) { 
        RRETURN(E_FAIL); 
    } 
    RRETURN(S_OK); 
} 
 
HRESULT 
xx_put_LONG(long * plnItem, long lnItem) 
{ 
    *plnItem = lnItem; 
    RRETURN(S_OK); 
} 
 
HRESULT 
xx_put_DATE(DATE * pdaItem, DATE daItem) 
{ 
    *pdaItem = daItem; 
    RRETURN(S_OK); 
} 
 
 
HRESULT 
xx_put_VARIANT_BOOL(VARIANT_BOOL * pfItem, VARIANT_BOOL fItem) 
{ 
    *pfItem = fItem; 
    RRETURN(S_OK); 
} 
 
 
HRESULT 
xx_put_VARIANT(VARIANT * * ppvItem, VARIANT vItem) 
{ 
    if (!*ppvItem) { 
        if (!(*ppvItem = (VARIANT *)AllocProvMem(sizeof(VARIANT)))){ 
            RRETURN(E_OUTOFMEMORY); 
        } 
    } 
    RRETURN(VariantCopy(*ppvItem, &vItem)); 
} 
 
HRESULT 
BuildADsPath( 
    BSTR Parent, 
    BSTR Name, 
    BSTR *pADsPath 
    ) 
{ 
    WCHAR ADsPath[MAX_PATH]; 
    WCHAR ProviderName[MAX_PATH]; 
    HRESULT hr = S_OK; 
 
    // 
    // We will assert if bad parameters are passed to us. 
    // This is because this should never be the case. This 
    // is an internal call 
    // 
 
    ADsAssert(Parent && Name); 
    ADsAssert(pADsPath); 
 
 
    // 
    // Special case the Namespace object; if 
    // the parent is L"ADs:", then Name = ADsPath 
    // 
 
    if (!_wcsicmp(Parent, L"ADs:")) { 
        RRETURN(xx_put_BSTR(pADsPath, Name)); 
    } 
 
    // 
    // The rest of the cases we expect valid data, 
    // Path, Parent and Name are read-only, the end-user 
    // cannot modify this data 
    // 
 
    // 
    // For first level objects we do not add 
    // the first backslash; so we examine that the parent is 
    // L"Sample:" and skip the slash otherwise we start with 
    // the slash 
    // 
 
    wsprintf(ProviderName, L"%s:", g_szProviderName); 
 
    wcscpy(ADsPath, Parent); 
 
    if (_wcsicmp(ADsPath, ProviderName)) { 
        wcscat(ADsPath, L"/"); 
    }else { 
        wcscat(ADsPath, L"//"); 
    } 
    wcscat(ADsPath, Name); 
 
    hr = xx_put_BSTR(pADsPath, ADsPath); 
 
    RRETURN(hr); 
} 
 
HRESULT 
BuildSchemaPath( 
    BSTR bstrADsPath, 
    BSTR bstrClass, 
    BSTR *pSchemaPath 
    ) 
{ 
    WCHAR ADsSchema[MAX_PATH]; 
    OBJECTINFO ObjectInfo; 
    POBJECTINFO pObjectInfo = &ObjectInfo; 
    CLexer Lexer(bstrADsPath); 
    HRESULT hr = S_OK; 
 
    wcscpy(ADsSchema, L""); 
 
    if (bstrClass && *bstrClass) { 
        memset(pObjectInfo, 0, sizeof(OBJECTINFO)); 
        hr = ADsObject(&Lexer, pObjectInfo); 
        BAIL_ON_FAILURE(hr); 
 
        if (pObjectInfo->RootRDN) { 
 
            wsprintf(ADsSchema,L"%s://",pObjectInfo->ProviderName); 
            wcscat(ADsSchema, pObjectInfo->RootRDN); 
            wcscat(ADsSchema,L"/schema/"); 
            wcscat(ADsSchema, bstrClass); 
 
        } 
    } 
 
    hr = ProvAllocString( ADsSchema, pSchemaPath); 
 
error: 
 
    if (pObjectInfo) { 
 
        // 
        // BugBug - KrishnaG; free up this piece of memory 
        // 
    } 
    RRETURN(hr); 
} 
 
 
HRESULT 
BuildADsGuid( 
    REFCLSID clsid, 
    BSTR *pADsClass 
){ 
    WCHAR ADsClass[MAX_PATH]; 
 
    StringFromGUID2(clsid, ADsClass, 256); 
 
    RRETURN(xx_put_BSTR(pADsClass, ADsClass)); 
} 
 
 
typedef struct _typeinfotable 
{ 
    GUID iid; 
    ITypeInfo * pTypeInfo; 
    struct _typeinfotable *pNext; 
}TYPEINFO_TABLE, *PTYPEINFO_TABLE; 
 
 
PTYPEINFO_TABLE gpTypeInfoTable = NULL; 
 
ITypeInfo * 
FindTypeInfo( 
    PTYPEINFO_TABLE pTypeInfoTable, 
    REFIID iid 
){ 
    PTYPEINFO_TABLE pTemp = NULL; 
 
    pTemp = pTypeInfoTable; 
 
    while (pTemp) { 
        if (IsEqualIID(iid, pTemp->iid)) { 
            return(pTemp->pTypeInfo); 
        } 
        pTemp = pTemp->pNext; 
    } 
    return(NULL); 
} 
 
 
PTYPEINFO_TABLE 
AddTypeInfo( 
    PTYPEINFO_TABLE pTypeInfoTable, 
    REFIID iid, 
    ITypeInfo * pTypeInfo 
){ 
    PTYPEINFO_TABLE pTemp = NULL; 
 
    pTemp = (PTYPEINFO_TABLE)AllocProvMem( 
                    sizeof(TYPEINFO_TABLE) 
                    ); 
    if (!pTemp) { 
        return(NULL); 
    } 
 
    memcpy(&pTemp->iid, &iid, sizeof(GUID)); 
    pTemp->pTypeInfo = pTypeInfo; 
    pTemp->pNext = pTypeInfoTable; 
 
    return(pTemp); 
} 
 
HRESULT 
LoadTypeInfoEntry( 
    CDispatchMgr *pDispMgr, 
    REFIID libid, 
    REFIID iid, 
    void * pIntf, 
    DISPID SpecialId 
){ 
    ITypeInfo * pTypeInfo = NULL; 
    HRESULT hr; 
 
    pTypeInfo = FindTypeInfo( 
                    gpTypeInfoTable, 
                    iid 
                    ); 
    if (!pTypeInfo) { 
 
        hr = LoadTypeInfo(libid, iid, &pTypeInfo); 
        BAIL_IF_ERROR(hr); 
 
        gpTypeInfoTable = AddTypeInfo( 
                                gpTypeInfoTable, 
                                iid, 
                                pTypeInfo 
                                ); 
        if (!gpTypeInfoTable) { 
            hr = HRESULT_FROM_WIN32(GetLastError()); 
            BAIL_IF_ERROR(hr); 
        } 
    } 
    pTypeInfo->AddRef(); 
 
 
    hr = pDispMgr->AddTypeInfo(pTypeInfo, pIntf); 
    BAIL_IF_ERROR(hr); 
 
    if (SpecialId == -4) { 
        hr = pDispMgr->MarkAsNewEnum(pTypeInfo); 
    } 
 
    RRETURN(S_OK); 
 
cleanup: 
 
   if (pTypeInfo) { 
       pTypeInfo->Release(); 
   } 
    RRETURN(hr); 
} 
 
HRESULT 
ValidateOutParameter(BSTR * retval) 
{ 
    if (!retval) { 
        RRETURN(E_ADS_BAD_PARAMETER); 
    } 
    RRETURN(S_OK); 
} 
 
 
PKEYDATA 
CreateTokenList( 
    LPWSTR   pKeyData, 
    WCHAR ch 
){ 
    DWORD       cTokens; 
    DWORD       cb; 
    PKEYDATA    pResult; 
    LPWSTR       pDest; 
    LPWSTR       psz = pKeyData; 
    LPWSTR      *ppToken; 
    WCHAR szTokenList[MAX_PATH]; 
 
 
    if (!psz || !*psz) 
        return NULL; 
 
    wsprintf(szTokenList, L"%c", ch); 
 
    cTokens=1; 
 
    // Scan through the string looking for commas, 
    // ensuring that each is followed by a non-NULL character: 
 
    while ((psz = wcschr(psz, ch)) && psz[1]) { 
 
        cTokens++; 
        psz++; 
    } 
 
    cb = sizeof(KEYDATA) + (cTokens-1) * sizeof(LPWSTR) + 
         wcslen(pKeyData)*sizeof(WCHAR) + sizeof(WCHAR); 
 
    if (!(pResult = (PKEYDATA)AllocProvMem(cb))) 
        return NULL; 
 
    // Initialise pDest to point beyond the token pointers: 
 
    pDest = (LPWSTR)((LPBYTE)pResult + sizeof(KEYDATA) + 
                                      (cTokens-1) * sizeof(LPWSTR)); 
 
    // Then copy the key data buffer there: 
 
    wcscpy(pDest, pKeyData); 
 
    ppToken = pResult->pTokens; 
 
 
    // Remember, wcstok has the side effect of replacing the delimiter 
    // by NULL, which is precisely what we want: 
 
    psz = wcstok (pDest, szTokenList); 
 
    while (psz) { 
 
        *ppToken++ = psz; 
        psz = wcstok (NULL, szTokenList); 
    } 
 
    pResult->cTokens = cTokens; 
 
    return( pResult ); 
} 
 
//+------------------------------------------------------------------------ 
// 
//  Function:   LoadTypeInfo 
// 
//  Synopsis:   Loads a typeinfo from a registered typelib. 
// 
//  Arguments:  [clsidTL] --  TypeLib GUID 
//              [clsidTI] --  TypeInfo GUID 
//              [ppTI]    --  Resulting typeInfo 
// 
//  Returns:    HRESULT 
// 
//------------------------------------------------------------------------- 
 
HRESULT 
LoadTypeInfo(CLSID clsidTL, CLSID clsidTI, LPTYPEINFO *ppTI) 
{ 
    HRESULT     hr; 
    ITypeLib *  pTL; 
 
    ADsAssert(ppTI); 
    *ppTI = NULL; 
    hr = LoadRegTypeLib(clsidTL, 1, 0, LOCALE_SYSTEM_DEFAULT, &pTL); 
    if (hr) 
        RRETURN(hr); 
 
    hr = pTL->GetTypeInfoOfGuid(clsidTI, ppTI); 
    pTL->Release(); 
    RRETURN(hr); 
}