1283 lines
34 KiB
C++
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);
|
|
|
|
}
|
|
|