341 lines
8.5 KiB
C++
341 lines
8.5 KiB
C++
|
//
|
||
|
// Author: DebiM
|
||
|
// Date: September 1996
|
||
|
//
|
||
|
//
|
||
|
// Class Store Schema creation and access using ADs
|
||
|
//
|
||
|
// This source file contains implementations for IClassAccess,
|
||
|
// interface for CClassAccess object.
|
||
|
//
|
||
|
//
|
||
|
//---------------------------------------------------------------------
|
||
|
|
||
|
#include "cstore.hxx"
|
||
|
|
||
|
HRESULT CreateContainer (HANDLE pParent,
|
||
|
LPOLESTR szName,
|
||
|
LPOLESTR szDesc
|
||
|
)
|
||
|
{
|
||
|
|
||
|
HRESULT hr;
|
||
|
int l;
|
||
|
ADS_ATTR_INFO Attr[3];
|
||
|
|
||
|
//
|
||
|
// Use the Parent Container interface to Create the child.
|
||
|
//
|
||
|
|
||
|
PackStrToAttr(Attr, OBJECTCLASS, CLASS_CS_CONTAINER);
|
||
|
|
||
|
PackStrToAttr(Attr+1, DESCRIPTION, szDesc);
|
||
|
|
||
|
//
|
||
|
// Set its schema version
|
||
|
//
|
||
|
//PackDWToAttr(Attr+2, STOREVERSION, SCHEMA_VERSION_NUMBER);
|
||
|
|
||
|
hr = ADSICreateDSObject(pParent, szName, Attr, 2);
|
||
|
|
||
|
return hr;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
HRESULT CreateRepository(LPOLESTR szParentPath, LPOLESTR szStoreName, LPOLESTR szPolicyDn)
|
||
|
{
|
||
|
|
||
|
HRESULT hr = S_OK;
|
||
|
HANDLE hADsParent = NULL;
|
||
|
HANDLE hADsContainer = NULL;
|
||
|
HANDLE hADsPolicy = NULL;
|
||
|
LPOLESTR szContainerName = NULL;
|
||
|
LPOLESTR szPolicyName = NULL;
|
||
|
int l;
|
||
|
WCHAR szPath [_MAX_PATH];
|
||
|
WCHAR * szFullName = NULL;
|
||
|
WCHAR szUsn[30];
|
||
|
ADS_ATTR_INFO pAttr[4];
|
||
|
DWORD cGot = 0, cModified = 0;
|
||
|
BOOL fCreatedContainer = FALSE,
|
||
|
fCreatedCategories = FALSE,
|
||
|
fCreatedClasses = FALSE;
|
||
|
LPOLESTR AttrName = GPNAME;
|
||
|
ADS_ATTR_INFO * pGetAttr = NULL;
|
||
|
|
||
|
if (!szParentPath)
|
||
|
{
|
||
|
hr = GetRootPath(szPath);
|
||
|
//
|
||
|
// If failed go away
|
||
|
//
|
||
|
if (FAILED(hr))
|
||
|
{
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
szParentPath = szPath;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// First get the PolicyName
|
||
|
//
|
||
|
if (szPolicyDn)
|
||
|
{
|
||
|
hr = ADSIOpenDSObject(szPolicyDn, NULL, NULL, ADS_SECURE_AUTHENTICATION,
|
||
|
&hADsPolicy);
|
||
|
RETURN_ON_FAILURE(hr);
|
||
|
|
||
|
//
|
||
|
// Get the PolicyName
|
||
|
//
|
||
|
|
||
|
hr = ADSIGetObjectAttributes(hADsPolicy, &AttrName, 1, &pGetAttr, &cGot);
|
||
|
|
||
|
if (SUCCEEDED(hr) && (cGot))
|
||
|
UnpackStrAllocFrom(pGetAttr[0], &szPolicyName);
|
||
|
|
||
|
if (pGetAttr)
|
||
|
FreeADsMem(pGetAttr);
|
||
|
pGetAttr = NULL;
|
||
|
|
||
|
ADSICloseDSObject(hADsPolicy);
|
||
|
}
|
||
|
|
||
|
hr = ADSIOpenDSObject(szParentPath, NULL, NULL, ADS_SECURE_AUTHENTICATION,
|
||
|
&hADsParent);
|
||
|
RETURN_ON_FAILURE(hr);
|
||
|
|
||
|
hr = CreateContainer(hADsParent,
|
||
|
szStoreName,
|
||
|
L"Application Store");
|
||
|
|
||
|
//
|
||
|
// handle this error correctly
|
||
|
// see if a broken class store is left behind
|
||
|
// this could happen due to DS going down after incomplete creation etc.
|
||
|
// from the class store container property you could tell
|
||
|
//
|
||
|
if ((hr == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS)) ||
|
||
|
(hr == HRESULT_FROM_WIN32(ERROR_OBJECT_ALREADY_EXISTS)))
|
||
|
{
|
||
|
//
|
||
|
// There is a Class Store already
|
||
|
// See if it is a good one.
|
||
|
|
||
|
DWORD dwStoreVersion = 0;
|
||
|
hr = BuildADsPathFromParent(szParentPath, szStoreName, &szFullName);
|
||
|
if (!SUCCEEDED(hr))
|
||
|
return CS_E_OBJECT_ALREADY_EXISTS;
|
||
|
|
||
|
hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION,
|
||
|
&hADsContainer);
|
||
|
|
||
|
FreeADsMem(szFullName);
|
||
|
if (!SUCCEEDED(hr))
|
||
|
return CS_E_OBJECT_ALREADY_EXISTS;
|
||
|
|
||
|
AttrName = STOREVERSION;
|
||
|
//
|
||
|
// Get the Store Version
|
||
|
//
|
||
|
|
||
|
hr = ADSIGetObjectAttributes(hADsContainer, &AttrName, 1, &pGetAttr, &cGot);
|
||
|
|
||
|
if (SUCCEEDED(hr) && (cGot))
|
||
|
UnpackDWFrom(pGetAttr[0], &dwStoreVersion);
|
||
|
|
||
|
if (pGetAttr)
|
||
|
FreeADsMem(pGetAttr);
|
||
|
|
||
|
ADSICloseDSObject(hADsContainer);
|
||
|
|
||
|
if (dwStoreVersion == SCHEMA_VERSION_NUMBER)
|
||
|
return CS_E_OBJECT_ALREADY_EXISTS;
|
||
|
|
||
|
// if it is zero, then it was aborted in the middle.
|
||
|
if (dwStoreVersion != 0)
|
||
|
return CS_E_SCHEMA_MISMATCH;
|
||
|
|
||
|
// If it is a bad one try to delete it
|
||
|
DeleteRepository(szParentPath, szStoreName);
|
||
|
|
||
|
//
|
||
|
// Then again try to create it and proceed if successful
|
||
|
//
|
||
|
|
||
|
hr = CreateContainer(hADsParent,
|
||
|
szStoreName,
|
||
|
L"Application Store");
|
||
|
|
||
|
}
|
||
|
|
||
|
ERROR_ON_FAILURE(hr);
|
||
|
fCreatedContainer = TRUE;
|
||
|
|
||
|
hr = BuildADsPathFromParent(szParentPath, szStoreName, &szFullName);
|
||
|
ERROR_ON_FAILURE(hr);
|
||
|
|
||
|
hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION,
|
||
|
&hADsContainer);
|
||
|
|
||
|
ERROR_ON_FAILURE(hr);
|
||
|
|
||
|
|
||
|
//
|
||
|
// Create the class container
|
||
|
//
|
||
|
|
||
|
hr = CreateContainer (hADsContainer,
|
||
|
CLASSCONTAINERNAME,
|
||
|
L"Application Object Classes");
|
||
|
|
||
|
ERROR_ON_FAILURE(hr);
|
||
|
fCreatedClasses = TRUE;
|
||
|
|
||
|
|
||
|
//
|
||
|
// Create the category container
|
||
|
//
|
||
|
|
||
|
hr = CreateContainer (hADsContainer,
|
||
|
CATEGORYCONTAINERNAME,
|
||
|
L"Component Categories");
|
||
|
|
||
|
ERROR_ON_FAILURE(hr);
|
||
|
fCreatedCategories = TRUE;
|
||
|
|
||
|
//
|
||
|
// Create the package container
|
||
|
//
|
||
|
|
||
|
hr = CreateContainer (hADsContainer,
|
||
|
PACKAGECONTAINERNAME,
|
||
|
L"Application Packages");
|
||
|
|
||
|
ERROR_ON_FAILURE(hr);
|
||
|
|
||
|
//
|
||
|
// Store the USN and PolicyID properties
|
||
|
//
|
||
|
|
||
|
GetCurrentUsn(szUsn);
|
||
|
|
||
|
PackStrToAttr(&pAttr[0], STOREUSN, szUsn);
|
||
|
PackStrToAttr(&pAttr[1], POLICYDN, szPolicyDn);
|
||
|
PackStrToAttr(&pAttr[2], POLICYNAME, szPolicyName);
|
||
|
PackDWToAttr(&pAttr[3], STOREVERSION, SCHEMA_VERSION_NUMBER);
|
||
|
|
||
|
hr = ADSISetObjectAttributes(hADsContainer, pAttr, 4, &cModified);
|
||
|
|
||
|
FreeAttr(pAttr[0]);
|
||
|
FreeAttr(pAttr[1]);
|
||
|
FreeAttr(pAttr[2]);
|
||
|
FreeAttr(pAttr[3]);
|
||
|
|
||
|
ADSICloseDSObject(hADsContainer);
|
||
|
ADSICloseDSObject(hADsParent);
|
||
|
|
||
|
FreeADsMem(szFullName);
|
||
|
CoTaskMemFree(szPolicyName);
|
||
|
|
||
|
return RemapErrorCode(hr, szParentPath);
|
||
|
|
||
|
Error_Cleanup:
|
||
|
|
||
|
if (fCreatedCategories)
|
||
|
ADSIDeleteDSObject(hADsContainer, CATEGORYCONTAINERNAME);
|
||
|
if (fCreatedClasses)
|
||
|
ADSIDeleteDSObject(hADsContainer, CLASSCONTAINERNAME);
|
||
|
if (hADsContainer)
|
||
|
ADSICloseDSObject(hADsContainer);
|
||
|
|
||
|
if (fCreatedContainer)
|
||
|
ADSIDeleteDSObject(hADsParent, szStoreName);
|
||
|
if (hADsParent)
|
||
|
ADSICloseDSObject(hADsParent);
|
||
|
|
||
|
if (szFullName)
|
||
|
FreeADsMem(szFullName);
|
||
|
if (szPolicyName)
|
||
|
CoTaskMemFree(szPolicyName);
|
||
|
|
||
|
return RemapErrorCode(hr, szParentPath);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT DeleteRepository(LPOLESTR szParentPath, LPOLESTR szStoreName)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
HANDLE hADsParent = NULL;
|
||
|
HANDLE hADsContainer = NULL;
|
||
|
WCHAR * szFullName = NULL;
|
||
|
|
||
|
hr = ADSIOpenDSObject(szParentPath, NULL, NULL, ADS_SECURE_AUTHENTICATION,
|
||
|
&hADsParent);
|
||
|
RETURN_ON_FAILURE(hr);
|
||
|
|
||
|
hr = BuildADsPathFromParent(szParentPath, szStoreName, &szFullName);
|
||
|
|
||
|
hr = ADSIOpenDSObject(szFullName, NULL, NULL, ADS_SECURE_AUTHENTICATION,
|
||
|
&hADsContainer);
|
||
|
FreeADsMem(szFullName);
|
||
|
ERROR_ON_FAILURE(hr);
|
||
|
|
||
|
ADSIDeleteDSObject(hADsContainer, CATEGORYCONTAINERNAME);
|
||
|
ADSIDeleteDSObject(hADsContainer, CLASSCONTAINERNAME);
|
||
|
ADSIDeleteDSObject(hADsContainer, PACKAGECONTAINERNAME);
|
||
|
ADSICloseDSObject(hADsContainer);
|
||
|
|
||
|
ADSIDeleteDSObject(hADsParent, szStoreName);
|
||
|
ADSICloseDSObject(hADsParent);
|
||
|
|
||
|
return S_OK;
|
||
|
|
||
|
Error_Cleanup:
|
||
|
if (hADsContainer)
|
||
|
ADSICloseDSObject(hADsContainer);
|
||
|
if (hADsParent)
|
||
|
ADSICloseDSObject(hADsParent);
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT GetRootPath(LPOLESTR szContainer)
|
||
|
{
|
||
|
HRESULT hr = S_OK;
|
||
|
ULONG cGot = 0;
|
||
|
HANDLE hADs = NULL;
|
||
|
LPOLESTR AttrName = {L"defaultNamingContext"}, pDN = NULL;
|
||
|
ADS_ATTR_INFO * pAttr = NULL;
|
||
|
|
||
|
szContainer[0] = L'\0';
|
||
|
|
||
|
//
|
||
|
// Do a bind to the machine by a GetObject for the Path
|
||
|
//
|
||
|
hr = ADSIOpenDSObject(L"LDAP://rootdse", NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_FAST_BIND,
|
||
|
&hADs);
|
||
|
RETURN_ON_FAILURE(hr);
|
||
|
|
||
|
hr = ADSIGetObjectAttributes(hADs, &AttrName, 1, &pAttr, &cGot);
|
||
|
|
||
|
if (SUCCEEDED(hr) && (cGot))
|
||
|
UnpackStrFrom(pAttr[0], &pDN);
|
||
|
else
|
||
|
pDN = L"\0";
|
||
|
|
||
|
wsprintf(szContainer, L"%s%s", LDAPPREFIX, pDN);
|
||
|
|
||
|
ADSICloseDSObject(hADs);
|
||
|
|
||
|
if (pAttr)
|
||
|
FreeADsMem(pAttr);
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
|