windows-nt/Source/XPSP1/NT/ds/adsi/nwnds/common.cxx
2020-09-26 16:20:57 +08:00

1283 lines
34 KiB
C++

#include "nds.hxx"
#pragma hdrstop
FILTERS Filters[] = {
{L"user", NDS_USER_ID},
{L"group", NDS_GROUP_ID},
{L"queue", NDS_PRINTER_ID},
{L"domain", NDS_DOMAIN_ID},
{L"computer", NDS_COMPUTER_ID},
{L"service", NDS_SERVICE_ID},
{L"fileservice", NDS_FILESERVICE_ID},
{L"fileshare", NDS_FILESHARE_ID},
{L"class", NDS_CLASS_ID},
{L"functionalset", NDS_FUNCTIONALSET_ID},
{L"syntax", NDS_SYNTAX_ID},
{L"property", NDS_PROPERTY_ID},
{L"tree", NDS_TREE_ID},
{L"Organizational Unit", NDS_OU_ID},
{L"Organization", NDS_O_ID},
{L"Locality", NDS_LOCALITY_ID}
};
#define MAX_FILTERS (sizeof(Filters)/sizeof(FILTERS))
PFILTERS gpFilters = Filters;
DWORD gdwMaxFilters = MAX_FILTERS;
extern WCHAR * szProviderName;
struct _err_lookup_ {
LPWSTR errString;
int errNo;
} g_aErrLookup[] = {
{L"ERR_INSUFFICIENT_MEMORY ", -150 },
{L"ERR_REQUEST_UNKNOWN ", -251 },
{L"ERR_OF_SOME_SORT ", -255 },
{L"ERR_NOT_ENOUGH_MEMORY ", -301 },
{L"ERR_BAD_KEY ", -302 },
{L"ERR_BAD_CONTEXT ", -303 },
{L"ERR_BUFFER_FULL ", -304 },
{L"ERR_LIST_EMPTY ", -305 },
{L"ERR_BAD_SYNTAX ", -306 },
{L"ERR_BUFFER_EMPTY ", -307 },
{L"ERR_BAD_VERB ", -308 },
{L"ERR_EXPECTED_IDENTIFIER ", -309 },
{L"ERR_EXPECTED_EQUALS ", -310 },
{L"ERR_ATTR_TYPE_EXPECTED ", -311 },
{L"ERR_ATTR_TYPE_NOT_EXPECTED ", -312 },
{L"ERR_FILTER_TREE_EMPTY ", -313 },
{L"ERR_INVALID_OBJECT_NAME ", -314 },
{L"ERR_EXPECTED_RDN_DELIMITER ", -315 },
{L"ERR_TOO_MANY_TOKENS ", -316 },
{L"ERR_INCONSISTENT_MULTIAVA ", -317 },
{L"ERR_COUNTRY_NAME_TOO_LONG ", -318 },
{L"ERR_SYSTEM_ERROR ", -319 },
{L"ERR_CANT_ADD_ROOT ", -320 },
{L"ERR_UNABLE_TO_ATTACH ", -321 },
{L"ERR_INVALID_HANDLE ", -322 },
{L"ERR_BUFFER_ZERO_LENGTH ", -323 },
{L"ERR_INVALID_REPLICA_TYPE ", -324 },
{L"ERR_INVALID_ATTR_SYNTAX ", -325 },
{L"ERR_INVALID_FILTER_SYNTAX ", -326 },
{L"ERR_CONTEXT_CREATION ", -328 },
{L"ERR_INVALID_UNION_TAG ", -329 },
{L"ERR_INVALID_SERVER_RESPONSE ", -330 },
{L"ERR_NULL_POINTER ", -331 },
{L"ERR_NO_SERVER_FOUND ", -332 },
{L"ERR_NO_CONNECTION ", -333 },
{L"ERR_RDN_TOO_LONG ", -334 },
{L"ERR_DUPLICATE_TYPE ", -335 },
{L"ERR_DATA_STORE_FAILURE ", -336 },
{L"ERR_NOT_LOGGED_IN ", -337 },
{L"ERR_INVALID_PASSWORD_CHARS ", -338 },
{L"ERR_FAILED_SERVER_AUTHENT ", -339 },
{L"ERR_TRANSPORT ", -340 },
{L"ERR_NO_SUCH_SYNTAX ", -341 },
{L"ERR_INVALID_DS_NAME ", -342 },
{L"ERR_ATTR_NAME_TOO_LONG ", -343 },
{L"ERR_INVALID_TDS ", -344 },
{L"ERR_INVALID_DS_VERSION ", -345 },
{L"ERR_UNICODE_TRANSLATION ", -346 },
{L"ERR_SCHEMA_NAME_TOO_LONG ", -347 },
{L"ERR_UNICODE_FILE_NOT_FOUND ", -348 },
{L"ERR_UNICODE_ALREADY_LOADED ", -349 },
{L"ERR_NOT_CONTEXT_OWNER ", -350 },
{L"ERR_ATTEMPT_TO_AUTHENTICATE_0 ", -351 },
{L"ERR_NO_WRITABLE_REPLICAS ", -352 },
{L"ERR_DN_TOO_LONG ", -353 },
{L"ERR_RENAME_NOT_ALLOWED ", -354 },
{L"ERR_NO_SUCH_ENTRY ", -601 },
{L"ERR_NO_SUCH_VALUE ", -602 },
{L"ERR_NO_SUCH_ATTRIBUTE ", -603 },
{L"ERR_NO_SUCH_CLASS ", -604 },
{L"ERR_NO_SUCH_PARTITION ", -605 },
{L"ERR_ENTRY_ALREADY_EXISTS ", -606 },
{L"ERR_NOT_EFFECTIVE_CLASS ", -607 },
{L"ERR_ILLEGAL_ATTRIBUTE ", -608 },
{L"ERR_MISSING_MANDATORY ", -609 },
{L"ERR_ILLEGAL_DS_NAME ", -610 },
{L"ERR_ILLEGAL_CONTAINMENT ", -611 },
{L"ERR_CANT_HAVE_MULTIPLE_VALUES ", -612 },
{L"ERR_SYNTAX_VIOLATION ", -613 },
{L"ERR_DUPLICATE_VALUE ", -614 },
{L"ERR_ATTRIBUTE_ALREADY_EXISTS ", -615 },
{L"ERR_MAXIMUM_ENTRIES_EXIST ", -616 },
{L"ERR_DATABASE_FORMAT ", -617 },
{L"ERR_INCONSISTENT_DATABASE ", -618 },
{L"ERR_INVALID_COMPARISON ", -619 },
{L"ERR_COMPARISON_FAILED ", -620 },
{L"ERR_TRANSACTIONS_DISABLED ", -621 },
{L"ERR_INVALID_TRANSPORT ", -622 },
{L"ERR_SYNTAX_INVALID_IN_NAME ", -623 },
{L"ERR_REPLICA_ALREADY_EXISTS ", -624 },
{L"ERR_TRANSPORT_FAILURE ", -625 },
{L"ERR_ALL_REFERRALS_FAILED ", -626 },
{L"ERR_CANT_REMOVE_NAMING_VALUE ", -627 },
{L"ERR_OBJECT_CLASS_VIOLATION ", -628 },
{L"ERR_ENTRY_IS_NOT_LEAF ", -629 },
{L"ERR_DIFFERENT_TREE ", -630 },
{L"ERR_ILLEGAL_REPLICA_TYPE ", -631 },
{L"ERR_SYSTEM_FAILURE ", -632 },
{L"ERR_INVALID_ENTRY_FOR_ROOT ", -633 },
{L"ERR_NO_REFERRALS ", -634 },
{L"ERR_REMOTE_FAILURE ", -635 },
{L"ERR_UNREACHABLE_SERVER ", -636 },
{L"ERR_PREVIOUS_MOVE_IN_PROGRESS ", -637 },
{L"ERR_NO_CHARACTER_MAPPING ", -638 },
{L"ERR_INCOMPLETE_AUTHENTICATION ", -639 },
{L"ERR_INVALID_CERTIFICATE ", -640 },
{L"ERR_INVALID_REQUEST ", -641 },
{L"ERR_INVALID_ITERATION ", -642 },
{L"ERR_SCHEMA_IS_NONREMOVABLE ", -643 },
{L"ERR_SCHEMA_IS_IN_USE ", -644 },
{L"ERR_CLASS_ALREADY_EXISTS ", -645 },
{L"ERR_BAD_NAMING_ATTRIBUTES ", -646 },
{L"ERR_NOT_ROOT_PARTITION ", -647 },
{L"ERR_INSUFFICIENT_STACK ", -648 },
{L"ERR_INSUFFICIENT_BUFFER ", -649 },
{L"ERR_AMBIGUOUS_CONTAINMENT ", -650 },
{L"ERR_AMBIGUOUS_NAMING ", -651 },
{L"ERR_DUPLICATE_MANDATORY ", -652 },
{L"ERR_DUPLICATE_OPTIONAL ", -653 },
{L"ERR_PARTITION_BUSY ", -654 },
{L"ERR_MULTIPLE_REPLICAS ", -655 },
{L"ERR_CRUCIAL_REPLICA ", -656 },
{L"ERR_SCHEMA_SYNC_IN_PROGRESS ", -657 },
{L"ERR_SKULK_IN_PROGRESS ", -658 },
{L"ERR_TIME_NOT_SYNCHRONIZED ", -659 },
{L"ERR_RECORD_IN_USE ", -660 },
{L"ERR_DS_VOLUME_NOT_MOUNTED ", -661 },
{L"ERR_DS_VOLUME_IO_FAILURE ", -662 },
{L"ERR_DS_LOCKED ", -663 },
{L"ERR_OLD_EPOCH ", -664 },
{L"ERR_NEW_EPOCH ", -665 },
{L"ERR_INCOMPATIBLE_DS_VERSION ", -666 },
{L"ERR_PARTITION_ROOT ", -667 },
{L"ERR_ENTRY_NOT_CONTAINER ", -668 },
{L"ERR_FAILED_AUTHENTICATION ", -669 },
{L"ERR_INVALID_CONTEXT ", -670 },
{L"ERR_NO_SUCH_PARENT ", -671 },
{L"ERR_NO_ACCESS ", -672 },
{L"ERR_REPLICA_NOT_ON ", -673 },
{L"ERR_INVALID_NAME_SERVICE ", -674 },
{L"ERR_INVALID_TASK ", -675 },
{L"ERR_INVALID_CONN_HANDLE ", -676 },
{L"ERR_INVALID_IDENTITY ", -677 },
{L"ERR_DUPLICATE_ACL ", -678 },
{L"ERR_PARTITION_ALREADY_EXISTS ", -679 },
{L"ERR_TRANSPORT_MODIFIED ", -680 },
{L"ERR_ALIAS_OF_AN_ALIAS ", -681 },
{L"ERR_AUDITING_FAILED ", -682 },
{L"ERR_INVALID_API_VERSION ", -683 },
{L"ERR_SECURE_NCP_VIOLATION ", -684 },
{L"ERR_MOVE_IN_PROGRESS ", -685 },
{L"ERR_NOT_LEAF_PARTITION ", -686 },
{L"ERR_CANNOT_ABORT ", -687 },
{L"ERR_CACHE_OVERFLOW ", -688 },
{L"ERR_INVALID_SUBORDINATE_COUNT ", -689 },
{L"ERR_INVALID_RDN ", -690 },
{L"ERR_MOD_TIME_NOT_CURRENT ", -691 },
{L"ERR_INCORRECT_BASE_CLASS ", -692 },
{L"ERR_MISSING_REFERENCE ", -693 },
{L"ERR_LOST_ENTRY ", -694 },
{L"ERR_AGENT_ALREADY_REGISTERED ", -695 },
{L"ERR_DS_LOADER_BUSY ", -696 },
{L"ERR_DS_CANNOT_RELOAD ", -697 },
{L"ERR_REPLICA_IN_SKULK ", -698 },
{L"ERR_FATAL ", -699 },
{L"ERR_OBSOLETE_API ", -700 },
{L"ERR_SYNCHRONIZATION_DISABLED ", -701 },
{L"ERR_INVALID_PARAMETER ", -702 },
{L"ERR_DUPLICATE_TEMPLATE ", -703 },
{L"ERR_NO_MASTER_REPLICA ", -704 },
{L"ERR_DUPLICATE_CONTAINMENT ", -705 },
{L"ERR_NOT_SIBLING ", -706 },
{L"ERR_INVALID_SIGNATURE ", -707 },
{L"ERR_INVALID_RESPONSE ", -708 },
{L"ERR_INSUFFICIENT_SOCKETS ", -709 },
{L"ERR_DATABASE_READ_FAIL ", -710 },
{L"ERR_INVALID_CODE_PAGE ", -711 },
{L"ERR_INVALID_ESCAPE_CHAR ", -712 },
{L"ERR_INVALID_DELIMITERS ", -713 },
{L"ERR_NOT_IMPLEMENTED ", -714 },
{L"ERR_CHECKSUM_FAILURE ", -715 },
{L"ERR_CHECKSUMMING_NOT_SUPPORTED ", -716 },
{L"ERR_CRC_FAILURE ", -717 }
};
DWORD g_cErrLookup = sizeof(g_aErrLookup)/sizeof(g_aErrLookup[0]);
//+------------------------------------------------------------------------
//
// Class: Common
//
// Purpose: Contains Winnt routines and properties that are common to
// all Winnt objects. Winnt objects get the routines and
// properties through C++ inheritance.
//
//-------------------------------------------------------------------------
HRESULT
BuildADsPath(
BSTR Parent,
BSTR Name,
BSTR *pADsPath
)
{
LPWSTR lpADsPath = NULL;
WCHAR ProviderName[MAX_PATH];
HRESULT hr = S_OK;
DWORD dwLen = 0;
LPWSTR pszDisplayName = NULL;
//
// We will assert if bad parameters are passed to us.
// This is because this should never be the case. This
// is an internal call
//
ADsAssert(Parent && Name);
ADsAssert(pADsPath);
//
// Get the display name for the name; The display name will have the proper
// escaping for characters that have special meaning in an ADsPath like
// '/' etc.
//
hr = GetDisplayName(
Name,
&pszDisplayName
);
BAIL_ON_FAILURE(hr);
//
// Special case the Namespace object; if
// the parent is L"ADs:", then Name = ADsPath
//
if (!_wcsicmp(Parent, L"ADs:")) {
hr = ADsAllocString( pszDisplayName, pADsPath);
BAIL_ON_FAILURE(hr);
goto cleanup;
}
//
// Allocate the right side buffer
// 2 for // + a buffer of MAX_PATH
//
dwLen = wcslen(Parent) + wcslen(pszDisplayName) + 2 + MAX_PATH;
lpADsPath = (LPWSTR)AllocADsMem(dwLen*sizeof(WCHAR));
if (!lpADsPath) {
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
//
// The rest of the cases we expect valid data,
// Path, Parent and Name are read-only, the end-user
// cannot modify this data
//
//
// For the first object, the domain object we do not add
// the first backslash; so we examine that the parent is
// L"WinNT:" and skip the slash otherwise we start with
// the slash
//
wsprintf(ProviderName, L"%s:", szProviderName);
wcscpy(lpADsPath, Parent);
if (_wcsicmp(lpADsPath, ProviderName)) {
wcscat(lpADsPath, L"/");
}else {
wcscat(lpADsPath, L"//");
}
wcscat(lpADsPath, pszDisplayName);
hr = ADsAllocString( lpADsPath, pADsPath);
cleanup:
error:
if (lpADsPath) {
FreeADsMem(lpADsPath);
}
if (pszDisplayName) {
FreeADsMem(pszDisplayName);
}
RRETURN(hr);
}
HRESULT
BuildSchemaPath(
BSTR bstrADsPath,
BSTR bstrClass,
BSTR *pSchemaPath
)
{
WCHAR ADsSchema[MAX_PATH];
OBJECTINFO ObjectInfo;
POBJECTINFO pObjectInfo = &ObjectInfo;
CLexer Lexer(bstrADsPath);
HRESULT hr = S_OK;
memset(pObjectInfo, 0, sizeof(OBJECTINFO));
wcscpy(ADsSchema, L"");
memset(pObjectInfo, 0, sizeof(OBJECTINFO));
if (bstrClass && *bstrClass) {
hr = ADsObject(&Lexer, pObjectInfo);
BAIL_ON_FAILURE(hr);
if (pObjectInfo->TreeName) {
wsprintf(ADsSchema,L"%s://",pObjectInfo->ProviderName);
wcscat(ADsSchema, pObjectInfo->TreeName);
wcscat(ADsSchema,L"/schema/");
wcscat(ADsSchema, bstrClass);
}
}
hr = ADsAllocString( ADsSchema, pSchemaPath);
error:
if (pObjectInfo) {
FreeObjectInfo( pObjectInfo );
}
RRETURN(hr);
}
HRESULT
BuildADsGuid(
REFCLSID clsid,
BSTR *pADsClass
)
{
WCHAR ADsClass[MAX_PATH];
if (!StringFromGUID2(clsid, ADsClass, MAX_PATH)) {
//
// MAX_PATH should be more than enough for the GUID.
//
ADsAssert(!"GUID too big !!!");
RRETURN(E_FAIL);
}
RRETURN(ADsAllocString( ADsClass, pADsClass));
}
HRESULT
MakeUncName(
LPWSTR szSrcBuffer,
LPWSTR szTargBuffer
)
{
ADsAssert(szSrcBuffer && *szSrcBuffer);
wcscpy(szTargBuffer, L"\\\\");
wcscat(szTargBuffer, szSrcBuffer);
RRETURN(S_OK);
}
HRESULT
ValidateOutParameter(
BSTR * retval
)
{
if (!retval) {
RRETURN(E_ADS_BAD_PARAMETER);
}
RRETURN(S_OK);
}
PKEYDATA
CreateTokenList(
LPWSTR pKeyData,
WCHAR ch
)
{
BOOL fQuoteMode = FALSE; // TRUE means we're processing between
// quotation marks
BOOL fEscaped = FALSE; // TRUE means next one char to be
// processed should be treated as literal
DWORD cTokens;
DWORD cb;
PKEYDATA pResult;
LPWSTR pDest;
LPWSTR psz = pKeyData;
LPWSTR pszTokenStart = NULL;
LPWSTR *ppToken;
if (!psz || !*psz)
return NULL;
cTokens=1;
// Scan through the string looking for delimiters,
// ensuring that each is followed by a non-NULL character:
// If this char follows an unescaped backslash:
// Treat as literal, treat next char regularly (set fEscaped = FALSE)
// Else, if we're between quotation marks:
// If we see a quotation mark, leave quote mode
// Else, treat as literal
// Else, if we're not between quote marks, and we see a quote mark:
// Enter quote mode
// Else, if we see a backslash (and we're not already in escape or quote
// mode:
// Treat next char as literal (set fEscaped = TRUE)
// Else, if we see the delimiter, and the next char is non-NULL:
// *** Found end of a token --- Increment count of tokens ***
// Else:
// Do nothing, just a plain old character
// Go on to next character, and repeat
//
// Backslashes inside quotation marks are always treated as literals,
// since that is the definition of being inside quotation marks
while (*psz) {
if (fEscaped) {
fEscaped = FALSE;
}
else if (fQuoteMode) {
if (*psz == L'"') {
fQuoteMode = FALSE;
}
// else, do nothing, no delimiter since in quote mode
}
else if (*psz == L'"') {
fQuoteMode = TRUE;
}
else if (*psz == L'\\') {
fEscaped = TRUE;
}
else if ( (*psz == ch) && (*(psz+1))) {
cTokens++;
}
// else, do nothing, just a regular character
psz++;
}
cb = sizeof(KEYDATA) + (cTokens-1) * sizeof(LPWSTR) +
wcslen(pKeyData)*sizeof(WCHAR) + sizeof(WCHAR);
if (!(pResult = (PKEYDATA)AllocADsMem(cb)))
return NULL;
// Initialise pDest to point beyond the token pointers:
pDest = (LPWSTR)((LPBYTE)pResult + sizeof(KEYDATA) +
(cTokens-1) * sizeof(LPWSTR));
// Then copy the key data buffer there:
wcscpy(pDest, pKeyData);
ppToken = pResult->pTokens;
// Split into tokens at each delimiter be replacing the delimiter
// with a NULL
psz = pDest;
pszTokenStart = pDest;
fEscaped = FALSE;
fQuoteMode = FALSE;
while (*psz) {
if (fEscaped) {
fEscaped = FALSE;
}
else if (fQuoteMode) {
if (*psz == L'"') {
fQuoteMode = FALSE;
}
// else, do nothing, no delimiter since in quote mode
}
else if (*psz == L'"') {
fQuoteMode = TRUE;
}
else if (*psz == L'\\') {
fEscaped = TRUE;
}
else if ((*psz == ch) && (*(psz+1))) {
*psz = '\0';
*ppToken++ = pszTokenStart;
pszTokenStart = psz + 1;
}
// else, do nothing, just a regular character
psz++;
}
*ppToken = pszTokenStart;
pResult->cTokens = cTokens;
return( pResult );
}
HRESULT
NDSConvertDWORDtoDATE(
DWORD dwDate,
DATE * pdaDate
)
{
FILETIME fileTime;
LARGE_INTEGER tmpTime;
WORD wFatDate;
WORD wFatTime;
HRESULT hr = S_OK;
::RtlSecondsSince1970ToTime(dwDate, &tmpTime );
fileTime.dwLowDateTime = tmpTime.LowPart;
fileTime.dwHighDateTime = tmpTime.HighPart;
if (!FileTimeToDosDateTime( &fileTime, &wFatDate, &wFatTime)){
hr = HRESULT_FROM_WIN32(GetLastError());
BAIL_ON_FAILURE(hr);
}
if (!DosDateTimeToVariantTime(wFatDate, wFatTime, pdaDate)){
hr = HRESULT_FROM_WIN32(GetLastError());
BAIL_ON_FAILURE(hr);
}
error:
RRETURN(hr);
}
HRESULT
NDSConvertDATEtoDWORD(
DATE daDate,
DWORD *pdwDate
)
{
FILETIME fileTime;
LARGE_INTEGER tmpTime;
WORD wFatDate;
WORD wFatTime;
HRESULT hr = S_OK;
if(!VariantTimeToDosDateTime(daDate, &wFatDate, &wFatTime)){
hr = HRESULT_FROM_WIN32(GetLastError());
BAIL_ON_FAILURE(hr);
}
if (!DosDateTimeToFileTime(wFatDate, wFatTime, &fileTime)) {
hr = HRESULT_FROM_WIN32(GetLastError());
BAIL_ON_FAILURE(hr);
}
tmpTime.LowPart = fileTime.dwLowDateTime;
tmpTime.HighPart = fileTime.dwHighDateTime;
::RtlTimeToSecondsSince1970(&tmpTime, (ULONG *)pdwDate);
error:
RRETURN(hr);
}
DWORD
ADsNwNdsOpenObject(
IN LPWSTR ObjectDN,
IN CCredentials& Credentials,
OUT HANDLE * lphObject,
OUT LPWSTR lpObjectFullName OPTIONAL,
OUT LPWSTR lpObjectClassName OPTIONAL,
OUT LPDWORD lpdwModificationTime,
OUT LPDWORD lpdwSubordinateCount OPTIONAL
)
{
HRESULT hr = S_OK;
DWORD dwStatus = S_OK;
LPWSTR pszUserName = NULL;
LPWSTR pszPassword = NULL;
hr = Credentials.GetUserName(&pszUserName);
hr = Credentials.GetPassword(&pszPassword);
// dwStatus = NwNdsOpenObject(
// ObjectDN,
// pszUserName,
// pszPassword,
// lphObject,
// NULL, // szObjectName optional parameter
// lpObjectFullName,
// lpObjectClassName,
// lpdwModificationTime,
// lpdwSubordinateCount
// );
if (pszUserName) {
FreeADsStr(pszUserName);
}
if (pszPassword) {
FreeADsStr(pszPassword);
}
return(dwStatus);
}
HRESULT
CheckAndSetExtendedError(
DWORD dwRetval
)
{
DWORD dwLastError;
WCHAR pszError[MAX_PATH];
WCHAR pszProviderName[MAX_PATH];
INT numChars;
HRESULT hr =S_OK;
wcscpy(pszError, L"");
wcscpy(pszProviderName, L"");
if (NWCCODE_SUCCEEDED(dwRetval)){
hr = S_OK;
}
else {
if (dwRetval == ERR_NO_ACCESS) {
hr = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
}
else if (dwRetval == ERR_ENTRY_ALREADY_EXISTS) {
hr = HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS);
}
else if (dwRetval == ERR_NO_SUCH_ENTRY) {
hr = HRESULT_FROM_WIN32(ERROR_BAD_NETPATH);
}
else {
hr = HRESULT_FROM_WIN32(ERROR_EXTENDED_ERROR);
numChars = LoadString( g_hInst,
NWNDS_PROVIDER_ID,
pszProviderName,
MAX_PATH -1);
//
// Set the default error string
wsprintf (pszError, L"NDS ccode = %x", dwRetval);
for (DWORD i=0; i < g_cErrLookup; i++ ) {
if ((DWORD) g_aErrLookup[i].errNo == dwRetval) {
wcscat (pszError, L"; ");
wcscat (pszError, g_aErrLookup[i].errString);
break;
}
}
ADsSetLastError(
dwRetval,
pszError,
pszProviderName
);
}
}
RRETURN(hr);
}
HRESULT
CopyObject(
IN NDS_CONTEXT_HANDLE hDestADsContext,
IN LPWSTR pszSrcADsPath,
IN LPWSTR pszDestContainer,
IN LPWSTR pszCommonName, //optional
IN CCredentials& Credentials,
OUT VOID ** ppObject
)
{
HRESULT hr = S_OK;
LPWSTR pszSrcNDSTreeName = NULL, pszSrcNDSDn = NULL;
LPWSTR pszChildNDSTreeName = NULL, pszChildNDSDn = NULL;
NDS_CONTEXT_HANDLE hSrcADsContext = NULL;
BSTR bstrChildADsPath = NULL;
NDS_BUFFER_HANDLE hDestOperationData = NULL;
NDS_BUFFER_HANDLE hAttrOperationData = NULL;
LPWSTR pszObjectClassName = NULL;
DWORD dwNumEntries = 0L;
DWORD dwNumEntriesDefs = 0L;
LPNDS_ATTR_INFO lpEntries = NULL;
LPWSTR pszParent= NULL;
LPWSTR pszRelativeName = NULL;
LPWSTR pszCN = NULL;
DWORD i = 0;
DWORD dwInfoType;
LPNDS_ATTR_DEF lpAttrDef = NULL;
IADs *pADs = NULL;
LPWSTR *ppszAttrs = NULL;
//
// allocate all variables that are needed
//
pszParent = (LPWSTR)AllocADsMem(MAX_PATH* sizeof(WCHAR));
if (!pszParent){
hr = E_OUTOFMEMORY;
goto error;
}
pszCN = (LPWSTR)AllocADsMem(MAX_PATH* sizeof(WCHAR));
if (!pszCN){
hr = E_OUTOFMEMORY;
goto error;
}
hr = BuildADsParentPath(
pszSrcADsPath,
pszParent,
pszCN
);
BAIL_ON_FAILURE(hr);
hr = BuildNDSPathFromADsPath2(
pszSrcADsPath,
&pszSrcNDSTreeName,
&pszSrcNDSDn
);
BAIL_ON_FAILURE(hr);
hr = ADsNdsOpenContext(
pszSrcNDSTreeName,
Credentials,
&hSrcADsContext
);
BAIL_ON_FAILURE(hr);
hr = ADsNdsReadObject(
hSrcADsContext,
pszSrcNDSDn,
DS_ATTRIBUTE_VALUES,
NULL,
(DWORD) -1, // signifies all attributes need to be returned
NULL,
&lpEntries,
&dwNumEntries
);
BAIL_ON_FAILURE(hr);
//
// create the destination object
//
// use the name given by the user if given at all
// otherwise use the name of the source
//
if ( pszCommonName != NULL) {
pszRelativeName = pszCommonName;
} else {
pszRelativeName = pszCN;
}
hr = BuildADsPath(
pszDestContainer,
pszRelativeName,
&bstrChildADsPath
);
BAIL_ON_FAILURE(hr);
hr = BuildNDSPathFromADsPath2(
bstrChildADsPath,
&pszChildNDSTreeName,
&pszChildNDSDn
);
BAIL_ON_FAILURE(hr);
hr = ADsNdsCreateBuffer(
hDestADsContext,
DSV_ADD_ENTRY,
&hDestOperationData
);
BAIL_ON_FAILURE(hr);
ppszAttrs = (LPWSTR *) AllocADsMem(sizeof(LPWSTR) * dwNumEntries);
if (!ppszAttrs) {
BAIL_ON_FAILURE(hr = E_OUTOFMEMORY);
}
for(i=0; i< dwNumEntries; i++)
ppszAttrs[i] = lpEntries[i].szAttributeName;
hr = ADsNdsReadAttrDef(
hDestADsContext,
DS_ATTR_DEFS,
ppszAttrs,
dwNumEntries,
&hAttrOperationData
);
BAIL_ON_FAILURE(hr);
hr = ADsNdsGetAttrDefListFromBuffer(
hDestADsContext,
hAttrOperationData,
&dwNumEntriesDefs,
&dwInfoType,
& lpAttrDef
);
BAIL_ON_FAILURE(hr);
for (i=0; i< dwNumEntriesDefs; i++){
if(wcscmp(lpEntries[i].szAttributeName, ACL_name) == 0){
//
// skip this attribute. Let it default
//
continue;
}
if(wcscmp(lpEntries[i].szAttributeName, OBJECT_CLASS_name) == 0){
hr = ADsNdsPutInBuffer(
hDestADsContext,
hDestOperationData,
lpEntries[i].szAttributeName,
lpEntries[i].dwSyntaxId,
lpEntries[i].lpValue,
1,
DS_ADD_ATTRIBUTE
);
BAIL_ON_FAILURE(hr);
pszObjectClassName = lpEntries[i].lpValue ?
lpEntries[i].lpValue[0].NdsValue.value_20.ClassName :
NULL;
} else if ( (lpAttrDef[i].dwFlags & DS_READ_ONLY_ATTR)
|| (lpAttrDef[i].dwFlags & DS_HIDDEN_ATTR) ){
//
// skip this value
//
continue;
} else {
hr = ADsNdsPutInBuffer(
hDestADsContext,
hDestOperationData,
lpEntries[i].szAttributeName,
lpEntries[i].dwSyntaxId,
lpEntries[i].lpValue,
lpEntries[i].dwNumberOfValues,
DS_ADD_ATTRIBUTE
);
BAIL_ON_FAILURE(hr);
}
}
hr = ADsNdsAddObject(
hDestADsContext,
pszChildNDSDn,
hDestOperationData
);
BAIL_ON_FAILURE(hr);
if (!pszObjectClassName) {
BAIL_ON_FAILURE(hr = E_FAIL);
}
if (_wcsicmp(pszObjectClassName, L"user") == 0) {
hr = ADsNdsGenObjectKey(hDestADsContext,
pszChildNDSDn);
BAIL_ON_FAILURE(hr);
}
hr = CNDSGenObject::CreateGenericObject(
pszDestContainer,
pszRelativeName,
pszObjectClassName,
Credentials,
ADS_OBJECT_BOUND,
IID_IADs,
(void **)&pADs
);
BAIL_ON_FAILURE(hr);
//
// InstantiateDerivedObject should add-ref this pointer for us.
//
hr = InstantiateDerivedObject(
pADs,
Credentials,
IID_IUnknown,
ppObject
);
if (FAILED(hr)) {
hr = pADs->QueryInterface(
IID_IUnknown,
ppObject
);
BAIL_ON_FAILURE(hr);
}
error:
FreeADsMem(pszParent);
FreeADsMem(pszCN);
FreeADsStr(pszSrcNDSTreeName);
FreeADsStr(pszSrcNDSDn);
FreeADsStr(pszChildNDSTreeName);
FreeADsStr(pszChildNDSDn);
FreeADsMem(ppszAttrs);
if (bstrChildADsPath) {
SysFreeString(bstrChildADsPath);
}
if (hDestOperationData) {
ADsNdsFreeBuffer(hDestOperationData);
}
if (hAttrOperationData) {
ADsNdsFreeBuffer(hAttrOperationData);
}
if(hSrcADsContext){
ADsNdsCloseContext(hSrcADsContext);
}
if (pADs){
pADs->Release();
}
FreeNdsAttrInfo(lpEntries, dwNumEntries);
ADsNdsFreeAttrDefList(lpAttrDef, dwNumEntriesDefs);
RRETURN(hr);
}
HRESULT
MoveObject(
IN NDS_CONTEXT_HANDLE hDestADsContext,
IN LPWSTR pszSrcADsPath,
IN LPWSTR pszDestContainer,
IN LPWSTR pszCommonName, //optional
IN CCredentials& Credentials,
OUT VOID ** ppObject
)
{
HRESULT hr = S_OK;
LPWSTR pszSrcNDSTreeName = NULL, pszSrcNDSDn = NULL;
LPWSTR pszParentNDSTreeName = NULL, pszParentNDSDn = NULL;
NDS_CONTEXT_HANDLE hSrcADsContext = NULL;
LPWSTR pszObjectClassName = NULL;
DWORD dwNumEntries = 0L;
LPNDS_ATTR_INFO lpEntries = NULL;
LPWSTR pszParent= NULL;
LPWSTR pszRelativeName = NULL;
LPWSTR pszCN = NULL;
IADs *pADs = NULL;
LPWSTR pszAttrs = L"object Class";
//
// allocate all variables that are needed
//
pszParent = (LPWSTR)AllocADsMem(MAX_PATH* sizeof(WCHAR));
if (!pszParent){
hr = E_OUTOFMEMORY;
goto error;
}
pszCN = (LPWSTR)AllocADsMem(MAX_PATH* sizeof(WCHAR));
if (!pszCN){
hr = E_OUTOFMEMORY;
goto error;
}
hr = BuildADsParentPath(
pszSrcADsPath,
pszParent,
pszCN
);
BAIL_ON_FAILURE(hr);
hr = BuildNDSPathFromADsPath2(
pszSrcADsPath,
&pszSrcNDSTreeName,
&pszSrcNDSDn
);
BAIL_ON_FAILURE(hr);
hr = ADsNdsOpenContext(
pszSrcNDSTreeName,
Credentials,
&hSrcADsContext
);
BAIL_ON_FAILURE(hr);
//
// Just get the objectClass attribute
//
hr = ADsNdsReadObject(
hSrcADsContext,
pszSrcNDSDn,
DS_ATTRIBUTE_VALUES,
&pszAttrs,
1,
NULL,
&lpEntries,
&dwNumEntries
);
BAIL_ON_FAILURE(hr);
if (dwNumEntries != 1) {
BAIL_ON_FAILURE(hr = E_FAIL);
}
pszObjectClassName = (lpEntries[0].lpValue) ?
lpEntries[0].lpValue[0].NdsValue.value_20.ClassName :
NULL;
if (!pszObjectClassName) {
BAIL_ON_FAILURE(E_FAIL);
}
hr = BuildNDSPathFromADsPath2(
pszDestContainer,
&pszParentNDSTreeName,
&pszParentNDSDn
);
BAIL_ON_FAILURE(hr);
//
// use the name given by the user if given at all
// otherwise use the name of the source
//
if ( pszCommonName != NULL) {
pszRelativeName = pszCommonName;
} else {
pszRelativeName = pszCN;
}
//
// If the relative name has changed and parent hasn't changed, just do a
// simple rename
//
if ((_wcsicmp(pszParent,pszDestContainer) == 0) &&
(_wcsicmp(pszCN,pszRelativeName) != 0)) {
hr = ADsNdsRenameObject(
hDestADsContext,
pszSrcNDSDn,
pszRelativeName
);
BAIL_ON_FAILURE(hr);
}
//
// If the parent has changed
//
if (_wcsicmp(pszParent,pszDestContainer) != 0) {
hr = ADsNdsMoveObject(
hDestADsContext,
pszSrcNDSDn,
pszParentNDSDn,
pszRelativeName
);
BAIL_ON_FAILURE(hr);
}
if (!pszObjectClassName) {
BAIL_ON_FAILURE(hr = E_FAIL);
}
hr = CNDSGenObject::CreateGenericObject(
pszDestContainer,
pszRelativeName,
pszObjectClassName,
Credentials,
ADS_OBJECT_BOUND,
IID_IADs,
(void **)&pADs
);
BAIL_ON_FAILURE(hr);
//
// InstantiateDerivedObject should add-ref this pointer for us.
//
hr = InstantiateDerivedObject(
pADs,
Credentials,
IID_IUnknown,
ppObject
);
if (FAILED(hr)) {
hr = pADs->QueryInterface(
IID_IUnknown,
ppObject
);
BAIL_ON_FAILURE(hr);
}
error:
FreeADsMem(pszParent);
FreeADsMem(pszCN);
FreeADsStr(pszSrcNDSTreeName);
FreeADsStr(pszSrcNDSDn);
FreeADsStr(pszParentNDSTreeName);
FreeADsStr(pszParentNDSDn);
if(hSrcADsContext){
ADsNdsCloseContext(hSrcADsContext);
}
if (pADs){
pADs->Release();
}
FreeNdsAttrInfo( lpEntries, dwNumEntries );
RRETURN(hr);
}
HRESULT
ConvertDWORDtoSYSTEMTIME(
DWORD dwDate,
LPSYSTEMTIME pSystemTime
)
{
FILETIME fileTime;
LARGE_INTEGER tmpTime;
HRESULT hr = S_OK;
::RtlSecondsSince1970ToTime(dwDate, &tmpTime );
fileTime.dwLowDateTime = tmpTime.LowPart;
fileTime.dwHighDateTime = tmpTime.HighPart;
if (!FileTimeToSystemTime( &fileTime, pSystemTime)){
hr = HRESULT_FROM_WIN32(GetLastError());
}
RRETURN(hr);
}
HRESULT
ConvertSYSTEMTIMEtoDWORD(
CONST SYSTEMTIME *pSystemTime,
DWORD *pdwDate
)
{
FILETIME fileTime;
LARGE_INTEGER tmpTime;
HRESULT hr = S_OK;
if (!SystemTimeToFileTime(pSystemTime,&fileTime)) {
hr = HRESULT_FROM_WIN32(GetLastError());
BAIL_ON_FAILURE(hr);
}
tmpTime.LowPart = fileTime.dwLowDateTime;
tmpTime.HighPart = fileTime.dwHighDateTime;
::RtlTimeToSecondsSince1970(&tmpTime, (ULONG *)pdwDate);
error:
RRETURN(hr);
}
HRESULT
InitializeNWLibrary(
void
)
{
NWDSCCODE ccode;
HRESULT hr = S_OK;
LCONV lConvInfo;
ccode = NWCallsInit(NULL, NULL);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
ccode = NWCLXInit(NULL, NULL);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
NWLlocaleconv(&lConvInfo);
ccode = NWInitUnicodeTables(lConvInfo.country_id,lConvInfo.code_page);
CHECK_AND_SET_EXTENDED_ERROR(ccode, hr);
error:
RRETURN(hr);
}