/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
RegDSAPI.cpp
Abstract:
Sample Provider Registry DS APIs
Author:
Environment:
User mode
Revision History :
--*/
#include "adssmp.h"
#pragma hdrstop
#include "string.h"
#define SAMPLEDS_REGDSPATH L"SOFTWARE\\Microsoft\\ADs\\SampleDS\\DS"
#define SAMPLEDS_REGSCHEMAPATH L"SOFTWARE\\Microsoft\\ADs\\SampleDS\\Schema"
#define SAMPLEDS_REG_TYPE L"TYPE"
#define SAMPLEDS_REG_MANPROP L"Mandatory Properties"
#define SAMPLEDS_REG_PROPERTY L"PROPERTY"
#define SAMPLEDS_REG_CLASS L"CLASS"
#define SAMPLEDS_REG_SYNTAX L"Syntax"
/*++
Routine Description:
Open an object in the DS. Class of the object is also returned
in szClass if the parameter is not NULL.
Arguments:
szClass will be used to store the object class if it is not NULL.
szClass has to be a LPWSTR of length MAX_PATH.
Return Value:
--*/
HRESULT
SampleDSOpenObject(
LPWSTR szRegPath,
HANDLE *phKey,
LPWSTR szClass,
DWORD dwType
)
{
if (!szRegPath ||
!phKey)
RRETURN(E_FAIL);
WCHAR szFullRegPath[MAX_PATH] = L"";
switch (dwType) {
case REG_DS:
wcscpy(
szFullRegPath,
SAMPLEDS_REGDSPATH
);
break;
case REG_SCHEMA:
wcscpy(
szFullRegPath,
SAMPLEDS_REGSCHEMAPATH
);
break;
default:
RRETURN(E_FAIL);
};
if (*szRegPath != L'\0')
wcscat(szFullRegPath,
szRegPath
);
if (RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
szFullRegPath,
0,
KEY_ALL_ACCESS,
(PHKEY)phKey
) != ERROR_SUCCESS) {
RRETURN(E_FAIL);
}
if (szClass){
DWORD dwDataType;
DWORD dwClass = MAX_PATH * sizeof(WCHAR);
if (RegQueryValueEx(
(HKEY)*phKey,
SAMPLEDS_REG_TYPE,
NULL,
&dwDataType,
(BYTE*)szClass,
&dwClass
) != ERROR_SUCCESS) {
goto Error;
}
if (dwDataType != REG_SZ) {
goto Error;
}
}
RRETURN(S_OK);
Error:
RegCloseKey((HKEY)*phKey);
RRETURN (E_FAIL);
}
/*++
Routine Description:
Close an object in the DS
Arguments:
Return Value:
--*/
HRESULT
SampleDSCloseObject(
HANDLE hKey
)
{
if (RegCloseKey((HKEY)hKey
) != ERROR_SUCCESS)
RRETURN(E_FAIL);
RRETURN(S_OK);
}
/*++
Routine Description:
Setup the enumeration handle of the objects in the DS
Arguments:
Return Value:
--*/
HRESULT
SampleDSRDNEnum(
HANDLE *phEnum,
HANDLE hContainerKey
)
{
if (!phEnum)
RRETURN(E_FAIL);
LPREGDS_ENUM lprdsenum = new REGDS_ENUM;
if (lprdsenum == NULL)
RRETURN(E_OUTOFMEMORY);
HANDLE hKey = hContainerKey;
if (hKey == NULL) {
if ( SampleDSOpenObject(L"",
&hKey,
NULL,
REG_DS
) != ERROR_SUCCESS) {
goto Error;
}
}
lprdsenum->dwIndex = 0;
lprdsenum->hContainerKey= hKey;
*((LPREGDS_ENUM *) phEnum) = lprdsenum;
RRETURN(S_OK);
Error:
delete lprdsenum;
*phEnum = NULL;
RRETURN(E_FAIL);
}
/*++
Routine Description:
Get the next object in the DS using the enumeration handle created
by SampleDSRDNRnum
Arguments:
Return Value:
--*/
HRESULT
SampleDSNextRDN(
HANDLE hEnum,
LPWSTR *pszName,
LPWSTR *pszClass
)
{
HRESULT hr = E_FAIL;
DWORD dwName = MAX_PATH;
LRESULT lResult;
FILETIME ftLastWrite;
if (!hEnum || !pszName)
RRETURN(hr);
*pszName = (LPWSTR) AllocProvMem(sizeof(WCHAR)*dwName);
if (*pszName == NULL)
RRETURN(E_OUTOFMEMORY);
lResult = RegEnumKeyEx(
(HKEY)LPREGDS_ENUM(hEnum)->hContainerKey,
LPREGDS_ENUM(hEnum)->dwIndex,
*pszName,
&dwName,
0,
NULL,
NULL,
&ftLastWrite
);
if (lResult != ERROR_SUCCESS) {
if (lResult == ERROR_NO_MORE_ITEMS)
hr = S_FALSE; // Not an error, no items left
goto Error;
} else {
LPREGDS_ENUM(hEnum)->dwIndex++;
if (pszClass != NULL) {
DWORD dwClass = MAX_PATH;
*pszClass = (LPWSTR) AllocProvMem(sizeof(WCHAR)*dwClass);
if (*pszClass == NULL) {
hr = E_OUTOFMEMORY;
goto Error;
}
if (SampleDSGetTypeText(
(HKEY)LPREGDS_ENUM(hEnum)->hContainerKey,
*pszName,
*pszClass,
&dwClass
) != S_OK) {
goto Error;
}
}
}
RRETURN(S_OK);
Error:
if (*pszName) {
FreeProvMem(*pszName);
*pszName = NULL;
}
if (*pszClass) {
FreeProvMem(*pszClass);
*pszClass = NULL;
}
RRETURN(hr);
}
/*++
Routine Description:
Free the enumeration handle
Arguments:
Return Value:
--*/
HRESULT
SampleDSFreeEnum(HANDLE hEnum)
{
if (!hEnum)
RRETURN(E_FAIL);
LPREGDS_ENUM lprdsenum = (LPREGDS_ENUM)hEnum;
if (lprdsenum->hContainerKey) {
SampleDSCloseObject(lprdsenum->hContainerKey);
}
delete lprdsenum;
RRETURN(S_OK);
}
/*++
Routine Description:
Modify properties of an object in the DS
Arguments:
Return Value:
--*/
HRESULT
SampleDSModifyObject(HANDLE hKey,
HANDLE hOperationData
)
{
if (!hKey)
RRETURN(E_FAIL);
if (!hOperationData)
RRETURN(S_OK);
LPSampleDS_ATTRS_INFO pAttrsInfo = (LPSampleDS_ATTRS_INFO)hOperationData;
LPSampleDS_ATTR_INFO pInfo = pAttrsInfo->pAttrInfo;
DWORD cAttrInfo = pAttrsInfo->dwAttr;
BYTE* pbData;
DWORD dwData;
DWORD dwType;
for (DWORD i = 0;i < cAttrInfo;i++) {
switch (pInfo->dwSyntaxId) {
case SampleDS_DATATYPE_1:
{
SampleDS_TYPE_1* pData = (SampleDS_TYPE_1*)pInfo->lpValue;
pbData = (BYTE*)pData->DNString;
dwData = (wcslen(pData->DNString) + 1) * sizeof(WCHAR);
dwType = REG_SZ;
break;
}
case SampleDS_DATATYPE_2:
{
SampleDS_TYPE_2* pData = (SampleDS_TYPE_2*)pInfo->lpValue;
pbData = (BYTE*)&(pData->Integer);
dwData = sizeof(DWORD);
dwType = REG_DWORD;
break;
}
default:
RRETURN(E_FAIL);
}
if (RegSetValueEx(
(HKEY)hKey,
pInfo->lpAttributeName,
NULL,
dwType,
pbData,
dwData
) != ERROR_SUCCESS)
RRETURN(E_FAIL);
pInfo++;
}
RRETURN(NO_ERROR);
}
/*++
Routine Description:
Read the properties of an object in the DS
Arguments:
Return Value:
--*/
HRESULT
SampleDSReadObject(
HANDLE hkey,
HANDLE *phOperationData
)
{
DWORD cValues;
LPSampleDS_ATTR_INFO pInfo = NULL;
DWORD i;
LPWSTR pszValue = NULL;
BYTE* pbData = NULL;
DWORD cProp = 0;
if (RegQueryInfoKey(
(HKEY)hkey,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
&cValues,
NULL,
NULL,
NULL,
NULL
) != ERROR_SUCCESS) {
RRETURN(E_FAIL);
};
if (cValues == 0) {
*phOperationData = NULL;
RRETURN(NO_ERROR);
}
DWORD dwData;
DWORD dwValue;
pInfo = (LPSampleDS_ATTR_INFO)AllocProvMem(
sizeof(SampleDS_ATTR_INFO)*cValues
);
if (!pInfo)
RRETURN(E_OUTOFMEMORY);
for (i = 0; i < cValues; i++) {
DWORD dwType;
pszValue = (LPWSTR)AllocProvMem(sizeof(WCHAR)*MAX_PATH);
pbData = (BYTE*)AllocProvMem(sizeof(WCHAR)*MAX_PATH);
if (pbData == NULL || pszValue == NULL)
goto Error;
dwData = sizeof(WCHAR) * MAX_PATH;
dwValue = sizeof(WCHAR) * MAX_PATH;
if (RegEnumValue(
(HKEY)hkey,
i,
pszValue,
&dwValue,
NULL,
&dwType,
pbData,
&dwData
) != ERROR_SUCCESS)
goto Error;
if (!_wcsicmp(
pszValue,
SAMPLEDS_REG_TYPE)) {
FreeProvMem(pszValue);
FreeProvMem(pbData);
continue;
};
switch (dwType) {
case REG_DWORD:
{
SampleDS_TYPE_2 *pData = NULL;
pData = (SampleDS_TYPE_2*)AllocProvMem(
sizeof(SampleDS_TYPE_2));
if (pData == NULL)
goto Error;
pInfo[cProp].lpValue = (BYTE*)pData;
pData->Integer = *(DWORD*)pbData;
pInfo[cProp].dwSyntaxId = SampleDS_DATATYPE_2;
FreeProvMem(pbData);
pbData = NULL;
break;
}
case REG_SZ:
{
SampleDS_TYPE_1 *pData = NULL;
pData = (SampleDS_TYPE_1*)AllocProvMem(
sizeof(SampleDS_TYPE_1));
if (pData == NULL)
goto Error;
pInfo[cProp].lpValue = (BYTE*)pData;
pData->DNString = (LPWSTR)pbData;
pInfo[cProp].dwSyntaxId = SampleDS_DATATYPE_1;
break;
}
default:
goto Error;
}
pInfo[cProp].lpAttributeName = pszValue;
pInfo[cProp].dwNumberOfValues = 1;
cProp++;
}
// Ownership has already been passed
pbData = NULL;
pszValue = NULL;
LPSampleDS_ATTRS_INFO pAttrsInfo;
pAttrsInfo = (LPSampleDS_ATTRS_INFO)AllocProvMem(sizeof(SampleDS_ATTRS_INFO));
if (!pAttrsInfo)
goto Error;
pAttrsInfo->pAttrInfo = pInfo;
pAttrsInfo->dwAttr = cProp;
*phOperationData = pAttrsInfo;
RRETURN(NO_ERROR);
Error:
for (DWORD j=0; j<cProp; j++) {
if (pInfo[j].lpAttributeName)
FreeProvMem(pInfo[j].lpAttributeName);
if (pInfo[j].lpValue) {
if (pInfo[j].dwSyntaxId == SampleDS_DATATYPE_1) {
if (((SampleDS_TYPE_1*)(pInfo[j].lpValue))->DNString)
FreeProvMem(((SampleDS_TYPE_1*)
(pInfo[j].lpValue))->DNString);
}
FreeProvMem(pInfo[j].lpValue);
}
}
if (pszValue)
FreeProvMem(pszValue);
if (pbData)
FreeProvMem(pbData);
FreeProvMem(pInfo);
RRETURN(E_FAIL);
}
/*++
Routine Description:
Get all the property defintions from the Schema
Arguments:
Return Value:
--*/
HRESULT
SampleDSGetPropertyDefinition(
LPSampleDS_ATTR_DEF* ppAttrDefsReturn,
DWORD *pnumObject)
{
WCHAR szRegPath[MAX_PATH] = SAMPLEDS_REGSCHEMAPATH;
DWORD numEntries;
HKEY hKey;
LPSampleDS_ATTR_DEF pAttrDefsCurrent;
LPSampleDS_ATTR_DEF pAttrDefsStart;
LPWSTR szPropNameCur;
DWORD dwPropNameCur = MAX_PATH;
DWORD numProperties = 0;
if( RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
szRegPath,
0,
KEY_ALL_ACCESS,
&hKey
) != ERROR_SUCCESS) {
RRETURN(E_FAIL);
}
if( RegQueryInfoKey(
hKey,
NULL,
NULL,
NULL,
&numEntries,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
) != ERROR_SUCCESS) {
goto Error;
}
pAttrDefsStart = (LPSampleDS_ATTR_DEF)AllocProvMem(
sizeof(SampleDS_ATTR_DEF)*numEntries);
if (!pAttrDefsStart)
goto Error;
pAttrDefsCurrent = pAttrDefsStart;
DWORD i;
for (i=0; i<numEntries; i++) {
szPropNameCur = (LPWSTR)AllocProvMem(sizeof(WCHAR)*dwPropNameCur);
if (!szPropNameCur)
goto Error;
if (RegEnumKey(
hKey,
i,
szPropNameCur,
dwPropNameCur
) != ERROR_SUCCESS)
goto Error;
if (SampleDSGetPropertyInfo(
hKey,
szPropNameCur,
pAttrDefsCurrent
) != ERROR_SUCCESS) {
FreeProvMem(szPropNameCur);
continue;
}
pAttrDefsCurrent->lpAttributeName = szPropNameCur;
numProperties++;
pAttrDefsCurrent++;
}
// Ownership has been passed
szPropNameCur = NULL;
if (numProperties != numEntries) {
LPSampleDS_ATTR_DEF pAttrDefsFinal;
pAttrDefsFinal = (LPSampleDS_ATTR_DEF)AllocProvMem(
sizeof(SampleDS_ATTR_DEF)*numProperties);
if (!pAttrDefsFinal)
goto Error;
memcpy(
(void*)pAttrDefsFinal,
(void*)pAttrDefsStart,
sizeof(SampleDS_ATTR_DEF)*numProperties
);
*ppAttrDefsReturn = pAttrDefsFinal;
FreeProvMem(pAttrDefsStart);
}
else {
*ppAttrDefsReturn = pAttrDefsStart;
}
*pnumObject = numProperties;
RegCloseKey(hKey);
RRETURN(S_OK);
Error:
RegCloseKey(hKey);
LPSampleDS_ATTR_DEF pAttrDefsDelete = pAttrDefsStart;
for (DWORD j=0; j<numProperties; j++) {
if (pAttrDefsDelete->lpAttributeName)
FreeProvMem(pAttrDefsDelete->lpAttributeName);
pAttrDefsDelete++;
}
if (szPropNameCur)
FreeProvMem(szPropNameCur);
if (pAttrDefsStart)
FreeProvMem(pAttrDefsStart);
RRETURN(E_FAIL);
}
/*++
Routine Description:
Get a particular property defintion from the schema
Arguments:
Return Value:
--*/
HRESULT
SampleDSGetPropertyDefinition(
LPSampleDS_ATTR_DEF* ppAttrDefReturn,
LPWSTR szPropName)
{
WCHAR szRegPath[MAX_PATH] = SAMPLEDS_REGSCHEMAPATH;
DWORD numEntries;
HKEY hKey;
LPSampleDS_ATTR_DEF pAttrDefCurrent;
LPWSTR szPropNameCur;
DWORD i;
if( RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
szRegPath,
0,
KEY_ALL_ACCESS,
&hKey
) != ERROR_SUCCESS) {
RRETURN(E_FAIL);
}
if( RegQueryInfoKey(
hKey,
NULL,
NULL,
NULL,
&numEntries,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
) != ERROR_SUCCESS) {
goto Error;
}
pAttrDefCurrent= (LPSampleDS_ATTR_DEF)AllocProvMem(
sizeof(SampleDS_ATTR_DEF));
if (!pAttrDefCurrent)
goto Error;
szPropNameCur = (LPWSTR)AllocProvMem(sizeof(WCHAR)*MAX_PATH);
if (!szPropNameCur)
goto Error;
for (i=0; i<numEntries; i++) {
if (RegEnumKey(hKey,
i,
szPropNameCur,
MAX_PATH) != ERROR_SUCCESS)
goto Error;
if (!_wcsicmp(
szPropNameCur,
szPropName)) {
if (SampleDSGetPropertyInfo(
hKey,
szPropNameCur,
pAttrDefCurrent
) != ERROR_SUCCESS)
goto Error;
pAttrDefCurrent->lpAttributeName = szPropNameCur;
*ppAttrDefReturn = pAttrDefCurrent;
RegCloseKey(hKey);
RRETURN(S_OK);
}
}
Error:
RegCloseKey(hKey);
if (szPropNameCur)
FreeProvMem(szPropNameCur);
if (pAttrDefCurrent)
FreeProvMem(pAttrDefCurrent);
RRETURN(E_FAIL);
}
/*++
Routine Description:
Free memory allocated by GetPropertyDefinition
Arguments:
Return Value:
--*/
HRESULT
SampleDSFreePropertyDefinition(LPSampleDS_ATTR_DEF pAttrDefs,
DWORD numObject)
{
if (!pAttrDefs)
RRETURN(E_FAIL);
LPSampleDS_ATTR_DEF pAttrDefCurrent = pAttrDefs;
for (DWORD j=0; j<numObject; j++) {
if (pAttrDefCurrent->lpAttributeName)
FreeProvMem(pAttrDefCurrent->lpAttributeName);
pAttrDefCurrent++;
}
FreeProvMem(pAttrDefs);
RRETURN(S_OK);
}
/*++
Routine Description:
Get the type of an object in text format
Arguments:
Return Value:
--*/
HRESULT
SampleDSGetTypeText(HKEY hKey,
LPWSTR szPropertyName,
LPWSTR szClassName,
DWORD *pdwClassName)
{
HKEY hKeyProperty;
if (RegOpenKey(
hKey,
szPropertyName,
&hKeyProperty
) != ERROR_SUCCESS) {
RRETURN(E_FAIL);
}
DWORD dwType;
if (RegQueryValueEx(
hKeyProperty,
SAMPLEDS_REG_TYPE,
NULL,
&dwType,
(BYTE*)szClassName,
pdwClassName
) != ERROR_SUCCESS) {
goto Error;
}
if (dwType != REG_SZ) {
goto Error;
}
RegCloseKey(hKeyProperty);
RRETURN(S_OK);
Error:
RegCloseKey(hKeyProperty);
RRETURN(E_FAIL);
}
/*++
Routine Description:
Get the type of an object
Arguments:
Return Value:
--*/
HRESULT
SampleDSGetType(HKEY hKey,
LPWSTR szPropertyName,
DWORD *pdwType)
{
HRESULT hrReturn = S_OK;
LPWSTR szClassName;
DWORD dwClassName = MAX_PATH * sizeof(WCHAR);
szClassName = (LPWSTR)AllocProvMem(dwClassName);
if (!szClassName) {
hrReturn = E_OUTOFMEMORY;
goto Error;
}
if (SampleDSGetTypeText(
hKey,
szPropertyName,
szClassName,
&dwClassName
) == E_FAIL) {
hrReturn = E_FAIL;
goto Error;
}
if (!_wcsicmp(
szClassName,
SAMPLEDS_REG_PROPERTY)) {
*pdwType = SAMPLEDS_PROPERTY;
}
else if (!_wcsicmp(
szClassName,
SAMPLEDS_REG_CLASS)) {
*pdwType = SAMPLEDS_CLASS;
}
else {
*pdwType = SAMPLEDS_UNKNOWN;
}
Error:
if (szClassName)
FreeProvMem(szClassName);
RRETURN(hrReturn);
}
/*++
Routine Description:
Get information about a property from the schema
Arguments:
Return Value:
--*/
HRESULT
SampleDSGetPropertyInfo(HKEY hKey,
LPWSTR szPropertyName,
LPSampleDS_ATTR_DEF pAttrDef)
{
HKEY hKeyClass;
DWORD dwSyntax;
DWORD dwType;
DWORD dwSyntaxSize = sizeof(DWORD);
DWORD dwSchemaType;
if ((SampleDSGetType(
hKey,
szPropertyName,
&dwSchemaType
) == E_FAIL) ||
(dwSchemaType != SAMPLEDS_PROPERTY))
RRETURN(E_FAIL);
if (RegOpenKeyEx(
hKey,
szPropertyName,
NULL,
KEY_READ,
&hKeyClass
) != ERROR_SUCCESS)
RRETURN(E_FAIL);
if (RegQueryValueEx(
hKeyClass,
SAMPLEDS_REG_SYNTAX,
NULL,
&dwType,
(BYTE*)&dwSyntax,
&dwSyntaxSize
) == ERROR_SUCCESS) {
pAttrDef->dwSyntaxID = dwSyntax;
RegCloseKey(hKeyClass);
RRETURN(S_OK);
}
RegCloseKey(hKeyClass);
RRETURN(E_FAIL);
}
/*++
Routine Description:
Free the memory used by a LPWSTR_LIST
Arguments:
Return Value:
--*/
void FreeList(LPWSTR_LIST pList)
{
if (pList) {
if (pList->lpString) {
FreeProvStr(pList->lpString);
}
FreeList(pList->Next);
FreeProvMem(pList);
};
}
/*++
Routine Description:
Arguments:
Return Value:
--*/
HRESULT
SampleDSGetClassDefinition(
LPSampleDS_CLASS_DEF* ppClassDefsReturn,
DWORD *pnumObject)
{
WCHAR szRegPath[MAX_PATH] = SAMPLEDS_REGSCHEMAPATH;
DWORD numEntries;
HKEY hKey;
LPSampleDS_CLASS_DEF pClassDefsCurrent;
LPSampleDS_CLASS_DEF pClassDefsStart;
LPWSTR szClassName;
DWORD dwClassName = MAX_PATH;
DWORD numClass = 0;
if( RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
szRegPath,
0,
KEY_ALL_ACCESS,
&hKey
) != ERROR_SUCCESS) {
RRETURN(E_FAIL);
}
if( RegQueryInfoKey(
hKey,
NULL,
NULL,
NULL,
&numEntries,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
) != ERROR_SUCCESS) {
goto Error;
}
pClassDefsStart = (LPSampleDS_CLASS_DEF)AllocProvMem(
sizeof(SampleDS_CLASS_DEF)*numEntries);
if (!pClassDefsStart)
goto Error;
pClassDefsCurrent = pClassDefsStart;
DWORD i;
for (i=0; i<numEntries; i++) {
szClassName = (LPWSTR)AllocProvMem(sizeof(WCHAR)*dwClassName);
if (!szClassName)
goto Error;
if (RegEnumKey(
hKey,
i,
szClassName,
dwClassName
) != ERROR_SUCCESS)
goto Error;
if (SampleDSGetClassInfo(
hKey,
szClassName,
pClassDefsCurrent
) != ERROR_SUCCESS) {
FreeProvMem(szClassName);
continue;
}
pClassDefsCurrent->lpClassName = szClassName;
numClass++;
pClassDefsCurrent++;
}
szClassName = NULL;
if (numClass != numEntries) {
LPSampleDS_CLASS_DEF pClassDefsFinal;
pClassDefsFinal = (LPSampleDS_CLASS_DEF)AllocProvMem(
sizeof(SampleDS_CLASS_DEF)*numClass);
if (!pClassDefsFinal)
goto Error;
memcpy(
(void*)pClassDefsFinal,
(void*)pClassDefsStart,
sizeof(SampleDS_CLASS_DEF)*numClass
);
*ppClassDefsReturn = pClassDefsFinal;
FreeProvMem(pClassDefsStart);
}
else {
*ppClassDefsReturn = pClassDefsStart;
}
*pnumObject = numClass;
RegCloseKey(hKey);
RRETURN(S_OK);
Error:
RegCloseKey(hKey);
LPSampleDS_CLASS_DEF pClassDefsDelete = pClassDefsStart;
DWORD j;
for (j=0; j<numClass; j++) {
if (pClassDefsDelete->lpClassName)
FreeProvMem(pClassDefsDelete->lpClassName);
if (pClassDefsDelete->lpMandatoryAttributes)
FreeList(pClassDefsDelete->lpMandatoryAttributes);
pClassDefsDelete++;
}
if (szClassName)
FreeProvMem(szClassName);
if (pClassDefsStart)
FreeProvMem(pClassDefsStart);
RRETURN(E_FAIL);
}
/*++
Routine Description:
Get the class defintion for a particular class
Arguments:
Return Value:
--*/
HRESULT
SampleDSGetClassDefinition(
LPSampleDS_CLASS_DEF* ppClassDefReturn,
LPWSTR szClassName)
{
WCHAR szRegPath[MAX_PATH] = SAMPLEDS_REGSCHEMAPATH;
DWORD numEntries;
HKEY hKey;
LPSampleDS_CLASS_DEF pClassDefCurrent;
LPWSTR szClassNameCurrent;
DWORD i;
if( RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
szRegPath,
0,
KEY_ALL_ACCESS,
&hKey
) != ERROR_SUCCESS) {
RRETURN(E_FAIL);
}
if( RegQueryInfoKey(
hKey,
NULL,
NULL,
NULL,
&numEntries,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
) != ERROR_SUCCESS) {
goto Error;
}
pClassDefCurrent= (LPSampleDS_CLASS_DEF)AllocProvMem(
sizeof(SampleDS_CLASS_DEF));
if (!pClassDefCurrent)
goto Error;
szClassNameCurrent = (LPWSTR)AllocProvMem(sizeof(WCHAR)*MAX_PATH);
if (!szClassNameCurrent)
goto Error;
for (i=0; i<numEntries; i++) {
if (RegEnumKey(hKey,
i,
szClassNameCurrent,
MAX_PATH) != ERROR_SUCCESS)
goto Error;
if (!_wcsicmp(szClassNameCurrent,szClassName)) {
if (SampleDSGetClassInfo(
hKey,
szClassNameCurrent,
pClassDefCurrent
) != ERROR_SUCCESS)
goto Error;
pClassDefCurrent->lpClassName = szClassNameCurrent;
*ppClassDefReturn = pClassDefCurrent;
RegCloseKey(hKey);
RRETURN(S_OK);
}
}
Error:
RegCloseKey(hKey);
if (szClassNameCurrent)
FreeProvMem(szClassNameCurrent);
if (pClassDefCurrent)
FreeProvMem(pClassDefCurrent);
RRETURN(E_FAIL);
}
/*++
Routine Description:
Free memory allocated by GetClassDefinition
Arguments:
Return Value:
--*/
HRESULT
SampleDSFreeClassDefinition(LPSampleDS_CLASS_DEF pClassDefs,
DWORD numObject)
{
if (!pClassDefs)
RRETURN(E_FAIL);
LPSampleDS_CLASS_DEF pClassDefCurrent = pClassDefs;
for (DWORD j=0; j<numObject; j++) {
if (pClassDefCurrent->lpClassName)
FreeProvMem(pClassDefCurrent->lpClassName);
if (pClassDefCurrent->lpMandatoryAttributes)
FreeList(pClassDefCurrent->lpMandatoryAttributes);
pClassDefCurrent++;
}
FreeProvMem(pClassDefs);
RRETURN(S_OK);
}
/*++
Routine Description:
Get the next token in a REG_MULTISZ string returned by the
Regsitry getvalue function
Arguments:
Return Value:
--*/
LPWSTR nexttoken(LPWSTR szCurrent)
{
static LPWSTR szRemainder = NULL;
LPWSTR szReturn = NULL;
if (szCurrent) {
szRemainder = szCurrent;
}
else if (szRemainder == NULL) {
return NULL;
}
if (*szRemainder) {
szReturn = szRemainder;
while (*++szRemainder);
szRemainder++;
}
return szReturn;
}
/*++
Routine Description:
Get information about a particular class from the schema
Arguments:
Return Value:
--*/
HRESULT
SampleDSGetClassInfo(HKEY hKey,
LPWSTR szClassName,
LPSampleDS_CLASS_DEF pClassDef)
{
HKEY hKeyClass;
DWORD dwType;
LPWSTR szProperties;
DWORD dwProperties = MAX_PATH * 3;
LPWSTR_LIST pListStart = NULL;
DWORD dwManProp = 0;
LPWSTR_LIST pListCurrent = NULL;
LPWSTR szPropCurrent = NULL;
LPWSTR szProperty = NULL;
LPWSTR szPropertyNew = NULL;
DWORD dwSchemaType;
if ((SampleDSGetType(
hKey,
szClassName,
&dwSchemaType) == E_FAIL) ||
(dwSchemaType != SAMPLEDS_CLASS))
RRETURN(E_FAIL);
if (RegOpenKeyEx(
hKey,
szClassName,
NULL,
KEY_READ,
&hKeyClass
) != ERROR_SUCCESS)
RRETURN(E_FAIL);
szProperties= (LPWSTR)AllocProvMem(sizeof(WCHAR)*dwProperties);
if (!szProperties)
goto Error;
if (RegQueryValueEx(
hKeyClass,
SAMPLEDS_REG_MANPROP,
NULL,
&dwType,
(BYTE*)szProperties,
&dwProperties
) != ERROR_SUCCESS) {
goto Error;
}
if (dwType != REG_MULTI_SZ) {
goto Error;
}
szPropCurrent = szProperties;
szProperty = nexttoken(szPropCurrent);
szPropertyNew;
if (szProperty) {
pListStart = (LPWSTR_LIST)AllocProvMem(sizeof(WSTR_LIST));
if (!pListStart)
goto Error;
pListCurrent = pListStart;
szPropertyNew = AllocProvStr(szProperty);
if (!szPropertyNew)
goto Error;
pListCurrent->lpString = szPropertyNew;
szProperty = nexttoken(NULL);
dwManProp++;
while( szProperty != NULL ) {
LPWSTR_LIST pListNew = (LPWSTR_LIST)AllocProvMem(
sizeof(WSTR_LIST));
if (!pListNew)
goto Error;
pListCurrent->Next = pListNew;
szPropertyNew = AllocProvStr(szProperty);
if (!szPropertyNew)
goto Error;
pListNew->lpString = szPropertyNew;
pListCurrent = pListNew;
szProperty = nexttoken(NULL);
dwManProp++;
}
pListCurrent->Next = NULL;
}
pClassDef->lpMandatoryAttributes = pListStart;
pClassDef->dwNumberOfMandatoryAttributes = dwManProp;
RegCloseKey(hKeyClass);
RRETURN(S_OK);
Error:
RegCloseKey(hKeyClass);
if (pListStart)
FreeList(pListStart);
if (szProperties)
FreeProvMem(szProperties);
RRETURN(E_FAIL);
}
/*++
Routine Description:
Add an object in the DS
Arguments:
Return Value:
--*/
HRESULT
SampleDSAddObject(HANDLE hKey,
LPWSTR szObject,
LPWSTR szClass,
HANDLE hOperationData
)
{
if (!szObject || !szClass || !hKey)
RRETURN(E_FAIL);
HKEY hKeyNew;
if (RegCreateKey(
(HKEY)hKey,
szObject,
&hKeyNew
) != ERROR_SUCCESS) {
RRETURN(E_FAIL);
};
if (RegSetValueEx(
hKeyNew,
SAMPLEDS_REG_TYPE,
NULL,
REG_SZ,
(BYTE*)szClass,
(wcslen(szClass) + 1) * sizeof(WCHAR)
) != ERROR_SUCCESS) {
RRETURN(E_FAIL);
};
if (hOperationData) {
if (SampleDSModifyObject(
hKeyNew,
hOperationData
) != S_OK) {
RRETURN(E_FAIL);
};
};
RRETURN(S_OK);
}
/*++
Routine Description:
Delete a registry key and all its subkeys
Arguments:
Return Value:
--*/
LONG RegDeleteAllKeys(HKEY hKeyDelete,
LPWSTR pszSubKey)
{
HKEY hKeyChild;
TCHAR szTmp[MAX_PATH];
LONG lResult;
DWORD dwTmpSize = MAX_PATH;
lResult = RegOpenKeyEx(
hKeyDelete,
pszSubKey,
NULL,
KEY_ALL_ACCESS,
&hKeyChild
);
if (lResult != ERROR_SUCCESS)
return lResult;
lResult = RegEnumKey(
hKeyChild,
0,
szTmp,
dwTmpSize
);
while (lResult != ERROR_NO_MORE_ITEMS) {
RegDeleteAllKeys(
hKeyChild,
szTmp
);
lResult = RegEnumKey(
hKeyChild,
0,
szTmp,
dwTmpSize
);
}
RegCloseKey(hKeyChild);
lResult = RegDeleteKey(
hKeyDelete,
pszSubKey
);
return lResult;
}
/*++
Routine Description:
Remove an object from the DS
Arguments:
Return Value:
--*/
HRESULT
SampleDSRemoveObject(HANDLE hKey,
LPWSTR szObject)
{
if (RegDeleteAllKeys(
(HKEY)hKey,
szObject
) == ERROR_SUCCESS)
RRETURN(S_OK);
else
RRETURN(E_FAIL);
}
/*++
Routine Description:
Create Memory Buffer for operation data
Arguments:
Return Value:
--*/
HRESULT
SampleDSCreateBuffer(HANDLE *phOperationData)
{
LPSampleDS_ATTRS_INFO pAttrsInfo;
pAttrsInfo = (LPSampleDS_ATTRS_INFO)AllocProvMem(sizeof(SampleDS_ATTRS_INFO));
if (!pAttrsInfo)
RRETURN(E_OUTOFMEMORY);
*phOperationData = pAttrsInfo;
RRETURN(S_OK);
}
/*++
Routine Description:
Free memroy pointed to by operationdata
Arguments:
Return Value:
--*/
HRESULT
SampleDSFreeBuffer(HANDLE hOperationData)
{
if (!hOperationData)
RRETURN(E_FAIL);
LPSampleDS_ATTRS_INFO pAttrsInfo;
pAttrsInfo = (LPSampleDS_ATTRS_INFO)hOperationData;
LPSampleDS_ATTR_INFO pAttrInfo;
DWORD cAttr;
pAttrInfo = pAttrsInfo->pAttrInfo;
cAttr = pAttrsInfo->dwAttr;
if (pAttrInfo) {
for (DWORD i = 0;i<cAttr;i++) {
if (pAttrInfo->lpAttributeName)
FreeProvMem(pAttrInfo->lpAttributeName);
if (pAttrInfo->lpValue) {
if (pAttrInfo->dwSyntaxId == SampleDS_DATATYPE_1) {
if (((SampleDS_TYPE_1*)(pAttrInfo->lpValue))->DNString)
FreeProvMem(((SampleDS_TYPE_1*)
(pAttrInfo->lpValue))->DNString);
}
FreeProvMem(pAttrInfo->lpValue);
}
pAttrInfo++;
}
}
FreeProvMem(pAttrsInfo->pAttrInfo);
FreeProvMem(pAttrsInfo);
RRETURN(S_OK);
}