|
|
//================================================================================
// Copyright (C) 1997 Microsoft Corporation
// Author: RameshV (critical code borrowed from shirish koti)
// Description: This makes somethings easy for accessing the DS.
//================================================================================
#include <hdrmacro.h>
#include <sterr.h> // error reporting stuff
enum /* anonymous */ { REPEATED_ADDRESS1 = 0x01, // dont start error code with zero!
REPEATED_ADDRESS2, REPEATED_ADDRESS3, INVALID_ADDRESS1, INVALID_ADDRESS2, INVALID_ADDRESS3, REPEATED_ADSPATH, INVALID_ADSPATH, REPEATED_FLAGS1, REPEATED_FLAGS2, INVALID_FLAGS1, INVALID_FLAGS2, REPEATED_DWORD1, REPEATED_DWORD2, INVALID_DWORD1, INVALID_DWORD2, REPEATED_STRING1, REPEATED_STRING2, REPEATED_STRING3, REPEATED_STRING4, INVALID_STRING1, INVALID_STRING2, INVALID_STRING3, INVALID_STRING4, REPEATED_BINARY1, REPEATED_BINARY2, INVALID_BINARY1, INVALID_BINARY2, INVALID_ATTRIB_FIELD, INVALID_BINARY_CODING, UNEXPECTED_COLLECTION_TYPE, UNEXPECTED_INTERNAL_ERROR, };
//
// Constants
//
// Retrive 256 rows per query
#define DHCPDS_DS_SEARCH_PAGESIZE 256
//================================================================================
// structures
//================================================================================
//BeginExport(typedef)
typedef struct _STORE_HANDLE { // this is what is used almost always
DWORD MustBeZero; // for future use
LPWSTR Location; // where does this refer to?
LPWSTR UserName; // who is the user?
LPWSTR Password; // what is the password?
DWORD AuthFlags; // what permission was this opened with?
HANDLE ADSIHandle; // handle to within ADSI
ADS_SEARCH_HANDLE SearchHandle; // any searches going on?
LPVOID Memory; // memory allocated for this call..
DWORD MemSize; // how much was really allocated?
BOOL SearchStarted; // Did we start the search?
} STORE_HANDLE, *LPSTORE_HANDLE, *PSTORE_HANDLE; //EndExport(typedef)
LPWSTR _inline MakeRootDSEString( // given DSDC or domain name, produce ROOT DSE name
IN LPWSTR Server ) { LPWSTR RootDSE;
if( NULL == Server ) { RootDSE = MemAlloc( sizeof(DEFAULT_LDAP_ROOTDSE) ) ; if( NULL == RootDSE ) return NULL; wcscpy(RootDSE, DEFAULT_LDAP_ROOTDSE); return RootDSE; }
RootDSE = MemAlloc(sizeof(LDAP_PREFIX) + SizeString(Server,FALSE) + sizeof(ROOTDSE_POSTFIX)); if( NULL == RootDSE ) return NULL;
wcscpy(RootDSE, LDAP_PREFIX); wcscat(RootDSE, Server); wcscat(RootDSE, ROOTDSE_POSTFIX);
return RootDSE; }
LPWSTR _inline MakeServerLocationString( IN LPWSTR Server, IN LPWSTR Location ) { LPWSTR RetVal;
Require(Location);
RetVal = MemAlloc(sizeof(LDAP_PREFIX) + sizeof(WCHAR) + SizeString(Server,FALSE) + SizeString(Location,FALSE)); if( NULL == RetVal ) return NULL;
wcscpy(RetVal, LDAP_PREFIX); if( NULL != Server ) { wcscat(RetVal, Server); wcscat(RetVal, L"/"); } wcscat(RetVal, Location);
return RetVal; }
HRESULT GetEnterpriseRootFromRootHandle( // given /ROOTDSE object handle, get enterprise config root handle..
IN HANDLE DSERootHandle, IN LPWSTR Server, IN LPWSTR UserName, IN LPWSTR Password, IN DWORD AuthFlags, IN OUT LPWSTR *RootLocation, IN OUT HANDLE *hRoot ) { HRESULT hResult; DWORD Chk; DWORD i, j; DWORD nAttributes; PADS_ATTR_INFO Attributes; BOOL Found;
*RootLocation = NULL; hResult = ADSIGetObjectAttributes( DSERootHandle, (LPWSTR *)&constNamingContextString, 1, &Attributes, &nAttributes );
if( FAILED(hResult) ) return hResult; if( 0 == nAttributes ) { return E_ADS_PROPERTY_NOT_FOUND; }
Found = FALSE; for( i = 0; i < Attributes->dwNumValues ; i ++ ) { if( Attributes->pADsValues[i].dwType != ADSTYPE_CASE_IGNORE_STRING && Attributes->pADsValues[i].dwType != ADSTYPE_DN_STRING ) continue;
Chk = _wcsnicmp( ENT_ROOT_PREFIX, Attributes->pADsValues[i].CaseIgnoreString, ENT_ROOT_PREFIX_LEN ); if( 0 == Chk ) break; }
if( i < Attributes->dwNumValues ) { *RootLocation = MakeServerLocationString( Server, Attributes->pADsValues[i].CaseIgnoreString ); Found = TRUE; }
FreeADsMem(Attributes); if( FALSE == Found ) return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); if( NULL == *RootLocation ) return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
hResult = ADSIOpenDSObject( *RootLocation, UserName, Password, AuthFlags, hRoot );
if( SUCCEEDED(hResult) ) return S_OK;
MemFree(*RootLocation); *RootLocation = NULL; return hResult; }
DWORD GetEnterpriseRootObject( // get the /ROOTDSE object's naming context object..
IN LPWSTR Server, // domain controller name or domain dns name
IN LPWSTR UserName, IN LPWSTR Password, IN DWORD AuthFlags, IN OUT LPWSTR *RootLocation, // what is the value of the nameingContext attrib that we used?
IN OUT HANDLE *hRoot // handle to the above object..
) { DWORD Result; LPWSTR RootDSEString; LPWSTR RootEnterpriseString; HANDLE hRootDSE; HRESULT hResult;
*RootLocation = NULL; *hRoot = NULL; RootDSEString = MakeRootDSEString(Server); if( NULL == RootDSEString ) return ERROR_NOT_ENOUGH_MEMORY;
hResult = ADSIOpenDSObject( RootDSEString, UserName, Password, AuthFlags, &hRootDSE ); MemFree(RootDSEString);
if( FAILED(hResult) ) return ConvertHresult(hResult);
hResult = GetEnterpriseRootFromRootHandle( hRootDSE, Server, UserName, Password, AuthFlags, RootLocation, hRoot ); ADSICloseDSObject(hRootDSE);
if( FAILED(hResult) ) return ConvertHresult(hResult);
Require(hRoot && RootLocation); return ERROR_SUCCESS; }
//================================================================================
// exported functions
//================================================================================
//BeginExport(function)
DWORD StoreInitHandle( // initialize a handle
IN OUT STORE_HANDLE *hStore, // will be filled in with stuff..
IN DWORD Reserved, // must be zero -- for future use
IN LPWSTR Domain, // OPTIONAL NULL==>default Domain
IN LPWSTR UserName, // OPTIONAL NULL==>default credentials
IN LPWSTR Password, // OPTIONAL used only if UserName given
IN DWORD AuthFlags // OPTIONAL 0 ==> default??????
) //EndExport(function)
{ DWORD Result; DWORD Size; LPWSTR EnterpriseRootLocation; HANDLE RootServer; LPBYTE Memory;
Result = GetEnterpriseRootObject( Domain, UserName, Password, AuthFlags, &EnterpriseRootLocation, &RootServer ); if( ERROR_SUCCESS != Result) return Result;
Require(RootServer && EnterpriseRootLocation);
Size = sizeof(LONG); Size += SizeString(UserName, FALSE); Size += SizeString(Password, FALSE);
Memory = MemAlloc(Size); if( NULL == Memory ) { MemFree(EnterpriseRootLocation); ADSICloseDSObject(RootServer); return ERROR_NOT_ENOUGH_MEMORY; }
hStore->MemSize = Size; Size = sizeof(LONG); hStore->MustBeZero = 0; hStore->Location = EnterpriseRootLocation; hStore->UserName = (LPWSTR)&Memory[Size]; Size += SizeString(UserName, FALSE); hStore->Password = (LPWSTR)&Memory[Size]; Size += SizeString(Password, FALSE); hStore->AuthFlags = AuthFlags; hStore->ADSIHandle = RootServer; hStore->SearchHandle = NULL; hStore->Memory = Memory;
if( NULL == UserName ) hStore->UserName = NULL; else wcscpy(hStore->UserName, UserName); if( NULL == Password ) hStore->Password = NULL; else wcscpy(hStore->Password,Password);
return ERROR_SUCCESS; }
//BeginExport(function)
DWORD StoreCleanupHandle( // cleanup the handle
IN OUT LPSTORE_HANDLE hStore, IN DWORD Reserved ) //EndExport(function)
{ DWORD Result;
AssertRet(hStore, ERROR_INVALID_PARAMETER); AssertRet(hStore->Location, ERROR_INVALID_PARAMETER);
MemFree(hStore->Location); MemFree(hStore->Memory); if(hStore->SearchHandle) ADSICloseSearchHandle(hStore->ADSIHandle, hStore->SearchHandle); ADSICloseDSObject(hStore->ADSIHandle); // memset(hStore, 0, sizeof(*hStore));
hStore->Location = NULL; hStore->UserName = NULL; hStore->Password = NULL; hStore->AuthFlags = 0; hStore->ADSIHandle = 0; hStore->Memory = NULL; hStore->MemSize = 0; // hStore->SearchStarted = FALSE;
return ERROR_SUCCESS; }
//BeginExport(enum)
enum { StoreGetChildType, StoreGetAbsoluteSameServerType, StoreGetAbsoluteOtherServerType } _StoreGetType; //EndExport(enum)
DWORD ConvertPath( // convert a "CN=X" type spec to "LDAP://Server/CN=X"..
IN LPSTORE_HANDLE hStore, // needed to get the initial strings bits
IN DWORD StoreGetType, IN LPWSTR PathIn, OUT LPWSTR *PathOut ) { DWORD Size; DWORD PrefixSize; DWORD SuffixSize; LPWSTR TmpString; LPWSTR PrefixString;
*PathOut = NULL;
if( StoreGetChildType == StoreGetType ) { TmpString = PrefixString = hStore->Location; TmpString = wcschr(TmpString, L'/'); Require(TmpString); TmpString ++; TmpString = wcschr(TmpString, L'/'); Require(TmpString); TmpString ++; if( wcschr(TmpString, L'/') ) { TmpString = wcschr(TmpString, L'/'); TmpString ++; } PrefixSize = sizeof(WCHAR)*(DWORD)(TmpString - PrefixString ); SuffixSize = SizeString(hStore->Location, FALSE)-PrefixSize; } else if( StoreGetAbsoluteSameServerType == StoreGetType ) { TmpString = PrefixString = hStore->Location; TmpString = wcschr(TmpString, L'/'); Require(TmpString); TmpString ++; TmpString = wcschr(TmpString, L'/'); Require(TmpString); TmpString ++; if( wcschr(TmpString, L'/') ) { TmpString = wcschr(TmpString, L'/'); TmpString ++; } PrefixSize = sizeof(WCHAR)*(DWORD)(TmpString - PrefixString ); SuffixSize = 0; } else if( StoreGetAbsoluteOtherServerType == StoreGetType ) { PrefixSize = 0; // use the path given by the user
SuffixSize = 0; } else { Require(FALSE); PrefixSize = SuffixSize = 0; }
Size = PrefixSize + SuffixSize + SizeString(PathIn,FALSE) + sizeof(CONNECTOR) - sizeof(WCHAR); TmpString = MemAlloc(Size); if( NULL == TmpString ) return ERROR_NOT_ENOUGH_MEMORY;
if( PrefixSize ) { memcpy((LPBYTE)TmpString, (LPBYTE)PrefixString, PrefixSize); } wcscpy((LPWSTR)(PrefixSize + (LPBYTE)TmpString), PathIn); if( SuffixSize ) { wcscat(TmpString, CONNECTOR); wcscat(TmpString, (LPWSTR)(PrefixSize+(LPBYTE)PrefixString)); }
*PathOut = TmpString; StoreTrace2("ConvertedPath: %ws\n", TmpString); return ERROR_SUCCESS; }
//BeginExport(function)
DWORD StoreGetHandle( // get handle to child object, absolute object..
IN OUT LPSTORE_HANDLE hStore, // this gets modified..
IN DWORD Reserved, IN DWORD StoreGetType, // same server? just a simple child?
IN LPWSTR Path, IN OUT STORE_HANDLE *hStoreOut // new handle created..
) //EndExport(function)
{ HRESULT hResult; DWORD Result; DWORD Size; LPWSTR ConvertedPath; HANDLE ObjectHandle; LPBYTE Memory;
AssertRet(hStore, ERROR_INVALID_PARAMETER); AssertRet(hStore->Location, ERROR_INVALID_PARAMETER); AssertRet(Path, ERROR_INVALID_PARAMETER); AssertRet(hStoreOut, ERROR_INVALID_PARAMETER);
Result = ConvertPath(hStore, StoreGetType, Path, &ConvertedPath); if( ERROR_SUCCESS != Result ) return Result;
Require(ConvertedPath); Memory = MemAlloc(hStore->MemSize); if( NULL == Memory ) { MemFree(ConvertedPath); return ERROR_NOT_ENOUGH_MEMORY; }
hResult = ADSIOpenDSObject( ConvertedPath, hStore->UserName, hStore->Password, hStore->AuthFlags, &ObjectHandle ); if( FAILED(hResult) ) { MemFree(ConvertedPath); MemFree(Memory); return ConvertHresult(hResult); }
memcpy(Memory, hStore->Memory, hStore->MemSize); Size = sizeof(LONG); hStoreOut->MemSize = hStore->MemSize; hStoreOut->MustBeZero = 0; hStoreOut->Location = ConvertedPath; hStoreOut->UserName = (LPWSTR)&Memory[Size]; Size += SizeString(hStore->UserName, FALSE); hStoreOut->Password = (LPWSTR)&Memory[Size]; Size += SizeString(hStore->Password, FALSE); hStoreOut->AuthFlags = hStore->AuthFlags; hStoreOut->ADSIHandle = ObjectHandle; hStoreOut->SearchHandle = NULL; hStoreOut->Memory = Memory;
if( NULL == hStore->UserName ) hStoreOut->UserName = NULL; if( NULL == hStore->Password ) hStoreOut->Password = NULL;
return ERROR_SUCCESS; }
//BeginExport(function)
DWORD StoreSetSearchOneLevel( // search will return everything one level below
IN OUT LPSTORE_HANDLE hStore, IN DWORD Reserved ) //EndExport(function)
{ HRESULT hResult; ADS_SEARCHPREF_INFO SearchPref[3];
AssertRet(hStore && hStore->ADSIHandle, ERROR_INVALID_PARAMETER); AssertRet(Reserved == 0, ERROR_INVALID_PARAMETER);
SearchPref[0].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE; SearchPref[0].vValue.dwType = ADSTYPE_INTEGER; SearchPref[0].vValue.Integer = ADS_SCOPE_ONELEVEL;
SearchPref[1].dwSearchPref = ADS_SEARCHPREF_PAGESIZE; SearchPref[1].vValue.dwType = ADSTYPE_INTEGER; SearchPref[1].vValue.Integer = DHCPDS_DS_SEARCH_PAGESIZE;
// Make it cache the results at the client side. This is
// default, but try it anyway.
SearchPref[2].dwSearchPref = ADS_SEARCHPREF_CACHE_RESULTS; SearchPref[2].vValue.dwType = ADSTYPE_BOOLEAN; SearchPref[2].vValue.Boolean = TRUE;
hResult = ADSISetSearchPreference( /* hDSObject */ hStore->ADSIHandle, /* pSearchPrefs */ SearchPref, /* dwNumPrefs */ 2 // sizeof( SearchPref ) / sizeof( SearchPref[ 0 ])
);
if( FAILED(hResult) ) return ConvertHresult(hResult); return ERROR_SUCCESS; }
//BeginExport(function)
DWORD StoreSetSearchSubTree( // search will return the subtree below in ANY order
IN OUT LPSTORE_HANDLE hStore, IN DWORD Reserved ) //EndExport(function)
{ HRESULT hResult; ADS_SEARCHPREF_INFO SearchPref[3];
AssertRet(hStore && hStore->ADSIHandle, ERROR_INVALID_PARAMETER); AssertRet(Reserved == 0, ERROR_INVALID_PARAMETER);
SearchPref[0].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE; SearchPref[0].vValue.dwType = ADSTYPE_INTEGER; SearchPref[0].vValue.Integer = ADS_SCOPE_SUBTREE;
SearchPref[1].dwSearchPref = ADS_SEARCHPREF_PAGESIZE; SearchPref[1].vValue.dwType = ADSTYPE_INTEGER; SearchPref[1].vValue.Integer = DHCPDS_DS_SEARCH_PAGESIZE;
// Make it cache the results at the client side. This is
// default, but try it anyway.
SearchPref[2].dwSearchPref = ADS_SEARCHPREF_CACHE_RESULTS; SearchPref[2].vValue.dwType = ADSTYPE_BOOLEAN; SearchPref[2].vValue.Boolean = TRUE;
hResult = ADSISetSearchPreference( /* hDSObject */ hStore->ADSIHandle, /* pSearchPrefs */ SearchPref, /* dwNumPrefs */ sizeof( SearchPref ) / sizeof( SearchPref[ 0 ]) );
if( FAILED(hResult) ) return ConvertHresult(hResult); return ERROR_SUCCESS; }
//BeginExport(function)
DWORD StoreBeginSearch( IN OUT LPSTORE_HANDLE hStore, IN DWORD Reserved, IN LPWSTR SearchFilter ) //EndExport(function)
{ HRESULT hResult; LPWSTR nameAttrib;
nameAttrib = ATTRIB_NAME; AssertRet(hStore && hStore->ADSIHandle, ERROR_INVALID_PARAMETER); AssertRet(Reserved == 0, ERROR_INVALID_PARAMETER); hResult = ADSIExecuteSearch( hStore->ADSIHandle, SearchFilter, (LPWSTR *)&nameAttrib, 1, &(hStore->SearchHandle) );
if( FAILED(hResult) ) return ConvertHresult(hResult); hStore->SearchStarted = FALSE;
return ERROR_SUCCESS; }
//BeginExport(function)
DWORD StoreEndSearch( IN OUT LPSTORE_HANDLE hStore, IN DWORD Reserved ) //EndExport(function)
{ HRESULT hResult;
AssertRet(hStore, ERROR_INVALID_PARAMETER); AssertRet(hStore->SearchHandle, ERROR_INVALID_PARAMETER); AssertRet(Reserved == 0, ERROR_INVALID_PARAMETER);
hResult = ADSICloseSearchHandle(hStore->ADSIHandle, hStore->SearchHandle); hStore->SearchHandle = NULL;
hStore->SearchStarted = FALSE; if( FAILED(hResult) ) return ConvertHresult(hResult); return ERROR_SUCCESS; }
//BeginExport(function)
DWORD // ERROR_NO_MORE_ITEMS if exhausted
StoreSearchGetNext( IN OUT LPSTORE_HANDLE hStore, IN DWORD Reserved, OUT LPSTORE_HANDLE hStoreOut ) //EndExport(function)
{ DWORD Result; HRESULT hResult; ADS_SEARCH_COLUMN Column; LPWSTR ColumnName;
AssertRet(hStore && hStore->ADSIHandle && hStoreOut, ERROR_INVALID_PARAMETER); AssertRet(Reserved == 0, ERROR_INVALID_PARAMETER);
if ( !hStore->SearchStarted ) { hResult = ADSIGetFirstRow( hStore->ADSIHandle, hStore->SearchHandle ); hStore->SearchStarted = TRUE; } else { hResult = ADSIGetNextRow( hStore->ADSIHandle, hStore->SearchHandle ); }
if( FAILED(hResult) ) return ConvertHresult(hResult); if( S_ADS_NOMORE_ROWS == hResult ) return ERROR_NO_MORE_ITEMS;
hResult = ADSIGetColumn( hStore->ADSIHandle, hStore->SearchHandle, ATTRIB_NAME, &Column ); if( FAILED(hResult) ) { Require(FALSE); return ConvertHresult(hResult); }
Require(1==Column.dwNumValues); // single valued
if( Column.pADsValues[0].dwType == ADSTYPE_DN_STRING ) { Require(Column.pADsValues[0].DNString); ColumnName = MakeColumnName(Column.pADsValues[0].DNString); } else if( Column.pADsValues[0].dwType == ADSTYPE_CASE_IGNORE_STRING ) { Require(Column.pADsValues[0].CaseIgnoreString); ColumnName = MakeColumnName(Column.pADsValues[0].CaseIgnoreString); } else { Require(FALSE); ColumnName = NULL; } if( NULL == ColumnName ) Result = ERROR_NOT_ENOUGH_MEMORY; else { Result = StoreGetHandle( hStore, Reserved, StoreGetChildType, ColumnName, hStoreOut ); MemFree(ColumnName); }
ADSIFreeColumn( hStore->ADSIHandle, &Column );
return Result; }
//BeginExport(function)
DWORD StoreCreateObjectVA( // create a new object - var-args ending with ADSTYPE_INVALID
IN OUT LPSTORE_HANDLE hStore, IN DWORD Reserved, IN LPWSTR NewObjName, // name of the new object -- must be "CN=name" types
... // fmt is AttrType, AttrName, AttrValue [AttrValueLen]
) //EndExport(function) // LARGE_INTEGER type has hi_word followed by low_word
{ HRESULT hResult; DWORD Result; DWORD i; DWORD ArgType; DWORD nArgs; DWORD Arg1; va_list Args; PADS_ATTR_INFO Attributes;
AssertRet(hStore, ERROR_INVALID_PARAMETER); AssertRet(NewObjName, ERROR_INVALID_PARAMETER);
nArgs = 0; va_start(Args, NewObjName); do { ArgType = va_arg(Args, DWORD); if( ADSTYPE_INVALID == ArgType ) break; ( void ) va_arg((Args), LPWSTR); // skip the name of attrib
switch(ArgType) { case ADSTYPE_DN_STRING : case ADSTYPE_CASE_EXACT_STRING: case ADSTYPE_CASE_IGNORE_STRING: case ADSTYPE_PRINTABLE_STRING: case ADSTYPE_NUMERIC_STRING: case ADSTYPE_UTC_TIME: case ADSTYPE_OBJECT_CLASS: ( void ) va_arg(Args, LPWSTR); break;
case ADSTYPE_BOOLEAN: case ADSTYPE_INTEGER: ( void ) va_arg(Args, DWORD); break;
case ADSTYPE_OCTET_STRING: (void ) va_arg(Args, LPBYTE); (void ) va_arg(Args, DWORD); // additional DWORD values for these..
break; case ADSTYPE_LARGE_INTEGER: (void ) va_arg(Args, LONG); (void ) va_arg(Args, LONG); // additional DWORD values for these..
break; default: return ERROR_INVALID_PARAMETER; } nArgs ++; } while( 1 );
if( 0 == nArgs ) { Attributes = NULL; } else { Attributes = MemAlloc(nArgs * sizeof(*Attributes)); if( NULL == Attributes ) return ERROR_NOT_ENOUGH_MEMORY;
memset(Attributes, 0, sizeof(*Attributes)); }
va_start(Args, NewObjName); for(i = 0; i < nArgs; i ++ ) { ArgType = va_arg(Args, DWORD); Require(ADSTYPE_INVALID != ArgType);
Attributes[i].dwNumValues = 1; Attributes[i].pADsValues = MemAlloc(sizeof(*Attributes[i].pADsValues)); if( NULL == Attributes[i].pADsValues ) { nArgs = i; goto Cleanup; }
Attributes[i].pszAttrName = (LPWSTR)va_arg(Args, LPWSTR); Attributes[i].dwControlCode = ADS_ATTR_APPEND; Attributes[i].dwADsType = ArgType; Attributes[i].pADsValues[0].dwType = ArgType;
switch(ArgType) { case ADSTYPE_DN_STRING : Attributes[i].pADsValues[0].DNString = (LPWSTR)va_arg(Args,LPWSTR); break; case ADSTYPE_CASE_EXACT_STRING: Attributes[i].pADsValues[0].CaseExactString = (LPWSTR)va_arg(Args,LPWSTR); break; case ADSTYPE_CASE_IGNORE_STRING: Attributes[i].pADsValues[0].CaseIgnoreString = (LPWSTR)va_arg(Args,LPWSTR); break; case ADSTYPE_PRINTABLE_STRING: Attributes[i].pADsValues[0].PrintableString = (LPWSTR)va_arg(Args,LPWSTR); break; case ADSTYPE_NUMERIC_STRING: Attributes[i].pADsValues[0].NumericString = (LPWSTR)va_arg(Args,LPWSTR); break; case ADSTYPE_BOOLEAN: Attributes[i].pADsValues[0].Boolean = va_arg(Args,DWORD); break; case ADSTYPE_INTEGER: Attributes[i].pADsValues[0].Integer = va_arg(Args,DWORD); break; case ADSTYPE_OBJECT_CLASS: Attributes[i].pADsValues[0].ClassName = (LPWSTR)va_arg(Args,LPWSTR); break; case ADSTYPE_OCTET_STRING: Attributes[i].pADsValues[0].OctetString.lpValue = (LPBYTE)va_arg(Args,LPBYTE); Attributes[i].pADsValues[0].OctetString.dwLength = va_arg(Args, DWORD); break; case ADSTYPE_LARGE_INTEGER: Attributes[i].pADsValues[0].LargeInteger.HighPart = (LONG)va_arg(Args,LONG); Attributes[i].pADsValues[0].LargeInteger.LowPart = va_arg(Args, ULONG); break; case ADSTYPE_UTC_TIME: Attributes[i].pADsValues[0].UTCTime = *((ADS_UTC_TIME*)va_arg(Args,PVOID)); break; default: nArgs = i; Result = ERROR_INVALID_PARAMETER; goto Cleanup; } }
hResult = ADSICreateDSObject( hStore->ADSIHandle, NewObjName, Attributes, nArgs );
if( HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) == hResult || HRESULT_FROM_WIN32(ERROR_OBJECT_ALREADY_EXISTS) == hResult || E_ADS_OBJECT_EXISTS == hResult ) { Result = ERROR_ALREADY_EXISTS; } else if( FAILED(hResult) ) { Result = ConvertHresult(hResult); } else { Result = ERROR_SUCCESS; }
Cleanup:
if( NULL != Attributes ) { for( i = 0; i < nArgs ; i ++ ) { if( Attributes[i].pADsValues ) MemFree(Attributes[i].pADsValues); } MemFree(Attributes); }
return Result; }
//BeginExport(defines)
#define StoreCreateObject StoreCreateObjectVA
//EndExport(defines)
//BeginExport(function)
DWORD StoreDeleteObject( IN OUT LPSTORE_HANDLE hStore, IN DWORD Reserved, IN LPWSTR ObjectName ) //EndExport(function)
{ DWORD Result; HRESULT hResult;
AssertRet(hStore, ERROR_INVALID_PARAMETER); AssertRet(ObjectName, ERROR_INVALID_PARAMETER);
hResult = ADSIDeleteDSObject( hStore->ADSIHandle, ObjectName );
if( FAILED(hResult) ) return ConvertHresult(hResult); return ERROR_SUCCESS; }
//BeginExport(function)
//DOC StoreDeleteThisObject deletes the object defined by hStore,StoreGetType and ADsPath.
//DOC The refer to the object just the same way as for StoreGetHandle.
DWORD StoreDeleteThisObject( // delete an object
IN LPSTORE_HANDLE hStore, // point of anchor frm which reference is done
IN DWORD Reserved, // must be zero, reserved for future use
IN DWORD StoreGetType, // path is relative, absolute or diff server?
IN LPWSTR Path // ADsPath to the object or relative path
) //EndExport(function)
{ HRESULT hResult; DWORD Result; DWORD Size; LPWSTR ConvertedPath, ChildNameStart,ChildNameEnd; LPWSTR ChildName; HANDLE ParentObject;
AssertRet(hStore, ERROR_INVALID_PARAMETER); AssertRet(hStore->Location, ERROR_INVALID_PARAMETER); AssertRet(Path, ERROR_INVALID_PARAMETER);
Result = ConvertPath(hStore, StoreGetType, Path, &ConvertedPath); if( ERROR_SUCCESS != Result ) return Result;
Require(ConvertedPath); ChildNameStart = wcschr(ConvertedPath, L'/'); Require(ChildNameStart); ChildNameStart++; ChildNameStart = wcschr(ChildNameStart, L'/'); Require(ChildNameStart); ChildNameStart++; if( wcschr(ChildNameStart, L'/') ) { ChildNameStart = wcschr(ChildNameStart, L'/'); Require(ChildNameStart); ChildNameStart++; } ChildNameEnd = wcschr(ChildNameStart, L','); Require(ChildNameEnd); *ChildNameEnd++ = L'\0';
ChildName = MemAlloc((DWORD)((LPBYTE)ChildNameEnd - (LPBYTE)ChildNameStart)); if( NULL == ChildName ) { MemFree(ConvertPath); return ERROR_NOT_ENOUGH_MEMORY; }
memcpy(ChildName, ChildNameStart, (int)((LPBYTE)ChildNameEnd - (LPBYTE)ChildNameStart)); wcscpy(ChildNameStart, ChildNameEnd); // remove child name from ConvertPath
hResult = ADSIOpenDSObject( // open the parent object
ConvertedPath, hStore->UserName, hStore->Password, hStore->AuthFlags, &ParentObject ); MemFree(ConvertedPath);
if( FAILED(hResult) ) { MemFree(ChildName); return ConvertHresult(hResult); }
hResult = ADSIDeleteDSObject( // delete the required child object
ParentObject, ChildName ); MemFree(ChildName); ADSICloseDSObject(ParentObject); // free up handles and memory
if( FAILED(hResult) ) return ConvertHresult(hResult); return ERROR_SUCCESS; // : need to have better error messages than this
}
//================================================================================
// dhcp specific stuff follow here..
//================================================================================
//BeginExport(typedef)
typedef struct _EATTRIB { // encapsulated attribute
unsigned int Address1_present : 1; unsigned int Address2_present : 1; unsigned int Address3_present : 1; unsigned int ADsPath_present : 1; unsigned int StoreGetType_present : 1; unsigned int Flags1_present : 1; unsigned int Flags2_present : 1; unsigned int Dword1_present : 1; unsigned int Dword2_present : 1; unsigned int String1_present : 1; unsigned int String2_present : 1; unsigned int String3_present : 1; unsigned int String4_present : 1; unsigned int Binary1_present : 1; unsigned int Binary2_present : 1;
DWORD Address1; // character "i"
DWORD Address2; // character "j"
DWORD Address3; // character "k"
LPWSTR ADsPath; // character "p" "r" "l"
DWORD StoreGetType; // "p,r,l" ==> sameserver, child, otherserver
DWORD Flags1; // character "f"
DWORD Flags2; // character "g"
DWORD Dword1; // character "d"
DWORD Dword2; // character "e"
LPWSTR String1; // character "s"
LPWSTR String2; // character "t"
LPWSTR String3; // character "u"
LPWSTR String4; // character "v"
LPBYTE Binary1; // character "b"
DWORD BinLen1; // # of bytes of above
LPBYTE Binary2; // character "d"
DWORD BinLen2; // # of bytes of above
} EATTRIB, *PEATTRIB, *LPEATTRIB; //EndExport(typedef)
//BeginExport(defines)
#define IS_ADDRESS1_PRESENT(pEA) ((pEA)->Address1_present)
#define IS_ADDRESS1_ABSENT(pEA) (!IS_ADDRESS1_PRESENT(pEA))
#define ADDRESS1_PRESENT(pEA) ((pEA)->Address1_present = 1 )
#define ADDRESS1_ABSENT(pEA) ((pEA)->Address1_present = 0 )
#define IS_ADDRESS2_PRESENT(pEA) ((pEA)->Address2_present)
#define IS_ADDRESS2_ABSENT(pEA) (!IS_ADDRESS2_PRESENT(pEA))
#define ADDRESS2_PRESENT(pEA) ((pEA)->Address2_present = 1 )
#define ADDRESS2_ABSENT(pEA) ((pEA)->Address2_present = 0 )
#define IS_ADDRESS3_PRESENT(pEA) ((pEA)->Address3_present)
#define IS_ADDRESS3_ABSENT(pEA) (!IS_ADDRESS3_PRESENT(pEA))
#define ADDRESS3_PRESENT(pEA) ((pEA)->Address3_present = 1 )
#define ADDRESS3_ABSENT(pEA) ((pEA)->Address3_present = 0 )
#define IS_ADSPATH_PRESENT(pEA) ((pEA)->ADsPath_present)
#define IS_ADSPATH_ABSENT(pEA) (!IS_ADSPATH_PRESENT(pEA))
#define ADSPATH_PRESENT(pEA) ((pEA)->ADsPath_present = 1)
#define ADSPATH_ABSENT(pEA) ((pEA)->ADsPath_present = 0)
#define IS_STOREGETTYPE_PRESENT(pEA) ((pEA)->StoreGetType_present)
#define IS_STOREGETTYPE_ABSENT(pEA) (!((pEA)->StoreGetType_present))
#define STOREGETTYPE_PRESENT(pEA) ((pEA)->StoreGetType_present = 1)
#define STOREGETTYPE_ABSENT(pEA) ((pEA)->StoreGetType_present = 0)
#define IS_FLAGS1_PRESENT(pEA) ((pEA)->Flags1_present)
#define IS_FLAGS1_ABSENT(pEA) (!((pEA)->Flags1_present))
#define FLAGS1_PRESENT(pEA) ((pEA)->Flags1_present = 1)
#define FLAGS1_ABSENT(pEA) ((pEA)->Flags1_present = 0)
#define IS_FLAGS2_PRESENT(pEA) ((pEA)->Flags2_present)
#define IS_FLAGS2_ABSENT(pEA) (!((pEA)->Flags2_present))
#define FLAGS2_PRESENT(pEA) ((pEA)->Flags2_present = 1)
#define FLAGS2_ABSENT(pEA) ((pEA)->Flags2_present = 0)
#define IS_DWORD1_PRESENT(pEA) ((pEA)->Dword1_present)
#define IS_DWORD1_ABSENT(pEA) (!((pEA)->Dword1_present))
#define DWORD1_PRESENT(pEA) ((pEA)->Dword1_present = 1)
#define DWORD1_ABSENT(pEA) ((pEA)->Dword1_present = 0)
#define IS_DWORD2_PRESENT(pEA) ((pEA)->Dword2_present)
#define IS_DWORD2_ABSENT(pEA) (!((pEA)->Dword2_present))
#define DWORD2_PRESENT(pEA) ((pEA)->Dword2_present = 1)
#define DWORD2_ABSENT(pEA) ((pEA)->Dword2_present = 0)
#define IS_STRING1_PRESENT(pEA) ((pEA)->String1_present)
#define IS_STRING1_ABSENT(pEA) (!((pEA)->String1_present))
#define STRING1_PRESENT(pEA) ((pEA)->String1_present = 1)
#define STRING1_ABSENT(pEA) ((pEA)->String1_present = 0)
#define IS_STRING2_PRESENT(pEA) ((pEA)->String2_present)
#define IS_STRING2_ABSENT(pEA) (!((pEA)->String2_present))
#define STRING2_PRESENT(pEA) ((pEA)->String2_present = 1)
#define STRING2_ABSENT(pEA) ((pEA)->String2_present = 0)
#define IS_STRING3_PRESENT(pEA) ((pEA)->String3_present)
#define IS_STRING3_ABSENT(pEA) (!((pEA)->String3_present))
#define STRING3_PRESENT(pEA) ((pEA)->String3_present = 1)
#define STRING3_ABSENT(pEA) ((pEA)->String3_present = 0)
#define IS_STRING4_PRESENT(pEA) ((pEA)->String4_present)
#define IS_STRING4_ABSENT(pEA) (!((pEA)->String4_present))
#define STRING4_PRESENT(pEA) ((pEA)->String4_present = 1)
#define STRING4_ABSENT(pEA) ((pEA)->String4_present = 0)
#define IS_BINARY1_PRESENT(pEA) ((pEA)->Binary1_present)
#define IS_BINARY1_ABSENT(pEA) (!((pEA)->Binary1_present))
#define BINARY1_PRESENT(pEA) ((pEA)->Binary1_present = 1)
#define BINARY1_ABSENT(pEA) ((pEA)->Binary1_present = 0)
#define IS_BINARY2_PRESENT(pEA) ((pEA)->Binary2_present)
#define IS_BINARY2_ABSENT(pEA) (!((pEA)->Binary2_present))
#define BINARY2_PRESENT(pEA) ((pEA)->Binary2_present = 1)
#define BINARY2_ABSENT(pEA) ((pEA)->Binary2_present = 0)
//EndExport(defines)
//BeginExport(inline)
BOOL _inline IsAnythingPresent( IN PEATTRIB pEA ) { return IS_ADDRESS1_PRESENT(pEA) || IS_ADDRESS2_PRESENT(pEA) || IS_ADDRESS3_PRESENT(pEA) || IS_ADSPATH_PRESENT(pEA) || IS_STOREGETTYPE_PRESENT(pEA) || IS_FLAGS1_PRESENT(pEA) || IS_FLAGS2_PRESENT(pEA) || IS_DWORD1_PRESENT(pEA) || IS_DWORD2_PRESENT(pEA) || IS_STRING1_PRESENT(pEA) || IS_STRING2_PRESENT(pEA) || IS_STRING3_PRESENT(pEA) || IS_STRING4_PRESENT(pEA) || IS_BINARY1_PRESENT(pEA) || IS_BINARY2_PRESENT(pEA) ; } //EndExport(inline)
//BeginExport(inline)
BOOL _inline IsEverythingPresent( IN PEATTRIB pEA ) { return IS_ADDRESS1_PRESENT(pEA) && IS_ADDRESS2_PRESENT(pEA) && IS_ADDRESS3_PRESENT(pEA) && IS_ADSPATH_PRESENT(pEA) && IS_STOREGETTYPE_PRESENT(pEA) && IS_FLAGS1_PRESENT(pEA) && IS_FLAGS2_PRESENT(pEA) && IS_DWORD1_PRESENT(pEA) && IS_DWORD2_PRESENT(pEA) && IS_STRING1_PRESENT(pEA) && IS_STRING2_PRESENT(pEA) && IS_STRING3_PRESENT(pEA) && IS_STRING4_PRESENT(pEA) && IS_BINARY1_PRESENT(pEA) && IS_BINARY2_PRESENT(pEA) ; } //EndExport(inline)
//BeginExport(inline)
VOID _inline EverythingPresent( IN PEATTRIB pEA ) { ADDRESS1_PRESENT(pEA); ADDRESS2_PRESENT(pEA); ADDRESS3_PRESENT(pEA); ADSPATH_PRESENT(pEA); STOREGETTYPE_ABSENT(pEA); FLAGS1_PRESENT(pEA); FLAGS2_PRESENT(pEA); DWORD1_PRESENT(pEA); DWORD2_PRESENT(pEA); STRING1_PRESENT(pEA); STRING2_PRESENT(pEA); STRING3_PRESENT(pEA); STRING4_PRESENT(pEA); BINARY1_PRESENT(pEA); BINARY2_PRESENT(pEA); } //EndExport(inline)
//BeginExport(inline)
VOID _inline NothingPresent( IN PEATTRIB pEA ) { ADDRESS1_ABSENT(pEA); ADDRESS2_ABSENT(pEA); ADDRESS3_ABSENT(pEA); ADSPATH_ABSENT(pEA); STOREGETTYPE_ABSENT(pEA); FLAGS1_ABSENT(pEA); FLAGS2_ABSENT(pEA); DWORD1_ABSENT(pEA); DWORD2_ABSENT(pEA); STRING1_ABSENT(pEA); STRING2_ABSENT(pEA); STRING3_ABSENT(pEA); STRING4_ABSENT(pEA); BINARY1_ABSENT(pEA); BINARY2_ABSENT(pEA); } //EndExport(inline)
const char ch_Address1 = L'i' , ch_Address2 = L'j' , ch_Address3 = L'k' , ch_ADsPath_relative = L'r' , ch_ADsPath_absolute = L'p' , ch_ADsPath_diff_srvr = L'l' , ch_Flags1 = L'f' , ch_Flags2 = L'g' , ch_Dword1 = L'd' , ch_Dword2 = L'e' , ch_String1 = L's' , ch_String2 = L't' , ch_String3 = L'u' , ch_String4 = L'v' , ch_Binary1 = L'b' , ch_Binary2 = L'c' , ch_FieldSep = L'$' ;
DWORD StringToIpAddress( // convert a string to an ip-address
IN LPWSTR String, IN OUT DWORD *Address ) { CHAR Buffer[20]; // large enough to hold any ip address stuff
DWORD Count; LPSTR SkippedWhiteSpace;
Count = wcstombs(Buffer, String, sizeof(Buffer) - 1); // save space for '\0'
if( -1 == Count ) return ERROR_INVALID_DATA; Buffer[Count] = '\0';
SkippedWhiteSpace = Buffer; while(( ' ' == *SkippedWhiteSpace || '\t' == *SkippedWhiteSpace) && ( SkippedWhiteSpace < &Buffer[Count])) { SkippedWhiteSpace++; }
*Address= ntohl(inet_addr(SkippedWhiteSpace));// address is in host order..
if( '\0' == *SkippedWhiteSpace ) return ERROR_INVALID_DATA;
return Count <= sizeof("000.000.000.000") ? ERROR_SUCCESS : ERROR_INVALID_DATA; }
DWORD _inline StringToFlags( // convert a string to a DWORD
IN LPWSTR String, IN OUT DWORD *Flags ) { DWORD Count; LPWSTR Remaining;
*Flags = ntohl(wcstoul(String, &Remaining,0));// see input for # base. conv to host order
if( *Remaining == L'\0' ) return ERROR_SUCCESS; return ERROR_INVALID_DATA; }
BYTE _inline Hex( IN WCHAR wCh ) { if( wCh >= '0' && wCh <= '9' ) return wCh - '0'; if( wCh >= 'A' && wCh <= 'F' ) return wCh - 'A' + 10; if( wCh >= 'a' && wCh <= 'f' ) return wCh - 'a' + 10; return 0x0F+1; // this means error!!!
}
DWORD _inline StringToBinary( // inline conversion of a string to binary
IN OUT LPWSTR String, // this string is mangled while converting
IN OUT LPBYTE *Bytes, // this ptr is set to some memory in String..
IN OUT DWORD *nBytes // # of hex bytes copied into location Bytes
) { LPBYTE HexString; DWORD n; BYTE ch1, ch2;
HexString = *Bytes = (LPBYTE)String; n = 0;
while( *String != L'\0' ) { // look at each character
ch1 = Hex(*String++); ch2 = Hex(*String++); if( ch1 > 0xF || ch2 > 0xF ) { // invalid hex bytes for input?
return ERROR_INVALID_DATA; } *HexString ++ = (ch1 << 4 ) | ch2; n ++; } *nBytes = n;
return ERROR_SUCCESS; }
DWORD ConvertStringtoEAttrib( // parse and get the fields out
IN OUT LPWSTR String, // may be destroyed in the process
IN OUT PEATTRIB Attrib // fill this in
) { DWORD Result; DWORD Address; DWORD Flags; WCHAR ThisChar; LPWSTR ThisString; CHAR Dummy[20]; WCHAR Sep;
Require(Attrib); NothingPresent(Attrib);
if( String ) StoreTrace2("ConvertStringtoEAttrib(%ws) called\n", String); Sep = ch_FieldSep;
while(String && *String && (ThisChar = *String ++)) { ThisString = String; do { // skip to the next attrib
String = wcschr(String, Sep); if( NULL == String ) break; if( String[1] == Sep ) { // double consequtive field-sep's stand for the real thing..
wcscpy(String, &String[1]); // remove one of the field-separators, and try looking for one lateron.
String ++; continue; } *String++ = L'\0'; // ok, got a real separator: mark that zero and prepare for next
break; } while(1); // this could as well be while(0) ??
if( ch_Address1 == ThisChar ) { // this is address1
SetInternalFormatError(REPEATED_ADDRESS1, IS_ADDRESS1_PRESENT(Attrib)); Result = StringToIpAddress( ThisString, &Address ); if( ERROR_SUCCESS != Result ) { // should not happen
SetInternalFormatError(INVALID_ADDRESS1, TRUE); } else { ADDRESS1_PRESENT(Attrib); Attrib->Address1 = Address; StoreTrace2("Found address1 %s\n", inet_ntoa(*(struct in_addr*)&Address)); } continue; }
if( ch_Address2 == ThisChar ) { SetInternalFormatError(REPEATED_ADDRESS2, IS_ADDRESS2_PRESENT(Attrib)); Result = StringToIpAddress( ThisString, &Address ); if( ERROR_SUCCESS != Result ) { // should not happen
SetInternalFormatError(INVALID_ADDRESS2, TRUE); } else { ADDRESS2_PRESENT(Attrib); Attrib->Address2 = Address; StoreTrace2("Found address2 %s\n", inet_ntoa(*(struct in_addr*)&Address)); } continue; }
if( ch_Address3 == ThisChar ) { SetInternalFormatError(REPEATED_ADDRESS3, IS_ADDRESS3_PRESENT(Attrib)); Result = StringToIpAddress( ThisString, &Address ); if( ERROR_SUCCESS != Result ) { // should not happen
SetInternalFormatError(INVALID_ADDRESS3, TRUE); } else { ADDRESS3_PRESENT(Attrib); Attrib->Address3 = Address; StoreTrace2("Found address3 %s\n", inet_ntoa(*(struct in_addr*)&Address)); } continue; }
if( ch_ADsPath_relative == ThisChar || ch_ADsPath_absolute == ThisChar || ch_ADsPath_diff_srvr == ThisChar ) { SetInternalFormatError(REPEATED_ADSPATH, IS_ADSPATH_PRESENT(Attrib)); ADSPATH_PRESENT(Attrib); STOREGETTYPE_PRESENT(Attrib); Attrib->ADsPath = ThisString; if( ch_ADsPath_relative == ThisChar ) Attrib->StoreGetType = StoreGetChildType; else if(ch_ADsPath_absolute == ThisChar ) Attrib->StoreGetType = StoreGetAbsoluteSameServerType; else if(ch_ADsPath_diff_srvr == ThisChar ) Attrib->StoreGetType = StoreGetAbsoluteOtherServerType; StoreTrace3("Found path [%ld] [%ws]\n", Attrib->StoreGetType, ThisString); continue; }
if( ch_String1 == ThisChar ) { SetInternalFormatError(REPEATED_STRING1, IS_STRING1_PRESENT(Attrib)); STRING1_PRESENT(Attrib); Attrib->String1 = ThisString; StoreTrace2("Found string1 [%ws]\n", ThisString); continue; }
if( ch_String2 == ThisChar ) { SetInternalFormatError(REPEATED_STRING2, IS_STRING2_PRESENT(Attrib)); STRING2_PRESENT(Attrib); Attrib->String2 = ThisString; StoreTrace2("Found string2 [%ws]\n", ThisString); continue; }
if( ch_String3 == ThisChar ) { SetInternalFormatError(REPEATED_STRING3, IS_STRING3_PRESENT(Attrib)); STRING3_PRESENT(Attrib); Attrib->String3 = ThisString; StoreTrace2("Found string3 [%ws]\n", ThisString); continue; }
if( ch_String4 == ThisChar ) { SetInternalFormatError(REPEATED_STRING4, IS_STRING4_PRESENT(Attrib)); STRING4_PRESENT(Attrib); Attrib->String4 = ThisString; StoreTrace2("Found string4 [%ws]\n", ThisString); continue; }
if( ch_Flags1 == ThisChar ) { SetInternalFormatError(REPEATED_FLAGS1, IS_FLAGS1_PRESENT(Attrib)); Result = StringToFlags( ThisString, &Flags ); if( ERROR_SUCCESS != Result ) { SetInternalFormatError(INVALID_FLAGS1, TRUE); } else { FLAGS1_PRESENT(Attrib); Attrib->Flags1 = Flags; StoreTrace2("Found flags1: 0x%lx\n", Flags); } continue; }
if( ch_Flags2 == ThisChar ) { SetInternalFormatError(REPEATED_FLAGS2, IS_FLAGS2_PRESENT(Attrib)); Result = StringToFlags( ThisString, &Flags ); if( ERROR_SUCCESS != Result ) { SetInternalFormatError(INVALID_FLAGS2, TRUE); } else { FLAGS2_PRESENT(Attrib); Attrib->Flags2 = Flags; StoreTrace2("Found flags2: 0x%lx\n", Flags); } continue; }
if( ch_Dword1 == ThisChar ) { SetInternalFormatError(REPEATED_DWORD1, IS_DWORD1_PRESENT(Attrib)); Result = StringToFlags( ThisString, &Flags ); if( ERROR_SUCCESS != Result ) { SetInternalFormatError(INVALID_DWORD1, TRUE); } else { DWORD1_PRESENT(Attrib); Attrib->Dword1 = Flags; StoreTrace2("Found dword1: 0x%lx\n", Flags); } continue; }
if( ch_Dword2 == ThisChar ) { SetInternalFormatError(REPEATED_DWORD2, IS_DWORD2_PRESENT(Attrib)); Result = StringToFlags( ThisString, &Flags ); if( ERROR_SUCCESS != Result ) { SetInternalFormatError(INVALID_DWORD2, TRUE); } else { DWORD2_PRESENT(Attrib); Attrib->Dword2 = Flags; StoreTrace2("Found dword2: 0x%lx\n", Flags); } continue; }
if( ch_Binary1 == ThisChar ) { SetInternalFormatError(REPEATED_BINARY1, IS_BINARY1_PRESENT(Attrib)); Result = StringToBinary( ThisString, &Attrib->Binary1, &Attrib->BinLen1 ); if( ERROR_SUCCESS != Result ) { SetInternalFormatError(INVALID_BINARY1, TRUE); BINARY1_ABSENT(Attrib); } else { BINARY1_PRESENT(Attrib); StoreTrace2("Found Binary1 of length %ld\n", Attrib->BinLen1); } continue; }
if( ch_Binary2 == ThisChar ) { SetInternalFormatError(REPEATED_BINARY2, IS_BINARY2_PRESENT(Attrib)); Result = StringToBinary( ThisString, &Attrib->Binary2, &Attrib->BinLen2 ); if( ERROR_SUCCESS != Result ) { SetInternalFormatError(INVALID_BINARY2, TRUE); BINARY2_ABSENT(Attrib); } else { BINARY2_PRESENT(Attrib); StoreTrace2("Found Binary2 of length %ld\n", Attrib->BinLen2); } continue; }
SetInternalFormatError(INVALID_ATTRIB_FIELD, TRUE); }
return IsAnythingPresent(Attrib)? ERROR_SUCCESS : ERROR_INVALID_DATA; }
BOOL _inline InvalidStringInBinary( // check if the given binary stream forms a LPWSTR
IN LPBYTE Data, IN DWORD DataLen ) { if( 0 == DataLen ) return TRUE; if( DataLen % sizeof(WCHAR) ) return TRUE; DataLen /= sizeof(WCHAR); if( L'\0' != ((LPWSTR)Data)[DataLen-1] ) return TRUE; return FALSE; }
DWORD ConvertBinarytoEAttrib( // parse and get the fields out
IN OUT LPBYTE Data, // input free format data
IN DWORD DataLen, // bytes for data length
IN OUT PEATTRIB Attrib // fill this in
) { DWORD Result; DWORD Address; DWORD Flags; DWORD Offset; DWORD ThisDataLen; DWORD xDataLen; LPBYTE xData; LPBYTE ThisData; WCHAR ThisChar; CHAR Dummy[20];
Require(Attrib); NothingPresent(Attrib);
Offset = 0; while( Data && DataLen >= sizeof(BYTE) + sizeof(WORD) ) { ThisChar = ntohs(*(LPWORD)Data); Data += sizeof(WORD); DataLen -= sizeof(WORD); ThisDataLen = ntohs(*(LPWORD)Data); Data += sizeof(WORD); DataLen -= sizeof(WORD); if( ROUND_UP_COUNT(ThisDataLen, ALIGN_WORD) > DataLen ) { SetInternalFormatError(INVALID_BINARY_CODING, TRUE); break; } ThisData = Data; Data += ROUND_UP_COUNT(ThisDataLen, ALIGN_WORD); DataLen -= ROUND_UP_COUNT(ThisDataLen, ALIGN_WORD);
if( ch_Address1 == ThisChar ) { // this is address1
SetInternalFormatError(REPEATED_ADDRESS1, IS_ADDRESS1_PRESENT(Attrib)); if( sizeof(DWORD) != ThisDataLen ) { SetInternalFormatError(INVALID_ADDRESS1, TRUE); } else { Address = ntohl(*(DWORD UNALIGNED *)ThisData); ADDRESS1_PRESENT(Attrib); Attrib->Address1 = Address; StoreTrace2("Found address1 %s\n", inet_ntoa(*(struct in_addr*)&Address)); } continue; }
if( ch_Address2 == ThisChar ) { SetInternalFormatError(REPEATED_ADDRESS2, IS_ADDRESS2_PRESENT(Attrib)); if( sizeof(DWORD) != ThisDataLen ) { SetInternalFormatError(INVALID_ADDRESS2, TRUE); } else { Address = ntohl(*(DWORD UNALIGNED *)ThisData); ADDRESS2_PRESENT(Attrib); Attrib->Address2 = Address; StoreTrace2("Found address2 %s\n", inet_ntoa(*(struct in_addr*)&Address)); } continue; }
if( ch_Address3 == ThisChar ) { SetInternalFormatError(REPEATED_ADDRESS3, IS_ADDRESS3_PRESENT(Attrib)); if( sizeof(DWORD) != ThisDataLen ) { SetInternalFormatError(INVALID_ADDRESS3, TRUE); } else { Address = ntohl(*(DWORD UNALIGNED *)ThisData); ADDRESS3_PRESENT(Attrib); Attrib->Address3 = Address; StoreTrace2("Found address3 %s\n", inet_ntoa(*(struct in_addr*)&Address)); } continue; }
if( ch_ADsPath_relative == ThisChar || ch_ADsPath_absolute == ThisChar || ch_ADsPath_diff_srvr == ThisChar ) { SetInternalFormatError(REPEATED_ADSPATH, IS_ADSPATH_PRESENT(Attrib)); if( InvalidStringInBinary(ThisData, ThisDataLen) ) { SetInternalFormatError(INVALID_ADSPATH, TRUE); continue; }
ADSPATH_PRESENT(Attrib); STOREGETTYPE_PRESENT(Attrib); Attrib->ADsPath = (LPWSTR)ThisData; if( ch_ADsPath_relative == ThisChar ) Attrib->StoreGetType = StoreGetChildType; else if(ch_ADsPath_absolute == ThisChar ) Attrib->StoreGetType = StoreGetAbsoluteSameServerType; else if(ch_ADsPath_diff_srvr == ThisChar ) Attrib->StoreGetType = StoreGetAbsoluteOtherServerType; StoreTrace3("Found path [%ld] [%ws]\n", Attrib->StoreGetType, (LPWSTR)ThisData); continue; }
if( ch_String1 == ThisChar ) { SetInternalFormatError(REPEATED_STRING1, IS_STRING1_PRESENT(Attrib)); if( InvalidStringInBinary(ThisData, ThisDataLen) ) { SetInternalFormatError(INVALID_STRING1, TRUE); continue; } STRING1_PRESENT(Attrib); Attrib->String1 = (LPWSTR)ThisData; StoreTrace2("Found string1 [%ws]\n", (LPWSTR)ThisData); continue; }
if( ch_String2 == ThisChar ) { SetInternalFormatError(REPEATED_STRING2, IS_STRING2_PRESENT(Attrib)); if( InvalidStringInBinary(ThisData, ThisDataLen) ) { SetInternalFormatError(INVALID_STRING2, TRUE); continue; } STRING2_PRESENT(Attrib); Attrib->String2 = (LPWSTR)ThisData; StoreTrace2("Found string2 [%ws]\n", (LPWSTR)ThisData); continue; }
if( ch_String3 == ThisChar ) { SetInternalFormatError(REPEATED_STRING3, IS_STRING3_PRESENT(Attrib)); if( InvalidStringInBinary(ThisData, ThisDataLen) ) { SetInternalFormatError(INVALID_STRING3, TRUE); continue; } STRING3_PRESENT(Attrib); Attrib->String3 = (LPWSTR)ThisData; StoreTrace2("Found string3 [%ws]\n", (LPWSTR)ThisData); continue; }
if( ch_String4 == ThisChar ) { SetInternalFormatError(REPEATED_STRING4, IS_STRING4_PRESENT(Attrib)); if( InvalidStringInBinary(ThisData, ThisDataLen) ) { SetInternalFormatError(INVALID_STRING4, TRUE); continue; } STRING4_PRESENT(Attrib); Attrib->String4 = (LPWSTR)ThisData; StoreTrace2("Found string4 [%ws]\n", (LPWSTR)ThisData); continue; }
if( ch_Flags1 == ThisChar ) { SetInternalFormatError(REPEATED_FLAGS1, IS_FLAGS1_PRESENT(Attrib)); if( sizeof(DWORD) != ThisDataLen ) { SetInternalFormatError(INVALID_FLAGS1, TRUE); } else { Flags = ntohl(*(DWORD UNALIGNED *)ThisData); FLAGS1_PRESENT(Attrib); Attrib->Flags1 = Flags; StoreTrace2("Found flags1: 0x%lx\n", Flags); } continue; }
if( ch_Flags2 == ThisChar ) { SetInternalFormatError(REPEATED_FLAGS2, IS_FLAGS2_PRESENT(Attrib)); if( sizeof(DWORD) != ThisDataLen ) { SetInternalFormatError(INVALID_FLAGS2, TRUE); } else { Flags = ntohl(*(DWORD UNALIGNED *)ThisData); FLAGS2_PRESENT(Attrib); Attrib->Flags2 = Flags; StoreTrace2("Found flags2: 0x%lx\n", Flags); } continue; }
if( ch_Dword1 == ThisChar ) { SetInternalFormatError(REPEATED_DWORD1, IS_DWORD1_PRESENT(Attrib)); if( sizeof(DWORD) != ThisDataLen ) { SetInternalFormatError(INVALID_DWORD1, TRUE); } else { Flags = ntohl(*(DWORD UNALIGNED *)ThisData); DWORD1_PRESENT(Attrib); Attrib->Dword1 = Flags; StoreTrace2("Found dword1: 0x%lx\n", Flags); } continue; }
if( ch_Dword2 == ThisChar ) { SetInternalFormatError(REPEATED_DWORD2, IS_DWORD2_PRESENT(Attrib)); if( sizeof(DWORD) != ThisDataLen ) { SetInternalFormatError(INVALID_DWORD2, TRUE); } else { Flags = ntohl(*(DWORD UNALIGNED *)ThisData); DWORD2_PRESENT(Attrib); Attrib->Dword2 = Flags; StoreTrace2("Found dword2: 0x%lx\n", Flags); } continue; }
if( ch_Binary1 == ThisChar ) { SetInternalFormatError(REPEATED_BINARY1, IS_BINARY1_PRESENT(Attrib)); BINARY1_PRESENT(Attrib); Attrib->Binary1 = ThisData; Attrib->BinLen1 = ThisDataLen; StoreTrace2("Found %ld bytes of binary 1 data\n", ThisDataLen); continue; }
if( ch_Binary2 == ThisChar ) { SetInternalFormatError(REPEATED_BINARY2, IS_BINARY2_PRESENT(Attrib)); BINARY2_PRESENT(Attrib); Attrib->Binary2 = ThisData; Attrib->BinLen2 = ThisDataLen; StoreTrace2("Found %ld bytes of binary 2 data\n", ThisDataLen); continue; }
SetInternalFormatError(INVALID_ATTRIB_FIELD, TRUE); }
return IsAnythingPresent(Attrib) ? ERROR_SUCCESS: ERROR_INVALID_DATA; }
PEATTRIB CloneAttrib( IN PEATTRIB Attrib ) { PEATTRIB RetVal; DWORD Size;
Size = sizeof(*Attrib); Size = ROUND_UP_COUNT(Size, ALIGN_WORST);
if( IS_ADSPATH_PRESENT(Attrib) ) { Size += sizeof(WCHAR)*(1 + wcslen(Attrib->ADsPath)); } if( IS_STRING1_PRESENT(Attrib) ) { Size += sizeof(WCHAR)*(1 + wcslen(Attrib->String1)); } if( IS_STRING2_PRESENT(Attrib) ) { Size += sizeof(WCHAR)*(1 + wcslen(Attrib->String2)); } if( IS_STRING3_PRESENT(Attrib) ) { Size += sizeof(WCHAR)*(1 + wcslen(Attrib->String3)); } if( IS_STRING4_PRESENT(Attrib) ) { Size += sizeof(WCHAR)*(1 + wcslen(Attrib->String4)); }
if( IS_BINARY1_PRESENT(Attrib) ) Size += Attrib->BinLen1; if( IS_BINARY2_PRESENT(Attrib) ) Size += Attrib->BinLen2;
RetVal = (PEATTRIB)MemAlloc(Size); if( NULL == RetVal ) return NULL;
Size = sizeof(*Attrib); Size = ROUND_UP_COUNT(Size, ALIGN_WORST); *RetVal = *Attrib;
if( IS_ADSPATH_PRESENT(Attrib) ) { RetVal->ADsPath = (LPWSTR)(Size + (LPBYTE)RetVal); Size += sizeof(WCHAR)*(1 + wcslen(Attrib->ADsPath)); wcscpy(RetVal->ADsPath, Attrib->ADsPath); } if( IS_STRING1_PRESENT(Attrib) ) { RetVal->String1 = (LPWSTR)(Size + (LPBYTE)RetVal); Size += sizeof(WCHAR)*(1 + wcslen(Attrib->String1)); wcscpy(RetVal->String1, Attrib->String1); } if( IS_STRING2_PRESENT(Attrib) ) { RetVal->String2 = (LPWSTR)(Size + (LPBYTE)RetVal); Size += sizeof(WCHAR)*(1 + wcslen(Attrib->String2)); wcscpy(RetVal->String2, Attrib->String2); } if( IS_STRING3_PRESENT(Attrib) ) { RetVal->String3 = (LPWSTR)(Size + (LPBYTE)RetVal); Size += sizeof(WCHAR)*(1 + wcslen(Attrib->String3)); wcscpy(RetVal->String3, Attrib->String3); } if( IS_STRING4_PRESENT(Attrib) ) { RetVal->String4 = (LPWSTR)(Size + (LPBYTE)RetVal); Size += sizeof(WCHAR)*(1 + wcslen(Attrib->String4)); wcscpy(RetVal->String4, Attrib->String4); }
if( IS_BINARY1_PRESENT(Attrib) ) { RetVal->Binary1 = (Size + (LPBYTE)RetVal); Size += Attrib->BinLen1; memcpy(RetVal->Binary1, Attrib->Binary1, Attrib->BinLen1); }
if( IS_BINARY2_PRESENT(Attrib) ) { RetVal->Binary2 = (Size + (LPBYTE)RetVal); Size += Attrib->BinLen2; memcpy(RetVal->Binary2, Attrib->Binary2, Attrib->BinLen2); }
return RetVal; }
DWORD AddAttribToArray( IN OUT PARRAY Array, IN PEATTRIB Attrib ) { DWORD Result;
Require(Attrib);
Attrib = CloneAttrib(Attrib); if( NULL == Attrib) return ERROR_NOT_ENOUGH_MEMORY; Result = MemArrayAddElement(Array, (LPVOID)Attrib); if( ERROR_SUCCESS == Result ) return ERROR_SUCCESS; MemFree(Attrib); return Result; }
BOOL _inline OnlyADsPathPresent( IN PEATTRIB pEA ) { if( ! IS_ADSPATH_PRESENT(pEA) ) return FALSE; return IS_ADDRESS1_ABSENT(pEA) && IS_ADDRESS2_ABSENT(pEA) && IS_ADSPATH_ABSENT(pEA) && IS_STOREGETTYPE_ABSENT(pEA) && IS_FLAGS1_ABSENT(pEA) && IS_FLAGS2_ABSENT(pEA) && IS_STRING1_ABSENT(pEA) && IS_STRING2_ABSENT(pEA) && IS_BINARY1_ABSENT(pEA) && IS_BINARY2_ABSENT(pEA) ; }
DWORD StoreCollectAttributes( // fwd declaration
IN OUT PSTORE_HANDLE hStore, IN DWORD Reserved, IN LPWSTR AttribName, IN OUT PARRAY ArrayToAddTo, IN DWORD RecursionDepth );
DWORD _inline StoreCollectAttributesInternal( IN OUT PSTORE_HANDLE hStore, IN DWORD Reserved, IN PEATTRIB Attrib, IN LPWSTR AttribName, IN OUT PARRAY ArrayToAddTo, // array of PEATTRIBs
IN DWORD RecursionDepth // 0 ==> no recursion
) { DWORD Result, Result2; STORE_HANDLE hStore2;
if( 0 == RecursionDepth ) { Result = AddAttribToArray(ArrayToAddTo, Attrib); if( ERROR_SUCCESS != Result ) SetInternalFormatError(UNEXPECTED_INTERNAL_ERROR, TRUE); return ERROR_STACK_OVERFLOW; }
StoreTrace2("Recursing to %ws\n", Attrib->ADsPath); Result = StoreGetHandle( hStore, /*Reserved*/ 0, Attrib->StoreGetType, Attrib->ADsPath, &hStore2 ); if( ERROR_SUCCESS != Result ) return Result;
Result = StoreCollectAttributes( &hStore2, Reserved, AttribName, ArrayToAddTo, RecursionDepth-1 );
Result2 = StoreCleanupHandle( &hStore2, 0 );
return Result; }
//BeginExport(function)
DWORD StoreCollectAttributes( IN OUT PSTORE_HANDLE hStore, IN DWORD Reserved, IN LPWSTR AttribName, // this attrib must be some kind of a text string
IN OUT PARRAY ArrayToAddTo, // array of PEATTRIBs
IN DWORD RecursionDepth // 0 ==> no recursion
) //EndExport(function)
{ HRESULT hResult; DWORD Result; DWORD Error; DWORD nAttributes; DWORD i; PADS_ATTR_INFO Attributes; LPWSTR Attribs[1]; LPWSTR ThisAttribStr; EATTRIB ThisEAttrib;
Attribs[0] = AttribName; Attributes = NULL; nAttributes = 0; hResult = ADSIGetObjectAttributes( hStore->ADSIHandle, Attribs, sizeof(Attribs)/sizeof(Attribs[0]), &Attributes, &nAttributes ); if( HRESULT_FROM_WIN32( ERROR_DS_NO_ATTRIBUTE_OR_VALUE) == hResult ) { return ERROR_SUCCESS; }
if( FAILED(hResult) ) return ConvertHresult(hResult);
if( 0 == nAttributes || NULL == Attributes ) return ERROR_SUCCESS;
Require( 1 == nAttributes ); Error = ERROR_SUCCESS;
for( i = 0; i < Attributes[0].dwNumValues ; i ++ ) { switch(Attributes[0].pADsValues[i].dwType) { case ADSTYPE_DN_STRING: ThisAttribStr = Attributes[0].pADsValues[i].DNString; break; case ADSTYPE_CASE_EXACT_STRING: ThisAttribStr = Attributes[0].pADsValues[i].CaseExactString; break; case ADSTYPE_CASE_IGNORE_STRING: ThisAttribStr = Attributes[0].pADsValues[i].CaseIgnoreString; break; case ADSTYPE_PRINTABLE_STRING: ThisAttribStr = Attributes[0].pADsValues[i].PrintableString; break; default: SetInternalFormatError(UNEXPECTED_COLLECTION_TYPE, TRUE); continue; } Require(ThisAttribStr); Result = ConvertStringtoEAttrib(ThisAttribStr, &ThisEAttrib); if( ERROR_SUCCESS == Result ) { if( OnlyADsPathPresent(&ThisEAttrib) ) { Result = StoreCollectAttributesInternal( hStore, Reserved, &ThisEAttrib, AttribName, ArrayToAddTo, RecursionDepth ); } else { Result = AddAttribToArray(ArrayToAddTo, &ThisEAttrib); } if( ERROR_SUCCESS != Result ) Error = Result; } else Error = Result; }
FreeADsMem(Attributes);
return Error; }
DWORD StoreCollectBinaryAttributes( // fwd declaration
IN OUT PSTORE_HANDLE hStore, IN DWORD Reserved, IN LPWSTR AttribName, IN OUT PARRAY ArrayToAddTo, IN DWORD RecursionDepth );
DWORD _inline StoreCollectBinaryAttributesInternal( IN OUT PSTORE_HANDLE hStore, IN DWORD Reserved, IN PEATTRIB Attrib, IN LPWSTR AttribName, IN OUT PARRAY ArrayToAddTo, // array of PEATTRIBs
IN DWORD RecursionDepth // 0 ==> no recursion
) { DWORD Result, Result2; STORE_HANDLE hStore2;
if( 0 == RecursionDepth ) { Result = AddAttribToArray(ArrayToAddTo, Attrib); if( ERROR_SUCCESS != Result ) SetInternalFormatError(UNEXPECTED_INTERNAL_ERROR, TRUE); return ERROR_STACK_OVERFLOW; }
StoreTrace2("Recursing to %ws\n", Attrib->ADsPath); Result = StoreGetHandle( hStore, /*Reserved*/ 0, Attrib->StoreGetType, Attrib->ADsPath, &hStore2 ); if( ERROR_SUCCESS != Result ) return Result;
Result = StoreCollectBinaryAttributes( &hStore2, Reserved, AttribName, ArrayToAddTo, RecursionDepth-1 );
Result2 = StoreCleanupHandle( &hStore2, 0 );
return Result; }
//BeginExport(function)
DWORD StoreCollectBinaryAttributes( IN OUT PSTORE_HANDLE hStore, IN DWORD Reserved, IN LPWSTR AttribName, // accept only attrib type OCTET_STRING
IN OUT PARRAY ArrayToAddTo, // array of PEATTRIBs
IN DWORD RecursionDepth // 0 ==> no recursion
) //EndExport(function)
{ HRESULT hResult; DWORD Result; DWORD Error; DWORD nAttributes; DWORD i; DWORD DataLength; PADS_ATTR_INFO Attributes; LPWSTR Attribs[1]; LPBYTE Data; EATTRIB ThisEAttrib;
Attribs[0] = AttribName; Attributes = NULL; nAttributes = 0; hResult = ADSIGetObjectAttributes( hStore->ADSIHandle, Attribs, sizeof(Attribs)/sizeof(Attribs[0]), &Attributes, &nAttributes );
if( HRESULT_FROM_WIN32(ERROR_DS_NO_ATTRIBUTE_OR_VALUE) == hResult ) { return ERROR_SUCCESS; } if( FAILED(hResult) ) return ConvertHresult(hResult);
if( 0 == nAttributes || NULL == Attributes ) return ERROR_SUCCESS;
Require( 1 == nAttributes ); Error = ERROR_SUCCESS;
for( i = 0; i < Attributes[0].dwNumValues ; i ++ ) { if( ADSTYPE_OCTET_STRING != Attributes[0].pADsValues[i].dwType ) { SetInternalFormatError(UNEXPECTED_COLLECTION_TYPE, TRUE); continue; }
Data = Attributes[0].pADsValues[i].OctetString.lpValue; DataLength = Attributes[0].pADsValues[i].OctetString.dwLength;
Result = ConvertBinarytoEAttrib(Data, DataLength, &ThisEAttrib); if( ERROR_SUCCESS == Result ) { if( OnlyADsPathPresent(&ThisEAttrib) ) { Result = StoreCollectBinaryAttributesInternal( hStore, Reserved, &ThisEAttrib, AttribName, ArrayToAddTo, RecursionDepth ); } else { Result = AddAttribToArray(ArrayToAddTo, &ThisEAttrib); } if( ERROR_SUCCESS != Result ) Error = Result; } else Error = Result; }
FreeADsMem(Attributes);
return Error; }
DWORD _inline SizeAfterSeparation( // the field separation character has to doubled.
IN LPWSTR String, // string with field separation character not escape'ed.
IN WCHAR Sep ) { DWORD RetVal;
RetVal = wcslen(String); while(String = wcschr(String, Sep ) ) { RetVal ++; }
return RetVal; }
LPWSTR ConvertStringToString( // duplicate any field_sep characters found
IN LPWSTR InStr, IN WCHAR PrefixChar, IN LPWSTR Str, // copy into this pre-allocated buffer
IN WCHAR Sep ) { *Str++ = PrefixChar; while( *InStr ) { if( Sep != *InStr ) { *Str ++ = *InStr; } else { *Str ++ = Sep; *Str ++ = Sep; } InStr ++; }
*Str = L'\0'; return Str; }
LPWSTR // Return the ptr to where the '\0' is stored
ConvertAddressToString( // convert ip address to dotted notation LPWSTR
IN DWORD Address, IN WCHAR PrefixChar, IN LPWSTR Str // copy into this pre-allocated buffer
) { LPSTR AsciiStr;
Address = htonl(Address); // convert to n/w order before making string..
*Str ++ = PrefixChar; AsciiStr = inet_ntoa(*(struct in_addr *)&Address);
while( *Str ++ = (WCHAR) *AsciiStr ++ ) ;
Str --; *Str = L'\0'; return Str; }
LPWSTR ConvertDwordToString( // convert a DWORD to string in 0x.... fmt
IN DWORD Dword, IN WCHAR PrefixChar, IN LPWSTR Str // copy into this pre-allocated buffer
) { UCHAR Ch; LPWSTR Stream; INT i;
Dword = htonl(Dword); // convert to n/w order before making string.
*Str ++ = PrefixChar; *Str ++ = L'0'; *Str ++ = L'x' ;
Stream = Str; Str += sizeof(Dword)*2; for( i = sizeof(Dword); i ; i -- ) { Ch = (BYTE)(Dword & 0x0F); Dword >>= 4; Stream[i*2 -1] = (Ch < 10)? (L'0'+Ch) : (Ch-10 + L'A'); Ch = (BYTE)(Dword & 0x0F); Dword >>= 4; Stream[i*2 -2] = (Ch < 10)? (L'0'+Ch) : (Ch-10 + L'A'); } *Str = L'\0'; return Str; }
LPWSTR ConvertBinaryToString( // convert a binary byte sequence to a string as 0F321B etc..
IN LPBYTE Bytes, IN DWORD nBytes, IN WCHAR PrefixChar, IN LPWSTR Str ) { BYTE Ch, Ch1, Ch2; DWORD i;
*Str ++ = PrefixChar;
for( i = 0; i < nBytes; i ++ ) { Ch = *Bytes ++; Ch1 = Ch >> 4; Ch2 = Ch & 0x0F;
if( Ch1 >= 10 ) *Str ++ = Ch1 - 10 + L'A'; else *Str ++ = Ch1 + L'0';
if( Ch2 >= 10 ) *Str ++ = Ch2 - 10 + L'A'; else *Str ++ = Ch2 + L'0'; }
*Str = L'\0'; return Str; }
DWORD ConvertEAttribToString( // inverse of ConvertStringtoEAttrib
IN PEATTRIB Attrib, // the attrib to encapsulate
IN OUT LPWSTR *String, // allocated string
IN WCHAR Sep ) { DWORD nChars; LPWSTR Str; WCHAR PrefixChar; AssertRet(String && Attrib, ERROR_INVALID_PARAMETER); *String = NULL;
nChars = 0; if( IS_ADDRESS1_PRESENT(Attrib) ) nChars += sizeof(L"$i000.000.000.000"); if( IS_ADDRESS2_PRESENT(Attrib) ) nChars += sizeof(L"$j000.000.000.000"); if( IS_ADDRESS3_PRESENT(Attrib) ) nChars += sizeof(L"$k000.000.000.000");
if( IS_ADSPATH_PRESENT(Attrib) ) { AssertRet( IS_STOREGETTYPE_PRESENT(Attrib), ERROR_INVALID_PARAMETER ); AssertRet( Attrib->ADsPath, ERROR_INVALID_PARAMETER ); nChars += sizeof(WCHAR) * SizeAfterSeparation(Attrib->ADsPath,Sep); nChars += sizeof(L"$p"); }
if( IS_FLAGS1_PRESENT(Attrib) ) nChars += sizeof(L"$f0x") + sizeof(DWORD)*2*sizeof(WCHAR); if( IS_FLAGS2_PRESENT(Attrib) ) nChars += sizeof(L"$g0x") + sizeof(DWORD)*2*sizeof(WCHAR); if( IS_DWORD1_PRESENT(Attrib) ) nChars += sizeof(L"$d0x") + sizeof(DWORD)*2*sizeof(WCHAR); if( IS_DWORD2_PRESENT(Attrib) ) nChars += sizeof(L"$e0x") + sizeof(DWORD)*2*sizeof(WCHAR);
if( IS_STRING1_PRESENT(Attrib) ) { AssertRet( Attrib->String1, ERROR_INVALID_PARAMETER ); nChars += sizeof(WCHAR) * SizeAfterSeparation(Attrib->String1,Sep); nChars += sizeof(L"$s"); } if( IS_STRING2_PRESENT(Attrib) ) { AssertRet( Attrib->String2, ERROR_INVALID_PARAMETER ); nChars += sizeof(WCHAR) * SizeAfterSeparation(Attrib->String2,Sep); nChars += sizeof(L"$t"); } if( IS_STRING3_PRESENT(Attrib) ) { AssertRet( Attrib->String3, ERROR_INVALID_PARAMETER ); nChars += sizeof(WCHAR) * SizeAfterSeparation(Attrib->String3,Sep); nChars += sizeof(L"$u"); } if( IS_STRING4_PRESENT(Attrib) ) { AssertRet( Attrib->String4, ERROR_INVALID_PARAMETER ); nChars += sizeof(WCHAR) * SizeAfterSeparation(Attrib->String4,Sep); nChars += sizeof(L"$v"); }
if( IS_BINARY1_PRESENT(Attrib) ) { nChars += sizeof(WCHAR) * 2 * Attrib->BinLen1; nChars += sizeof(L"$b"); }
if( IS_BINARY2_PRESENT(Attrib) ) { nChars += sizeof(WCHAR) * 2 * Attrib->BinLen2; nChars += sizeof(L"$c"); }
if( 0 == nChars ) return ERROR_SUCCESS; // nothing is present really.
Str = MemAlloc(nChars + sizeof(L"") ); // take care of terminating the string
if( NULL == Str ) return ERROR_NOT_ENOUGH_MEMORY;
*String = Str; // save the return value, as Str keeps changing
if( IS_ADDRESS1_PRESENT(Attrib) ) { Str = ConvertAddressToString(Attrib->Address1, ch_Address1, Str); *Str++ = Sep; } if( IS_ADDRESS2_PRESENT(Attrib) ) { Str = ConvertAddressToString(Attrib->Address2, ch_Address2, Str); *Str++ = Sep; } if( IS_ADDRESS3_PRESENT(Attrib) ) { Str = ConvertAddressToString(Attrib->Address3, ch_Address3, Str); *Str++ = Sep; }
if( IS_ADSPATH_PRESENT(Attrib) ) { switch(Attrib->StoreGetType) { case StoreGetChildType: PrefixChar = ch_ADsPath_relative; break; case StoreGetAbsoluteSameServerType: PrefixChar = ch_ADsPath_absolute; break; case StoreGetAbsoluteOtherServerType: PrefixChar = ch_ADsPath_diff_srvr; break; default: Require(FALSE); // too late to do anything about this now.
PrefixChar = ch_ADsPath_diff_srvr; break; } Str = ConvertStringToString(Attrib->ADsPath, PrefixChar, Str,Sep); *Str++ = Sep; }
if( IS_FLAGS1_PRESENT(Attrib) ) { Str = ConvertDwordToString(Attrib->Flags1, ch_Flags1, Str); *Str++ = Sep; } if( IS_FLAGS2_PRESENT(Attrib) ) { Str = ConvertDwordToString(Attrib->Flags2, ch_Flags2, Str); *Str++ = Sep; } if( IS_DWORD1_PRESENT(Attrib) ) { Str = ConvertDwordToString(Attrib->Dword1, ch_Dword1, Str); *Str++ = Sep; } if( IS_DWORD2_PRESENT(Attrib) ) { Str = ConvertDwordToString(Attrib->Dword2, ch_Dword2, Str); *Str++ = Sep; }
if( IS_STRING1_PRESENT(Attrib) ) { Str = ConvertStringToString(Attrib->String1, ch_String1, Str,Sep); *Str++ = Sep; } if( IS_STRING2_PRESENT(Attrib) ) { Str = ConvertStringToString(Attrib->String2, ch_String2, Str,Sep); *Str++ = Sep; } if( IS_STRING3_PRESENT(Attrib) ) { Str = ConvertStringToString(Attrib->String3, ch_String3, Str,Sep); *Str++ = Sep; } if( IS_STRING4_PRESENT(Attrib) ) { Str = ConvertStringToString(Attrib->String4, ch_String4, Str,Sep); *Str++ = Sep; } if( IS_BINARY1_PRESENT(Attrib) ) { Str = ConvertBinaryToString(Attrib->Binary1, Attrib->BinLen1, ch_Binary1, Str); *Str++ = Sep; } if( IS_BINARY2_PRESENT(Attrib) ) { Str = ConvertBinaryToString(Attrib->Binary2, Attrib->BinLen2, ch_Binary2, Str); }
*Str = L'\0'; Require(((LPBYTE)Str) < nChars + 1 + ((LPBYTE)(*String)) );
return ERROR_SUCCESS; }
LPBYTE ConvertDwordToBinary( // pack a DWORD in binary format
IN DWORD Dword, IN WCHAR Character, IN LPBYTE Buffer ) { *(LPWORD)Buffer = htons(Character); Buffer += sizeof(WORD); *(LPWORD)Buffer = htons(sizeof(DWORD)); Buffer += sizeof(WORD); *(DWORD UNALIGNED *)Buffer = htonl(Dword); Buffer += sizeof(DWORD); return Buffer; }
LPBYTE ConvertAddressToBinary( // pack an address to binary format..
IN DWORD Address, IN WCHAR Character, IN LPBYTE Buffer ) { return ConvertDwordToBinary(Address,Character,Buffer); }
LPBYTE ConvertStringToBinary( // pack a string in binary format
IN LPWSTR Str, IN WCHAR Character, IN LPBYTE Buffer ) { DWORD Size;
Size = sizeof(WCHAR)*(1+wcslen(Str));
*(LPWORD)Buffer = htons(Character); Buffer += sizeof(WORD); *(LPWORD)Buffer = htons((WORD)Size); Buffer += sizeof(WORD); memcpy(Buffer, Str, Size); Buffer += ROUND_UP_COUNT(Size, ALIGN_WORD);
return Buffer; }
DWORD ConvertEAttribToBinary( // inverse of ConvertBinarytoEAttrib
IN PEATTRIB Attrib, // the attrib to encapsulate
IN OUT LPBYTE *Bytes, // allocated buffer
IN OUT DWORD *nBytes // # of bytes allocated
) { DWORD nChars; LPBYTE Buf; WCHAR PrefixChar;
AssertRet(Bytes && Attrib && nBytes, ERROR_INVALID_PARAMETER); *Bytes = NULL; *nBytes =0;
nChars = 0; // WCHAR_opcode ~ WORD_size ~ DWORD_ipAddress
if( IS_ADDRESS1_PRESENT(Attrib) ) nChars += sizeof(WORD) + sizeof(WORD) + sizeof(DWORD); if( IS_ADDRESS2_PRESENT(Attrib) ) nChars += sizeof(WORD) + sizeof(WORD) + sizeof(DWORD); if( IS_ADDRESS3_PRESENT(Attrib) ) nChars += sizeof(WORD) + sizeof(WORD) + sizeof(DWORD);
if( IS_ADSPATH_PRESENT(Attrib) ) { AssertRet( IS_STOREGETTYPE_PRESENT(Attrib), ERROR_INVALID_PARAMETER ); AssertRet( Attrib->ADsPath, ERROR_INVALID_PARAMETER ); nChars += sizeof(WORD) + sizeof(WORD); // WCHAR_opcode ~ WORD_size
nChars += sizeof(WCHAR) * (1+ wcslen(Attrib->ADsPath)); }
// WCHAR_opcode ~ WORD_size ~ DWORD_flags
if( IS_FLAGS1_PRESENT(Attrib) ) nChars += sizeof(WORD) + sizeof(WORD) + sizeof(DWORD); if( IS_FLAGS2_PRESENT(Attrib) ) nChars += sizeof(WORD) + sizeof(WORD) + sizeof(DWORD); if( IS_DWORD1_PRESENT(Attrib) ) nChars += sizeof(WORD) + sizeof(WORD) + sizeof(DWORD); if( IS_DWORD2_PRESENT(Attrib) ) nChars += sizeof(WORD) + sizeof(WORD) + sizeof(DWORD);
if( IS_STRING1_PRESENT(Attrib) ) { AssertRet( Attrib->String1, ERROR_INVALID_PARAMETER ); nChars += sizeof(WORD) + sizeof(WORD); // WCHAR_opcode ~ WORD_size
nChars += sizeof(WCHAR) * (1 + wcslen(Attrib->String1)); } if( IS_STRING2_PRESENT(Attrib) ) { AssertRet( Attrib->String2, ERROR_INVALID_PARAMETER ); nChars += sizeof(WORD) + sizeof(WORD); // WCHAR_opcode ~ WORD_size
nChars += sizeof(WCHAR) * (1 + wcslen(Attrib->String2)); } if( IS_STRING3_PRESENT(Attrib) ) { AssertRet( Attrib->String3, ERROR_INVALID_PARAMETER ); nChars += sizeof(WORD) + sizeof(WORD); // WCHAR_opcode ~ WORD_size
nChars += sizeof(WCHAR) * (1 + wcslen(Attrib->String3)); } if( IS_STRING4_PRESENT(Attrib) ) { AssertRet( Attrib->String4, ERROR_INVALID_PARAMETER ); nChars += sizeof(WORD) + sizeof(WORD); // WCHAR_opcode ~ WORD_size
nChars += sizeof(WCHAR) * (1 + wcslen(Attrib->String4)); }
if( IS_BINARY1_PRESENT(Attrib) ) { nChars += sizeof(WORD) + sizeof(WORD); // WCHAR_opcode ~ WORD_size
nChars += ROUND_UP_COUNT(Attrib->BinLen1, ALIGN_WORD); }
if( IS_BINARY2_PRESENT(Attrib) ) { nChars += sizeof(WORD) + sizeof(WORD); // WCHAR_opcode ~ WORD_size
nChars += ROUND_UP_COUNT(Attrib->BinLen2, ALIGN_WORD); }
if( 0 == nChars ) return ERROR_SUCCESS; // nothing is present really.
Buf = MemAlloc(nChars); if( NULL == Buf ) return ERROR_NOT_ENOUGH_MEMORY;
*Bytes = Buf; // save the return value.. Buf itself is changed..
*nBytes = nChars; if( IS_ADDRESS1_PRESENT(Attrib) ) Buf = ConvertAddressToBinary(Attrib->Address1, ch_Address1, Buf); if( IS_ADDRESS2_PRESENT(Attrib) ) Buf = ConvertAddressToBinary(Attrib->Address2, ch_Address2, Buf); if( IS_ADDRESS3_PRESENT(Attrib) ) Buf = ConvertAddressToBinary(Attrib->Address3, ch_Address3, Buf);
if( IS_ADSPATH_PRESENT(Attrib) ) { switch(Attrib->StoreGetType) { case StoreGetChildType: PrefixChar = ch_ADsPath_relative; break; case StoreGetAbsoluteSameServerType: PrefixChar = ch_ADsPath_absolute; break; case StoreGetAbsoluteOtherServerType: PrefixChar = ch_ADsPath_diff_srvr; break; default: Require(FALSE); // too late to do anything about this now.
PrefixChar = ch_ADsPath_diff_srvr; break; } Buf = ConvertStringToBinary(Attrib->ADsPath, PrefixChar, Buf); }
if( IS_FLAGS1_PRESENT(Attrib) ) Buf = ConvertDwordToBinary(Attrib->Flags1, ch_Flags1, Buf); if( IS_FLAGS2_PRESENT(Attrib) ) Buf = ConvertDwordToBinary(Attrib->Flags2, ch_Flags2, Buf); if( IS_DWORD1_PRESENT(Attrib) ) Buf = ConvertDwordToBinary(Attrib->Dword1, ch_Dword1, Buf); if( IS_DWORD2_PRESENT(Attrib) ) Buf = ConvertDwordToBinary(Attrib->Dword2, ch_Dword2, Buf);
if( IS_STRING1_PRESENT(Attrib) ) Buf = ConvertStringToBinary(Attrib->String1, ch_String1, Buf); if( IS_STRING2_PRESENT(Attrib) ) Buf = ConvertStringToBinary(Attrib->String2, ch_String2, Buf); if( IS_STRING3_PRESENT(Attrib) ) Buf = ConvertStringToBinary(Attrib->String3, ch_String3, Buf); if( IS_STRING4_PRESENT(Attrib) ) Buf = ConvertStringToBinary(Attrib->String4, ch_String4, Buf);
if( IS_BINARY1_PRESENT(Attrib) ) { *(LPWORD)Buf = htons(ch_Binary1); Buf += sizeof(WORD); *(LPWORD)Buf = htons((WORD)Attrib->BinLen1); Buf += sizeof(WORD); memcpy(Buf, Attrib->Binary1, Attrib->BinLen1); Buf += ROUND_UP_COUNT(Attrib->BinLen1, ALIGN_WORD); }
if( IS_BINARY2_PRESENT(Attrib) ) { *(LPWORD)Buf = htons(ch_Binary2); Buf += sizeof(WORD); *(LPWORD)Buf = htons((WORD)Attrib->BinLen2); Buf += sizeof(WORD); memcpy(Buf, Attrib->Binary2, Attrib->BinLen2); Buf += ROUND_UP_COUNT(Attrib->BinLen2, ALIGN_WORD); }
Require( Buf == nChars + (*Bytes) );
return ERROR_SUCCESS; }
StoreUpdateAttributesInternal( // update a list of attributes
IN OUT LPSTORE_HANDLE hStore, // handle to obj to update
IN DWORD Reserved, // for future use, must be zero
IN LPWSTR AttribName, // name of attrib, must be string type
IN PARRAY Array, // list of attribs
IN WCHAR Sep ) //EndExport(function)
{ DWORD Result; HRESULT hResult; LONG nValues, i; ADS_ATTR_INFO Attribute; PADSVALUE Values; ARRAY_LOCATION Loc; LPWSTR Str; PEATTRIB ThisAttrib;
if( NULL == hStore || NULL == hStore->ADSIHandle ) return ERROR_INVALID_PARAMETER; if( NULL == AttribName || 0 != Reserved ) return ERROR_INVALID_PARAMETER; if( NULL == Array ) return ERROR_INVALID_PARAMETER;
nValues = MemArraySize(Array);
if( 0 == nValues ) { // delete the attribute
Attribute.pszAttrName = AttribName; Attribute.dwControlCode = ADS_ATTR_CLEAR; Attribute.dwADsType = ADSTYPE_CASE_IGNORE_STRING; Attribute.pADsValues = NULL; Attribute.dwNumValues = 0;
hResult = ADSISetObjectAttributes( /* hDSObject */ hStore->ADSIHandle, /* pAttributeEntr.. */ &Attribute, /* dwNumAttributes */ 1, /* pdwNumAttribut.. */ &nValues ); if( FAILED(hResult) || 1 != nValues ) { // something went wrong
return ConvertHresult(hResult); } return ERROR_SUCCESS; }
Values = MemAlloc(nValues * sizeof(ADSVALUE)); if( NULL == Values ) { // could not allocate ADs array
return ERROR_NOT_ENOUGH_MEMORY; }
for(i = 0, Result = MemArrayInitLoc(Array, &Loc) ; ERROR_FILE_NOT_FOUND != Result ; // convert to PADS_ATTR_INFO
i ++ , Result = MemArrayNextLoc(Array, &Loc) ) { Result = MemArrayGetElement(Array, &Loc, &ThisAttrib); //- ERROR_SUCCESS == Result && NULL != ThisAttrib
Str = NULL; Result = ConvertEAttribToString(ThisAttrib, &Str, Sep); if( ERROR_SUCCESS != Result ) { // something went wrong!
goto Cleanup; // free allocated memory
}
Values[i].dwType = ADSTYPE_CASE_IGNORE_STRING; Values[i].CaseIgnoreString = Str; }
Attribute.pszAttrName = AttribName; Attribute.dwControlCode = ADS_ATTR_UPDATE; Attribute.dwADsType = ADSTYPE_CASE_IGNORE_STRING; Attribute.pADsValues = Values; Attribute.dwNumValues = nValues;
hResult = ADSISetObjectAttributes( /* hDSObject */ hStore->ADSIHandle, /* pAttributeEntr.. */ &Attribute, /* dwNumAttributes */ 1, /* pdwNumAttribut.. */ &nValues ); if( FAILED(hResult) || 1 != nValues ) { // something went wrong
Result = ConvertHresult(hResult); } else Result = ERROR_SUCCESS;
Cleanup:
if( Values ) { // got to free allocated memory
while( i -- ) { // got to free converted strings
if( Values[i].CaseIgnoreString ) MemFree(Values[i].CaseIgnoreString); } MemFree(Values); }
return Result; }
//BeginExport(function)
//DOC StoreUpdateAttributes is sort of the converse of StoreCollectAttributes.
//DOC This function takes an array of type EATTRIB elements and updates the DS
//DOC with this array. This function does not work when the attrib is of type
//DOC OCTET_STRING etc. It works only with types that can be derived from
//DOC PrintableString.
DWORD StoreUpdateAttributes( // update a list of attributes
IN OUT LPSTORE_HANDLE hStore, // handle to obj to update
IN DWORD Reserved, // for future use, must be zero
IN LPWSTR AttribName, // name of attrib, must be string type
IN PARRAY Array // list of attribs
) //EndExport(function)
{ DWORD Result; HRESULT hResult;
Result = StoreUpdateAttributesInternal( hStore, Reserved, AttribName, Array, ch_FieldSep );
return Result; }
//BeginExport(function)
//DOC StoreUpdateBinaryAttributes is sort of the converse of StoreCollectBinaryAttributes
//DOC This function takes an array of type EATTRIB elements and updates the DS
//DOC with this array. This function works only when the attrib is of type
//DOC OCTET_STRING etc. It doesnt work with types that can be derived from
//DOC PrintableString!!!.
DWORD StoreUpdateBinaryAttributes( // update a list of attributes
IN OUT LPSTORE_HANDLE hStore, // handle to obj to update
IN DWORD Reserved, // for future use, must be zero
IN LPWSTR AttribName, // name of attrib, must be OCTET_STRING type
IN PARRAY Array // list of attribs
) //EndExport(function)
{ DWORD Result; HRESULT hResult; LONG nValues, i, nBytes; ADS_ATTR_INFO Attribute; PADSVALUE Values; ARRAY_LOCATION Loc; LPBYTE Bytes; PEATTRIB ThisAttrib;
if( NULL == hStore || NULL == hStore->ADSIHandle ) return ERROR_INVALID_PARAMETER; if( NULL == AttribName || 0 != Reserved ) return ERROR_INVALID_PARAMETER; if( NULL == Array ) return ERROR_INVALID_PARAMETER;
nValues = MemArraySize(Array);
if( 0 == nValues ) { // delete the attribute
Attribute.pszAttrName = AttribName; Attribute.dwControlCode = ADS_ATTR_CLEAR; Attribute.dwADsType = ADSTYPE_OCTET_STRING; Attribute.pADsValues = NULL; Attribute.dwNumValues = 0;
hResult = ADSISetObjectAttributes( /* hDSObject */ hStore->ADSIHandle, /* pAttributeEntr.. */ &Attribute, /* dwNumAttributes */ 1, /* pdwNumAttribut.. */ &nValues ); if( FAILED(hResult) || 1 != nValues ) { // something went wrong
return ConvertHresult(hResult); } return ERROR_SUCCESS; }
Values = MemAlloc(nValues * sizeof(ADSVALUE)); if( NULL == Values ) { // could not allocate ADs array
return ERROR_NOT_ENOUGH_MEMORY; }
for(i = 0, Result = MemArrayInitLoc(Array, &Loc) ; ERROR_FILE_NOT_FOUND != Result ; // convert to PADS_ATTR_INFO
i ++ , Result = MemArrayNextLoc(Array, &Loc) ) { Result = MemArrayGetElement(Array, &Loc, &ThisAttrib); //- ERROR_SUCCESS == Result && NULL != ThisAttrib
Bytes = NULL; nBytes =0; Result = ConvertEAttribToBinary(ThisAttrib, &Bytes, &nBytes); if( ERROR_SUCCESS != Result ) { // something went wrong!
goto Cleanup; // free allocated memory
}
Values[i].dwType = ADSTYPE_OCTET_STRING; Values[i].OctetString.dwLength = nBytes; Values[i].OctetString.lpValue = Bytes; }
Attribute.pszAttrName = AttribName; Attribute.dwControlCode = ADS_ATTR_UPDATE; Attribute.dwADsType = ADSTYPE_OCTET_STRING; Attribute.pADsValues = Values; Attribute.dwNumValues = nValues;
hResult = ADSISetObjectAttributes( /* hDSObject */ hStore->ADSIHandle, /* pAttributeEntr.. */ &Attribute, /* dwNumAttributes */ 1, /* pdwNumAttribut.. */ &nValues ); if( FAILED(hResult) || 1 != nValues ) { // something went wrong
Result = ConvertHresult(hResult); } else Result = ERROR_SUCCESS;
Cleanup:
if( Values ) { // got to free allocated memory
while( i -- ) { // got to free converted strings
if( Values[i].OctetString.lpValue ) MemFree(Values[i].OctetString.lpValue); } MemFree(Values); }
return Result; }
//================================================================================
// end of file
//================================================================================
|