You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
10539 lines
354 KiB
10539 lines
354 KiB
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
Nds32.c
|
|
|
|
Abstract:
|
|
|
|
This module implements functions to Read, Add, Modify, and Remove
|
|
NDS Objects and Attributes using the Microsoft Netware redirector.
|
|
|
|
Author:
|
|
|
|
Glenn Curtis [GlennC] 04-Jan-1996 - New NDS function implementations
|
|
Glenn Curtis [GlennC] 24-Apr-1996 - Added schema APIs
|
|
Glenn Curtis [GlennC] 20-Jun-1996 - Added search API
|
|
Felix Wong [t-felixw] 24-Sep-1995 - Added Win95 Support
|
|
Glenn Curtis [GlennC] 20-Nov-1996 - Improved search API
|
|
Glenn Curtis [GlennC] 02-Jan-1997 - Added rename object API
|
|
Tommy Evans [tommye] 21-Apr-2000 - Moved the NDS_OBJECT typedef out and
|
|
renamed to NDS_OBJECT_PRIV.
|
|
|
|
--*/
|
|
|
|
#include <procs.h>
|
|
#include <nds32.h>
|
|
#include <align.h>
|
|
#include <nwapi32.h>
|
|
#include <nwpkstr.h>
|
|
|
|
#ifdef WIN95
|
|
#include <msnwapi.h>
|
|
#include <utils95.h>
|
|
#include <ndsapi95.h>
|
|
#endif
|
|
|
|
/* Definitions */
|
|
|
|
#define NDS_SIGNATURE 0x6E656C67 /* glen */
|
|
#define ONE_KB 1024
|
|
#define TWO_KB (ONE_KB*2)
|
|
#define FOUR_KB (ONE_KB*4)
|
|
#define EIGHT_KB (ONE_KB*8)
|
|
#define SIXTEEN_KB (ONE_KB*16)
|
|
#define THIRY_TWO_KB (ONE_KB*32)
|
|
#define SIXTY_FOUR_KB (ONE_KB*64)
|
|
#define ONE_TWENTY_EIGHT_KB (ONE_KB*128)
|
|
#define NDS_MAX_BUFFER (ONE_KB*63)
|
|
|
|
#define NDS_SEARCH_ENTRY 0
|
|
#define NDS_SEARCH_SUBORDINATES 1
|
|
#define NDS_SEARCH_SUBTREE 2
|
|
|
|
#define NDS_DEREF_ALIASES 0x00000000
|
|
#define NDS_DONT_DEREF_ALIASES 0x00010000
|
|
|
|
/* NetWare NDS NCP function identifiers */
|
|
|
|
#define NETWARE_NDS_FUNCTION_RESOLVE_NAME 0x00000001
|
|
#define NETWARE_NDS_FUNCTION_READ_OBJECT 0x00000003
|
|
#define NETWARE_NDS_FUNCTION_LIST 0x00000005
|
|
#define NETWARE_NDS_FUNCTION_SEARCH 0x00000006
|
|
#define NETWARE_NDS_FUNCTION_ADD_OBJECT 0x00000007
|
|
#define NETWARE_NDS_FUNCTION_REMOVE_OBJECT 0x00000008
|
|
#define NETWARE_NDS_FUNCTION_MODIFY_OBJECT 0x00000009
|
|
#define NETWARE_NDS_FUNCTION_MODIFY_RDN 0x0000000A
|
|
#define NETWARE_NDS_FUNCTION_DEFINE_ATTR 0x0000000B
|
|
#define NETWARE_NDS_FUNCTION_READ_ATTR_DEF 0x0000000C
|
|
#define NETWARE_NDS_FUNCTION_REMOVE_ATTR_DEF 0x0000000D
|
|
#define NETWARE_NDS_FUNCTION_DEFINE_CLASS 0x0000000E
|
|
#define NETWARE_NDS_FUNCTION_READ_CLASS_DEF 0x0000000F
|
|
#define NETWARE_NDS_FUNCTION_MODIFY_CLASS 0x00000010
|
|
#define NETWARE_NDS_FUNCTION_REMOVE_CLASS_DEF 0x00000011
|
|
#define NETWARE_NDS_FUNCTION_LIST_CONT_CLASSES 0x00000012
|
|
#define NETWARE_NDS_FUNCTION_GET_EFFECTIVE_RIGHTS 0x00000013
|
|
#define NETWARE_NDS_FUNCTION_BEGIN_MOVE_OBJECT 0x0000002A
|
|
#define NETWARE_NDS_FUNCTION_FINISH_MOVE_OBJECT 0x0000002B
|
|
#define NETWARE_NDS_FUNCTION_GET_SERVER_ADDRESS 0x00000035
|
|
|
|
|
|
/* Data structure definitions */
|
|
|
|
typedef struct
|
|
{
|
|
DWORD dwBufferId;
|
|
DWORD dwOperation;
|
|
|
|
//
|
|
// About the request buffer
|
|
//
|
|
DWORD dwRequestBufferSize;
|
|
DWORD dwRequestAvailableBytes;
|
|
DWORD dwNumberOfRequestEntries;
|
|
DWORD dwLengthOfRequestData;
|
|
|
|
//
|
|
// The request buffer
|
|
//
|
|
LPBYTE lpRequestBuffer;
|
|
|
|
//
|
|
// About the reply buffer
|
|
//
|
|
DWORD dwReplyBufferSize;
|
|
DWORD dwReplyAvailableBytes;
|
|
DWORD dwNumberOfReplyEntries;
|
|
DWORD dwLengthOfReplyData;
|
|
|
|
//
|
|
// More about the reply buffer
|
|
//
|
|
DWORD dwReplyInformationType;
|
|
|
|
//
|
|
// The reply buffer
|
|
//
|
|
LPBYTE lpReplyBuffer;
|
|
|
|
//
|
|
// About the index buffer
|
|
//
|
|
DWORD dwIndexBufferSize;
|
|
DWORD dwIndexAvailableBytes;
|
|
DWORD dwNumberOfIndexEntries;
|
|
DWORD dwLengthOfIndexData;
|
|
|
|
//
|
|
// More about the index buffer
|
|
//
|
|
DWORD dwCurrentIndexEntry;
|
|
|
|
//
|
|
// The index buffer
|
|
//
|
|
LPBYTE lpIndexBuffer;
|
|
|
|
//
|
|
// About the syntax buffer
|
|
//
|
|
DWORD dwSyntaxBufferSize;
|
|
DWORD dwSyntaxAvailableBytes;
|
|
DWORD dwNumberOfSyntaxEntries;
|
|
DWORD dwLengthOfSyntaxData;
|
|
|
|
//
|
|
// The syntax buffer
|
|
//
|
|
LPBYTE lpSyntaxBuffer;
|
|
|
|
//
|
|
// A place to keep the search from object path ...
|
|
//
|
|
WCHAR szPath[NDS_MAX_NAME_CHARS + 4];
|
|
|
|
} NDS_BUFFER, * LPNDS_BUFFER;
|
|
|
|
|
|
/* Local Function Definitions */
|
|
|
|
VOID
|
|
PrepareAddEntry(
|
|
LPBYTE lpTempEntry,
|
|
UNICODE_STRING AttributeName,
|
|
DWORD dwSyntaxID,
|
|
LPBYTE lpAttributeValues,
|
|
DWORD dwValueCount,
|
|
LPDWORD lpdwLengthInBytes );
|
|
|
|
VOID
|
|
PrepareModifyEntry(
|
|
LPBYTE lpTempEntry,
|
|
UNICODE_STRING AttributeName,
|
|
DWORD dwSyntaxID,
|
|
DWORD dwAttrModificationOperation,
|
|
LPBYTE lpAttributeValues,
|
|
DWORD dwValueCount,
|
|
LPDWORD lpdwLengthInBytes );
|
|
|
|
VOID
|
|
PrepareReadEntry(
|
|
LPBYTE lpTempEntry,
|
|
UNICODE_STRING AttributeName,
|
|
LPDWORD lpdwLengthInBytes );
|
|
|
|
DWORD
|
|
CalculateValueDataSize(
|
|
DWORD dwSyntaxId,
|
|
LPBYTE lpAttributeValues,
|
|
DWORD dwValueCount );
|
|
|
|
VOID
|
|
AppendValueToEntry(
|
|
LPBYTE lpBuffer,
|
|
DWORD dwSyntaxId,
|
|
LPBYTE lpAttributeValues,
|
|
DWORD dwValueCount,
|
|
LPDWORD lpdwLengthInBytes );
|
|
|
|
DWORD
|
|
MapNetwareErrorCode(
|
|
DWORD dwNetwareError );
|
|
|
|
DWORD
|
|
IndexReadAttrDefReplyBuffer(
|
|
LPNDS_BUFFER lpNdsBuffer );
|
|
|
|
DWORD
|
|
IndexReadClassDefReplyBuffer(
|
|
LPNDS_BUFFER lpNdsBuffer );
|
|
|
|
DWORD
|
|
IndexReadObjectReplyBuffer(
|
|
LPNDS_BUFFER lpNdsBuffer );
|
|
|
|
DWORD
|
|
IndexReadNameReplyBuffer(
|
|
LPNDS_BUFFER lpNdsBuffer );
|
|
|
|
DWORD
|
|
IndexSearchObjectReplyBuffer(
|
|
LPNDS_BUFFER lpNdsBuffer );
|
|
|
|
DWORD
|
|
SizeOfASN1Structure(
|
|
LPBYTE * lppRawBuffer,
|
|
DWORD dwSyntaxId );
|
|
|
|
DWORD
|
|
ParseASN1ValueBlob(
|
|
LPBYTE RawDataBuffer,
|
|
DWORD dwSyntaxId,
|
|
DWORD dwNumberOfValues,
|
|
LPBYTE SyntaxStructure );
|
|
|
|
DWORD
|
|
ParseStringListBlob(
|
|
LPBYTE RawDataBuffer,
|
|
DWORD dwNumberOfStrings,
|
|
LPBYTE SyntaxStructure );
|
|
|
|
DWORD
|
|
ReadAttrDef_AllAttrs(
|
|
IN HANDLE hTree,
|
|
IN DWORD dwInformationType,
|
|
OUT HANDLE lphOperationData );
|
|
|
|
DWORD
|
|
ReadAttrDef_SomeAttrs(
|
|
IN HANDLE hTree,
|
|
IN DWORD dwInformationType,
|
|
IN OUT HANDLE lphOperationData );
|
|
|
|
DWORD
|
|
ReadClassDef_AllClasses(
|
|
IN HANDLE hTree,
|
|
IN DWORD dwInformationType,
|
|
OUT HANDLE lphOperationData );
|
|
|
|
DWORD
|
|
ReadClassDef_SomeClasses(
|
|
IN HANDLE hTree,
|
|
IN DWORD dwInformationType,
|
|
IN OUT HANDLE lphOperationData );
|
|
|
|
DWORD
|
|
ReadObject_AllAttrs(
|
|
IN HANDLE hObject,
|
|
IN DWORD dwInformationType,
|
|
OUT HANDLE * lphOperationData );
|
|
|
|
DWORD
|
|
ReadObject_SomeAttrs(
|
|
IN HANDLE hObject,
|
|
IN DWORD dwInformationType,
|
|
IN OUT HANDLE * lphOperationData );
|
|
|
|
DWORD
|
|
Search_AllAttrs(
|
|
IN HANDLE hStartFromObject,
|
|
IN DWORD dwInformationType,
|
|
IN DWORD dwScope,
|
|
IN BOOL fDerefAliases,
|
|
IN LPQUERY_TREE lpQueryTree,
|
|
IN OUT LPDWORD lpdwIterHandle,
|
|
OUT HANDLE * lphOperationData );
|
|
|
|
DWORD
|
|
Search_SomeAttrs(
|
|
IN HANDLE hStartFromObject,
|
|
IN DWORD dwInformationType,
|
|
IN DWORD dwScope,
|
|
IN BOOL fDerefAliases,
|
|
IN LPQUERY_TREE lpQueryTree,
|
|
IN OUT LPDWORD lpdwIterHandle,
|
|
IN OUT HANDLE * lphOperationData );
|
|
|
|
DWORD
|
|
GetFirstNdsSubTreeEntry(
|
|
OUT LPNDS_OBJECT_PRIV lpNdsObject,
|
|
IN DWORD BufferSize );
|
|
|
|
DWORD
|
|
GetNextNdsSubTreeEntry(
|
|
OUT LPNDS_OBJECT_PRIV lpNdsObject );
|
|
|
|
VOID
|
|
GetSubTreeData(
|
|
IN DWORD NdsRawDataPtr,
|
|
OUT LPDWORD lpdwEntryId,
|
|
OUT LPDWORD lpdwSubordinateCount,
|
|
OUT LPDWORD lpdwModificationTime,
|
|
OUT LPDWORD lpdwClassNameLen,
|
|
OUT LPWSTR * szClassName,
|
|
OUT LPDWORD lpdwObjectNameLen,
|
|
OUT LPWSTR * szObjectName );
|
|
|
|
LPBYTE
|
|
GetSearchResultData( IN LPBYTE lpResultBufferPtr,
|
|
OUT LPDWORD lpdwFlags,
|
|
OUT LPDWORD lpdwSubordinateCount,
|
|
OUT LPDWORD lpdwModificationTime,
|
|
OUT LPDWORD lpdwClassNameLen,
|
|
OUT LPWSTR * szClassName,
|
|
OUT LPDWORD lpdwObjectNameLen,
|
|
OUT LPWSTR * szObjectName,
|
|
OUT LPDWORD lpdwEntryInfo1,
|
|
OUT LPDWORD lpdwEntryInfo2 );
|
|
|
|
DWORD
|
|
WriteObjectToBuffer(
|
|
IN OUT LPBYTE * FixedPortion,
|
|
IN OUT LPWSTR * EndOfVariableData,
|
|
IN LPWSTR ObjectFullName,
|
|
IN LPWSTR ObjectName,
|
|
IN LPWSTR ClassName,
|
|
IN DWORD EntryId,
|
|
IN DWORD ModificationTime,
|
|
IN DWORD SubordinateCount,
|
|
IN DWORD NumberOfAttributes,
|
|
IN LPNDS_ATTR_INFO lpAttributeInfos );
|
|
|
|
DWORD
|
|
VerifyBufferSize(
|
|
IN LPBYTE lpRawBuffer,
|
|
IN DWORD dwBufferSize,
|
|
IN DWORD dwSyntaxID,
|
|
IN DWORD dwNumberOfValues,
|
|
OUT LPDWORD lpdwLength );
|
|
|
|
DWORD
|
|
VerifyBufferSizeForStringList(
|
|
IN DWORD dwBufferSize,
|
|
IN DWORD dwNumberOfValues,
|
|
OUT LPDWORD lpdwLength );
|
|
|
|
DWORD
|
|
WriteQueryTreeToBuffer(
|
|
IN LPQUERY_TREE lpQueryTree,
|
|
IN LPNDS_BUFFER lpNdsBuffer );
|
|
|
|
DWORD
|
|
WriteQueryNodeToBuffer(
|
|
IN LPQUERY_NODE lpQueryNode,
|
|
IN LPNDS_BUFFER lpNdsBuffer );
|
|
|
|
DWORD
|
|
NwNdsGetServerDN(
|
|
IN HANDLE hTree,
|
|
OUT LPWSTR szServerDN );
|
|
|
|
DWORD
|
|
AllocateOrIncreaseSyntaxBuffer(
|
|
IN LPNDS_BUFFER lpNdsBuffer ,
|
|
IN DWORD dwLengthNeeded );
|
|
|
|
DWORD
|
|
AllocateOrIncreaseRequestBuffer(
|
|
IN LPNDS_BUFFER lpNdsBuffer );
|
|
|
|
|
|
//
|
|
// Flags used for the function ParseNdsUncPath()
|
|
//
|
|
#define PARSE_NDS_GET_TREE_NAME 0
|
|
#define PARSE_NDS_GET_PATH_NAME 1
|
|
#define PARSE_NDS_GET_OBJECT_NAME 2
|
|
|
|
|
|
WORD
|
|
ParseNdsUncPath( IN OUT LPWSTR * Result,
|
|
IN LPWSTR ObjectPathName,
|
|
IN DWORD flag );
|
|
|
|
|
|
/* Function Implementations */
|
|
|
|
DWORD
|
|
NwNdsAddObject(
|
|
IN HANDLE hParentObject,
|
|
IN LPWSTR szObjectName,
|
|
IN HANDLE hOperationData )
|
|
/*
|
|
NwNdsAddObject()
|
|
|
|
This function is used to add a leaf object to an NDS directory tree.
|
|
|
|
Arguments:
|
|
|
|
HANDLE hParentObject - A handle to the parent object in
|
|
the directory tree to add a new leaf to. Handle is
|
|
obtained by calling NwNdsOpenObject.
|
|
|
|
LPWSTR szObjectName - The directory name that the new leaf
|
|
object will be known by.
|
|
|
|
HANDLE hOperationData - A buffer containing a list of
|
|
attributes and values to create the new object. This
|
|
buffer is manipulated by the following functions:
|
|
NwNdsCreateBuffer (NDS_OBJECT_ADD),
|
|
NwNdsPutInBuffer, and NwNdsFreeBuffer.
|
|
|
|
Returns:
|
|
|
|
NO_ERROR
|
|
UNSUCCESSFUL - Call GetLastError for Win32 error code.
|
|
*/
|
|
{
|
|
DWORD nwstatus;
|
|
NTSTATUS ntstatus;
|
|
DWORD dwReplyLength;
|
|
BYTE NdsReply[NDS_BUFFER_SIZE];
|
|
LPNDS_BUFFER lpNdsBuffer = (LPNDS_BUFFER) hOperationData;
|
|
LPNDS_OBJECT_PRIV lpNdsParentObject = (LPNDS_OBJECT_PRIV) hParentObject;
|
|
UNICODE_STRING ObjectName;
|
|
|
|
if ( lpNdsBuffer == NULL ||
|
|
lpNdsParentObject == NULL ||
|
|
szObjectName == NULL ||
|
|
lpNdsBuffer->dwBufferId != NDS_SIGNATURE ||
|
|
lpNdsBuffer->dwOperation != NDS_OBJECT_ADD ||
|
|
lpNdsParentObject->Signature != NDS_SIGNATURE )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
RtlInitUnicodeString( &ObjectName, szObjectName );
|
|
|
|
ntstatus =
|
|
FragExWithWait(
|
|
lpNdsParentObject->NdsTree,
|
|
NETWARE_NDS_FUNCTION_ADD_OBJECT,
|
|
NdsReply,
|
|
NDS_BUFFER_SIZE,
|
|
&dwReplyLength,
|
|
"DDDSDr",
|
|
0, // Version
|
|
0, // Flags
|
|
lpNdsParentObject->ObjectId,
|
|
&ObjectName,
|
|
lpNdsBuffer->dwNumberOfRequestEntries,
|
|
lpNdsBuffer->lpRequestBuffer, // Object attributes to be added
|
|
(WORD)lpNdsBuffer->dwLengthOfRequestData // Length of data
|
|
);
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsAddObject: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
ntstatus = ParseResponse( NdsReply,
|
|
dwReplyLength,
|
|
"GD",
|
|
&nwstatus );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsAddObject: The add name response was undecipherable.\n" ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
SetLastError( MapNetwareErrorCode( nwstatus ) );
|
|
return nwstatus;
|
|
}
|
|
|
|
|
|
DWORD
|
|
NwNdsAddAttributeToClass(
|
|
IN HANDLE hTree,
|
|
IN LPWSTR szClassName,
|
|
IN LPWSTR szAttributeName )
|
|
/*
|
|
NwNdsAddAttributeToClass()
|
|
|
|
This function is used to modify the schema definition of a class by adding
|
|
an optional attribute to a particular class. Modification of existing NDS
|
|
class defintions is limited to only adding additional optional attributes.
|
|
|
|
Arguments:
|
|
|
|
HANDLE hTree - A handle to the directory tree to be
|
|
manipulated. Handle is obtained by calling
|
|
NwNdsOpenObject.
|
|
|
|
LPWSTR szClassName - The name of the class definition to be
|
|
modified.
|
|
|
|
LPWSTR szAttributeName - The name of the attribute to be added
|
|
as an optional attribute to the class defintion in the
|
|
schema.
|
|
|
|
Returns:
|
|
|
|
NO_ERROR
|
|
UNSUCCESSFUL - Call GetLastError for Win32 error code.
|
|
*/
|
|
{
|
|
DWORD nwstatus;
|
|
DWORD status = NO_ERROR;
|
|
NTSTATUS ntstatus = STATUS_SUCCESS;
|
|
DWORD dwReplyLength;
|
|
BYTE NdsReply[NDS_BUFFER_SIZE];
|
|
LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hTree;
|
|
UNICODE_STRING ClassName;
|
|
UNICODE_STRING AttributeName;
|
|
|
|
if ( szAttributeName == NULL ||
|
|
szClassName == NULL ||
|
|
lpNdsObject == NULL ||
|
|
lpNdsObject->Signature != NDS_SIGNATURE )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
RtlInitUnicodeString( &ClassName, szClassName );
|
|
RtlInitUnicodeString( &AttributeName, szAttributeName );
|
|
|
|
ntstatus =
|
|
FragExWithWait(
|
|
lpNdsObject->NdsTree,
|
|
NETWARE_NDS_FUNCTION_MODIFY_CLASS,
|
|
NdsReply,
|
|
NDS_BUFFER_SIZE,
|
|
&dwReplyLength,
|
|
"DSDS",
|
|
0, // Version
|
|
&ClassName,
|
|
1, // Number of attributes
|
|
&AttributeName
|
|
);
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsAddAttributeToClass: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
ntstatus = ParseResponse( NdsReply,
|
|
dwReplyLength,
|
|
"GD",
|
|
&nwstatus );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsAddAttributeToClass: The modify class definition response was undecipherable.\n" ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
SetLastError( MapNetwareErrorCode( nwstatus ) );
|
|
return nwstatus;
|
|
}
|
|
|
|
|
|
DWORD
|
|
NwNdsChangeUserPassword(
|
|
IN HANDLE hUserObject,
|
|
IN LPWSTR szOldPassword,
|
|
IN LPWSTR szNewPassword )
|
|
/*
|
|
NwNdsChangeUserPassword()
|
|
|
|
This function is used to change the password for a given user object
|
|
in a NDS directory tree.
|
|
|
|
Arguments:
|
|
|
|
HANDLE hUserObject - A handle to a specific user object in
|
|
the directory tree to change the password on. Handle
|
|
is obtained by calling NwNdsOpenObject.
|
|
|
|
LPWSTR szOldPassword - The current password set on the user
|
|
object hUserObject.
|
|
|
|
- OR -
|
|
|
|
If NwNdsChangeUserPassword is called from a client with
|
|
administrative priveleges to the specified user object
|
|
identified by hUserObject, then the szOldPassword
|
|
value can be blank (L""). This way resetting the user
|
|
password to szNewPassword.
|
|
|
|
LPWSTR szNewPassword - The new password to be set on the user
|
|
object hUserObject.
|
|
|
|
Returns:
|
|
|
|
NO_ERROR
|
|
UNSUCCESSFUL - Call GetLastError for Win32 error code.
|
|
*/
|
|
{
|
|
DWORD status = NO_ERROR;
|
|
NTSTATUS ntstatus = STATUS_UNSUCCESSFUL;
|
|
UNICODE_STRING TreeNameStr;
|
|
UNICODE_STRING UserNameStr;
|
|
UNICODE_STRING OldPasswordStr;
|
|
UNICODE_STRING NewPasswordStr;
|
|
LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hUserObject;
|
|
DWORD tempStrLen = 0;
|
|
LPWSTR tempStr = NULL;
|
|
|
|
tempStrLen = ParseNdsUncPath( (LPWSTR *) &tempStr,
|
|
lpNdsObject->szContainerName,
|
|
PARSE_NDS_GET_TREE_NAME );
|
|
|
|
TreeNameStr.Buffer = tempStr;
|
|
TreeNameStr.Length = (WORD) tempStrLen;
|
|
TreeNameStr.MaximumLength = (WORD) tempStrLen;
|
|
|
|
tempStrLen = ParseNdsUncPath( (LPWSTR *) &tempStr,
|
|
lpNdsObject->szContainerName,
|
|
PARSE_NDS_GET_PATH_NAME );
|
|
|
|
#ifndef WIN95
|
|
UserNameStr.Buffer = tempStr;
|
|
UserNameStr.Length = (WORD) tempStrLen;
|
|
UserNameStr.MaximumLength = (WORD) tempStrLen;
|
|
|
|
RtlInitUnicodeString( &OldPasswordStr, szOldPassword );
|
|
RtlInitUnicodeString( &NewPasswordStr, szNewPassword );
|
|
|
|
ntstatus = NwNdsChangePassword( lpNdsObject->NdsTree,
|
|
&TreeNameStr,
|
|
&UserNameStr,
|
|
&OldPasswordStr,
|
|
&NewPasswordStr );
|
|
#else
|
|
{
|
|
LPSTR pszUser = NULL;
|
|
LPSTR pszOldPasswd = NULL;
|
|
LPSTR pszNewPasswd = NULL;
|
|
NW_STATUS nwstatus;
|
|
if (!(pszUser = AllocateAnsiString(tempStr))) {
|
|
ntstatus = STATUS_NO_MEMORY;
|
|
goto Exit;
|
|
}
|
|
if (!(pszOldPasswd = AllocateAnsiString(szOldPassword))) {
|
|
ntstatus = STATUS_NO_MEMORY;
|
|
goto Exit;
|
|
}
|
|
if (!(pszNewPasswd= AllocateAnsiString(szNewPassword))) {
|
|
ntstatus = STATUS_NO_MEMORY;
|
|
goto Exit;
|
|
}
|
|
|
|
nwstatus = NDSChangePassword( pszUser,
|
|
pszOldPasswd,
|
|
pszNewPasswd );
|
|
ntstatus = MapNwToNtStatus(nwstatus);
|
|
Exit:
|
|
if (pszUser)
|
|
FreeAnsiString(pszUser);
|
|
if (pszOldPasswd)
|
|
FreeAnsiString(pszOldPasswd);
|
|
if (pszNewPasswd)
|
|
FreeAnsiString(pszNewPasswd);
|
|
}
|
|
#endif
|
|
|
|
if ( ntstatus != STATUS_SUCCESS )
|
|
{
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
DWORD
|
|
NwNdsCloseObject(
|
|
IN HANDLE hObject )
|
|
/*
|
|
NwNdsCloseObject()
|
|
|
|
This function is used to close the handle used to manipulate an object
|
|
in an NDS directory tree. The handle must be one Opened by NwNdsOpenObject.
|
|
|
|
Arguments:
|
|
|
|
HANDLE lphObject - The handle of the object to be closed.
|
|
|
|
Returns:
|
|
|
|
NO_ERROR
|
|
UNSUCCESSFUL - Call GetLastError for Win32 error code.
|
|
*/
|
|
{
|
|
LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hObject;
|
|
|
|
if ( lpNdsObject->Signature != NDS_SIGNATURE )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
if ( lpNdsObject )
|
|
{
|
|
if ( lpNdsObject->NdsTree )
|
|
CloseHandle( lpNdsObject->NdsTree );
|
|
|
|
if ( lpNdsObject->NdsRawDataBuffer )
|
|
{
|
|
(void) LocalFree( (HLOCAL) lpNdsObject->NdsRawDataBuffer );
|
|
lpNdsObject->NdsRawDataBuffer = 0;
|
|
lpNdsObject->NdsRawDataSize = 0;
|
|
lpNdsObject->NdsRawDataId = INITIAL_ITERATION;
|
|
lpNdsObject->NdsRawDataCount = 0;
|
|
}
|
|
|
|
(void) LocalFree( (HLOCAL) lpNdsObject );
|
|
}
|
|
else
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
DWORD
|
|
NwNdsCreateBuffer(
|
|
IN DWORD dwOperation,
|
|
OUT HANDLE * lphOperationData )
|
|
/*
|
|
NwNdsCreateBuffer()
|
|
|
|
This function is used to create a buffer used to describe object
|
|
transactions to a specific object in an NDS directory tree. This routine
|
|
allocates memory and is automatically resized as needed during calls
|
|
to NwNdsPutInBuffer. This buffer must be freed with NwNdsFreeBuffer.
|
|
|
|
Arguments:
|
|
|
|
DWORD dwOperation - Indicates how buffer is to be utilized.
|
|
Use defined values NDS_OBJECT_ADD, NDS_OBJECT_MODIFY,
|
|
NDS_OBJECT_READ, NDS_SCHEMA_DEFINE_CLASS,
|
|
NDS_SCHEMA_READ_ATTR_DEF, NDS_SCHEMA_READ_CLASS_DEF,
|
|
NDS_OBJECT_LIST_SUBORDINATES, NDS_SEARCH.
|
|
|
|
HANDLE * lphOperationData - Address of a HANDLE handle to
|
|
receive created buffer.
|
|
|
|
Returns:
|
|
|
|
NO_ERROR
|
|
UNSUCCESSFUL - Call GetLastError for Win32 error code.
|
|
*/
|
|
{
|
|
LPNDS_BUFFER lpNdsBuffer = NULL;
|
|
DWORD dwSizeOfBuffer = TWO_KB; // Initial size, grow as needed.
|
|
|
|
switch( dwOperation )
|
|
{
|
|
case NDS_OBJECT_ADD:
|
|
case NDS_OBJECT_MODIFY:
|
|
case NDS_OBJECT_READ:
|
|
case NDS_SCHEMA_DEFINE_CLASS:
|
|
case NDS_SCHEMA_READ_ATTR_DEF:
|
|
case NDS_SCHEMA_READ_CLASS_DEF:
|
|
case NDS_OBJECT_LIST_SUBORDINATES:
|
|
case NDS_SEARCH:
|
|
break;
|
|
|
|
default:
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsCreateBuffer parameter dwOperation unknown 0x%.8X\n", dwOperation ));
|
|
ASSERT( FALSE );
|
|
#endif
|
|
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// Allocate memory for the buffer.
|
|
//
|
|
lpNdsBuffer =
|
|
(LPNDS_BUFFER) LocalAlloc( LPTR, sizeof(NDS_BUFFER) );
|
|
|
|
if ( lpNdsBuffer == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsCreateBuffer LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// Initialize the contents of the header structure.
|
|
//
|
|
lpNdsBuffer->dwBufferId = NDS_SIGNATURE;
|
|
lpNdsBuffer->dwOperation = dwOperation;
|
|
|
|
if ( dwOperation == NDS_OBJECT_LIST_SUBORDINATES )
|
|
{
|
|
lpNdsBuffer->dwIndexBufferSize = dwSizeOfBuffer;
|
|
lpNdsBuffer->dwIndexAvailableBytes = dwSizeOfBuffer;
|
|
}
|
|
else
|
|
{
|
|
lpNdsBuffer->dwRequestBufferSize = dwSizeOfBuffer;
|
|
lpNdsBuffer->dwRequestAvailableBytes = dwSizeOfBuffer;
|
|
}
|
|
|
|
//
|
|
// NOTE: The following are set to zero by LPTR
|
|
//
|
|
// lpNdsBuffer->dwNumberOfRequestEntries = 0;
|
|
// lpNdsBuffer->dwLengthOfRequestData = 0;
|
|
|
|
// lpNdsBuffer->dwReplyBufferSize = 0;
|
|
// lpNdsBuffer->dwReplyAvailableBytes = 0;
|
|
// lpNdsBuffer->dwNumberOfReplyEntries = 0;
|
|
// lpNdsBuffer->dwLengthOfReplyData = 0;
|
|
|
|
// lpNdsBuffer->dwReplyInformationType = 0;
|
|
|
|
// lpNdsBuffer->lpReplyBuffer = NULL;
|
|
|
|
// lpNdsBuffer->dwNumberOfIndexEntries = 0;
|
|
// lpNdsBuffer->dwLengthOfIndexData = 0;
|
|
// lpNdsBuffer->dwCurrentIndexEntry = 0;
|
|
|
|
// lpNdsBuffer->dwSyntaxBufferSize = 0;
|
|
// lpNdsBuffer->dwSyntaxAvailableBytes = 0;
|
|
// lpNdsBuffer->dwNumberOfSyntaxEntries = 0;
|
|
// lpNdsBuffer->dwLengthOfSyntaxData = 0;
|
|
|
|
// lpNdsBuffer->lpSyntaxBuffer = NULL;
|
|
|
|
//
|
|
// Now allocate the data buffer.
|
|
//
|
|
if ( dwOperation == NDS_OBJECT_LIST_SUBORDINATES )
|
|
{
|
|
lpNdsBuffer->lpIndexBuffer =
|
|
(LPBYTE) LocalAlloc( LPTR, dwSizeOfBuffer );
|
|
|
|
if ( lpNdsBuffer->lpIndexBuffer == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsCreateBuffer LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
(void) LocalFree((HLOCAL) lpNdsBuffer);
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lpNdsBuffer->lpRequestBuffer =
|
|
(LPBYTE) LocalAlloc( LPTR, dwSizeOfBuffer );
|
|
|
|
if ( lpNdsBuffer->lpRequestBuffer == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsCreateBuffer LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
(void) LocalFree((HLOCAL) lpNdsBuffer);
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
}
|
|
|
|
*lphOperationData = (HANDLE) lpNdsBuffer;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
DWORD
|
|
NwNdsCreateQueryNode(
|
|
IN DWORD dwOperation,
|
|
IN LPVOID lpLValue,
|
|
IN DWORD dwSyntaxId,
|
|
IN LPVOID lpRValue,
|
|
OUT LPQUERY_NODE * lppQueryNode
|
|
)
|
|
/*
|
|
NwNdsCreateQueryNode()
|
|
|
|
This function is used to generate a tree node that is part of a query
|
|
to be used with the function NwNdsSearch.
|
|
|
|
Arguments:
|
|
|
|
DWORD dwOperation - Indicates the type of node to create
|
|
for a search query. Use one of the defined values
|
|
below:
|
|
|
|
NDS_QUERY_OR
|
|
NDS_QUERY_AND :
|
|
These operations must have both lpLValue and
|
|
lpRValue pointing to a QUERY_NODE structure.
|
|
In this case the dwSyntaxId value is ignored.
|
|
|
|
NDS_QUERY_NOT :
|
|
This operation must have lpLValue pointing to a
|
|
QUERY_NODE structure and lpRValue set to NULL.
|
|
In this case the dwSyntaxId value is ignored.
|
|
|
|
NDS_QUERY_EQUAL
|
|
NDS_QUERY_GE
|
|
NDS_QUERY_LE
|
|
NDS_QUERY_APPROX :
|
|
These operations must have lpLValue pointing to
|
|
a LPWSTR containing the name of an NDS attribute,
|
|
and lpRValue pointing to an ASN1 structure defined
|
|
in NdsSntx.h. dwSyntaxId must be set to the syntax
|
|
identifier of the ASN1 structure pointed to by
|
|
lpRValue.
|
|
|
|
NDS_QUERY_PRESENT :
|
|
This operation must have lpLValue pointing to a
|
|
LPWSTR containing the name of an NDS attribute,
|
|
and lpRValue set to NULL. In this case the
|
|
dwSyntaxId value is ignored.
|
|
|
|
LPVOID lpLValue - A pointer to either a QUERY_NODE structure
|
|
or a LPWSTR depending on the value for dwOperation.
|
|
|
|
DWORD dwSyntaxId - The syntax identifier of the ASN1
|
|
structure pointed to by lpRValue for the dwOperations
|
|
NDS_QUERY_EQUAL, NDS_QUERY_GE, NDS_QUERY_LE, or
|
|
NDS_QUERY_APPROX. For other dwOperation values, this
|
|
is ignored.
|
|
|
|
LPVOID lpRValue - A pointer to either a QUERY_NODE structure,
|
|
an ASN1 structure, or NULL, depending on the value for
|
|
dwOperation.
|
|
|
|
LPQUERY_NODE * lppQueryNode - Address of a LPQUERY_NODE to receive
|
|
a pointer to created node.
|
|
|
|
Returns:
|
|
|
|
NO_ERROR
|
|
UNSUCCESSFUL - Call GetLastError for Win32 error code.
|
|
*/
|
|
{
|
|
LPWSTR szAttributeName;
|
|
DWORD dwAttributeNameLen;
|
|
LPWSTR szRValueString;
|
|
DWORD dwRValueStringLen;
|
|
|
|
switch( dwOperation )
|
|
{
|
|
case NDS_QUERY_OR :
|
|
case NDS_QUERY_AND :
|
|
|
|
if ( lpLValue == NULL || lpRValue == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsCreateQueryNode was not passed a pointer to an L or R value.\n" ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
*lppQueryNode = (LPQUERY_NODE) LocalAlloc( LPTR,
|
|
sizeof(QUERY_NODE) );
|
|
|
|
if ( *lppQueryNode == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsCreateQueryNode LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
(*lppQueryNode)->dwOperation = dwOperation;
|
|
(*lppQueryNode)->dwSyntaxId = NDS_NO_MORE_ITERATIONS;
|
|
(*lppQueryNode)->lpLVal = lpLValue;
|
|
(*lppQueryNode)->lpRVal = lpRValue;
|
|
|
|
break;
|
|
|
|
case NDS_QUERY_NOT :
|
|
|
|
if ( lpLValue == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsCreateQueryNode was not passed a pointer to an L value.\n" ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
*lppQueryNode = (LPQUERY_NODE) LocalAlloc( LPTR,
|
|
sizeof(QUERY_NODE) );
|
|
|
|
if ( *lppQueryNode == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsCreateQueryNode LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
(*lppQueryNode)->dwOperation = dwOperation;
|
|
(*lppQueryNode)->dwSyntaxId = NDS_NO_MORE_ITERATIONS;
|
|
(*lppQueryNode)->lpLVal = lpLValue;
|
|
(*lppQueryNode)->lpRVal = NULL;
|
|
|
|
break;
|
|
|
|
case NDS_QUERY_EQUAL :
|
|
case NDS_QUERY_GE :
|
|
case NDS_QUERY_LE :
|
|
case NDS_QUERY_APPROX :
|
|
|
|
switch( dwSyntaxId )
|
|
{
|
|
case NDS_SYNTAX_ID_1 :
|
|
case NDS_SYNTAX_ID_2 :
|
|
case NDS_SYNTAX_ID_3 :
|
|
case NDS_SYNTAX_ID_4 :
|
|
case NDS_SYNTAX_ID_5 :
|
|
case NDS_SYNTAX_ID_10 :
|
|
case NDS_SYNTAX_ID_20 :
|
|
//
|
|
// This syntax is in the form of a LPWSTR.
|
|
//
|
|
szAttributeName = (LPWSTR) lpLValue;
|
|
dwAttributeNameLen = ROUND_UP_COUNT(
|
|
( wcslen( szAttributeName ) + 1 ) *
|
|
sizeof(WCHAR),
|
|
ALIGN_DWORD );
|
|
szRValueString = ((LPASN1_TYPE_1) lpRValue)->DNString;
|
|
dwRValueStringLen = ROUND_UP_COUNT(
|
|
( wcslen( szRValueString ) + 1 ) *
|
|
sizeof(WCHAR),
|
|
ALIGN_DWORD );
|
|
|
|
*lppQueryNode = (LPQUERY_NODE)
|
|
LocalAlloc( LPTR,
|
|
sizeof(QUERY_NODE) +
|
|
dwAttributeNameLen +
|
|
dwRValueStringLen );
|
|
|
|
if ( *lppQueryNode == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsCreateQueryNode LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
(*lppQueryNode)->dwOperation = dwOperation;
|
|
(*lppQueryNode)->dwSyntaxId = dwSyntaxId;
|
|
(*lppQueryNode)->lpLVal = *lppQueryNode;
|
|
(LPBYTE) (*lppQueryNode)->lpLVal += sizeof(QUERY_NODE);
|
|
wcscpy( (LPWSTR) (*lppQueryNode)->lpLVal, szAttributeName );
|
|
(*lppQueryNode)->lpRVal = (*lppQueryNode)->lpLVal;
|
|
(LPBYTE) (*lppQueryNode)->lpRVal += dwAttributeNameLen;
|
|
wcscpy( (LPWSTR) (*lppQueryNode)->lpRVal, szRValueString );
|
|
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_7 :
|
|
case NDS_SYNTAX_ID_8 :
|
|
case NDS_SYNTAX_ID_22 :
|
|
case NDS_SYNTAX_ID_24 :
|
|
case NDS_SYNTAX_ID_27 :
|
|
//
|
|
// This syntax is in the form of a DWORD.
|
|
//
|
|
|
|
szAttributeName = (LPWSTR) lpLValue;
|
|
dwAttributeNameLen = ROUND_UP_COUNT(
|
|
( wcslen( szAttributeName ) + 1 ) *
|
|
sizeof(WCHAR),
|
|
ALIGN_DWORD );
|
|
|
|
*lppQueryNode = (LPQUERY_NODE)
|
|
LocalAlloc( LPTR,
|
|
sizeof(QUERY_NODE) +
|
|
dwAttributeNameLen +
|
|
sizeof(ASN1_TYPE_8) );
|
|
|
|
if ( *lppQueryNode == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsCreateQueryNode LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
(*lppQueryNode)->dwOperation = dwOperation;
|
|
(*lppQueryNode)->dwSyntaxId = dwSyntaxId;
|
|
(*lppQueryNode)->lpLVal = *lppQueryNode;
|
|
(LPBYTE) (*lppQueryNode)->lpLVal += sizeof(QUERY_NODE);
|
|
wcscpy( (LPWSTR) (*lppQueryNode)->lpLVal,
|
|
szAttributeName );
|
|
(*lppQueryNode)->lpRVal = (LPQUERY_NODE)((LPBYTE)((*lppQueryNode)->lpLVal) +
|
|
dwAttributeNameLen);
|
|
((LPASN1_TYPE_8)(*lppQueryNode)->lpRVal)->Integer =
|
|
((LPASN1_TYPE_8)lpRValue)->Integer;
|
|
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_9 :
|
|
//
|
|
// This syntax is in the form of an Octet String.
|
|
//
|
|
szAttributeName = (LPWSTR) lpLValue;
|
|
dwAttributeNameLen = ROUND_UP_COUNT(
|
|
( wcslen( szAttributeName ) + 1 ) *
|
|
sizeof(WCHAR),
|
|
ALIGN_DWORD );
|
|
|
|
*lppQueryNode = (LPQUERY_NODE)
|
|
LocalAlloc( LPTR,
|
|
sizeof(QUERY_NODE) +
|
|
dwAttributeNameLen +
|
|
sizeof( DWORD ) +
|
|
((LPASN1_TYPE_9) lpRValue)->Length + 1 );
|
|
|
|
if ( *lppQueryNode == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsCreateQueryNode LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
(*lppQueryNode)->dwOperation = dwOperation;
|
|
(*lppQueryNode)->dwSyntaxId = dwSyntaxId;
|
|
(*lppQueryNode)->lpLVal = *lppQueryNode;
|
|
(LPBYTE) (*lppQueryNode)->lpLVal += sizeof(QUERY_NODE);
|
|
wcscpy( (LPWSTR) (*lppQueryNode)->lpLVal, szAttributeName );
|
|
(*lppQueryNode)->lpRVal = (*lppQueryNode)->lpLVal;
|
|
(LPBYTE) (*lppQueryNode)->lpRVal += dwAttributeNameLen;
|
|
*((LPDWORD) (*lppQueryNode)->lpRVal) =
|
|
((LPASN1_TYPE_9) lpRValue)->Length;
|
|
(LPBYTE) (*lppQueryNode)->lpRVal += sizeof( DWORD );
|
|
memcpy( (*lppQueryNode)->lpRVal,
|
|
((LPASN1_TYPE_9) lpRValue)->OctetString,
|
|
((LPASN1_TYPE_9) lpRValue)->Length );
|
|
(LPBYTE) (*lppQueryNode)->lpRVal -= sizeof( DWORD );
|
|
|
|
break;
|
|
|
|
default :
|
|
SetLastError( ERROR_NOT_SUPPORTED );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
break;
|
|
|
|
case NDS_QUERY_PRESENT :
|
|
|
|
if ( lpLValue == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsCreateQueryNode was not passed a pointer to an L value.\n" ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
szAttributeName = (LPWSTR) lpLValue;
|
|
dwAttributeNameLen = ( wcslen( szAttributeName ) + 1 ) *
|
|
sizeof(WCHAR);
|
|
|
|
*lppQueryNode = (LPQUERY_NODE) LocalAlloc( LPTR,
|
|
sizeof(QUERY_NODE) +
|
|
dwAttributeNameLen );
|
|
|
|
if ( *lppQueryNode == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsCreateQueryNode LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
(*lppQueryNode)->dwOperation = dwOperation;
|
|
(*lppQueryNode)->dwSyntaxId = NDS_NO_MORE_ITERATIONS;
|
|
(*lppQueryNode)->lpLVal = (*lppQueryNode);
|
|
(LPBYTE) (*lppQueryNode)->lpLVal += sizeof(QUERY_NODE);
|
|
wcscpy( (LPWSTR) (*lppQueryNode)->lpLVal, szAttributeName );
|
|
(*lppQueryNode)->lpRVal = NULL;
|
|
|
|
break;
|
|
|
|
default :
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsCreateQueryNode was passed an unidentified operation - 0x%.8X.\n", dwOperation ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
DWORD
|
|
NwNdsDefineAttribute(
|
|
IN HANDLE hTree,
|
|
IN LPWSTR szAttributeName,
|
|
IN DWORD dwFlags,
|
|
IN DWORD dwSyntaxID,
|
|
IN DWORD dwLowerLimit,
|
|
IN DWORD dwUpperLimit,
|
|
IN ASN1_ID asn1ID )
|
|
/*
|
|
NwNdsDefineAttribute()
|
|
|
|
This function is used to create an attribute definition in the schema of
|
|
NDS tree hTree.
|
|
|
|
Arguments:
|
|
|
|
HANDLE hTree - A handle to the directory tree to be
|
|
manipulated. Handle is obtained by calling
|
|
NwNdsOpenObject.
|
|
|
|
LPWSTR szAttributeName - The name that the new attribute will
|
|
be referred to by.
|
|
|
|
DWORD dwFlags - Flags values to be set for new attribute
|
|
definition. Definitions for flag values are found at
|
|
the top of the file Nds32.h.
|
|
|
|
DWORD dwSyntaxID - The ID of the syntax structure to be use
|
|
for the new attribute. Syntax IDs and their associated
|
|
structures are defined in the file NdsSntx.h. According
|
|
to the NetWare NDS schema spec, there is and always will
|
|
be, only 28 (0..27) different syntaxes.
|
|
|
|
DWORD dwLowerLimit - The lower limit of a sized attribute
|
|
(dwFlags value set to NDS_SIZED_ATTR). Can be set to
|
|
zero if attribute is not sized.
|
|
|
|
DWORD dwUpperLimit - The upper limit of a sized attribute
|
|
(dwFlags value set to NDS_SIZED_ATTR). Can be set to
|
|
zero if attribute is not sized.
|
|
|
|
ASN1_ID asn1ID - The ASN.1 ID for the attribute. If no
|
|
attribute identifier has been registered, a
|
|
zero-length octet string is specified.
|
|
|
|
Returns:
|
|
|
|
NO_ERROR
|
|
UNSUCCESSFUL - Call GetLastError for Win32 error code.
|
|
*/
|
|
{
|
|
DWORD nwstatus;
|
|
DWORD status = NO_ERROR;
|
|
NTSTATUS ntstatus = STATUS_SUCCESS;
|
|
DWORD dwReplyLength;
|
|
BYTE NdsReply[NDS_BUFFER_SIZE];
|
|
LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hTree;
|
|
UNICODE_STRING AttributeName;
|
|
|
|
if ( szAttributeName == NULL ||
|
|
lpNdsObject == NULL ||
|
|
lpNdsObject->Signature != NDS_SIGNATURE )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
RtlInitUnicodeString( &AttributeName, szAttributeName );
|
|
|
|
ntstatus =
|
|
FragExWithWait(
|
|
lpNdsObject->NdsTree,
|
|
NETWARE_NDS_FUNCTION_DEFINE_ATTR,
|
|
NdsReply,
|
|
NDS_BUFFER_SIZE,
|
|
&dwReplyLength,
|
|
"DDSDDDD",
|
|
0, // Version
|
|
dwFlags,
|
|
&AttributeName,
|
|
dwSyntaxID,
|
|
dwLowerLimit,
|
|
dwUpperLimit,
|
|
0 // ASN1 Id
|
|
);
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsDefineAttribute: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
ntstatus = ParseResponse( NdsReply,
|
|
dwReplyLength,
|
|
"GD",
|
|
&nwstatus );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsDefineAttribute: The define attribute response was undecipherable.\n" ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
SetLastError( MapNetwareErrorCode( nwstatus ) );
|
|
return nwstatus;
|
|
}
|
|
|
|
|
|
DWORD
|
|
NwNdsDefineClass(
|
|
IN HANDLE hTree,
|
|
IN LPWSTR szClassName,
|
|
IN DWORD dwFlags,
|
|
IN ASN1_ID asn1ID,
|
|
IN HANDLE hSuperClasses,
|
|
IN HANDLE hContainmentClasses,
|
|
IN HANDLE hNamingAttributes,
|
|
IN HANDLE hMandatoryAttributes,
|
|
IN HANDLE hOptionalAttributes )
|
|
/*
|
|
NwNdsDefineClass()
|
|
|
|
This function is used to create a class definition in the schema of
|
|
NDS tree hTree.
|
|
|
|
Arguments:
|
|
|
|
HANDLE hTree - A handle to the directory tree to be
|
|
manipulated. Handle is obtained by calling
|
|
NwNdsOpenObject.
|
|
|
|
LPWSTR szClassName - The name that the new class will
|
|
be referred to by.
|
|
|
|
DWORD dwFlags - Flags values to be set for new class
|
|
definition. Definitions for flag values are found at
|
|
the top of the file Nds32.h.
|
|
|
|
ASN1_ID asn1ID - The ASN.1 ID for the class. If no
|
|
class identifier has been registered, a
|
|
zero-length octet string is specified.
|
|
|
|
HANDLE(S) hSuperClasses,
|
|
hContainmentClasses,
|
|
hNamingAttributes,
|
|
hMandatoryAttributes,
|
|
hOptionalAttributes -
|
|
|
|
Handle to buffers that contain class definition
|
|
information to create new class in schema.
|
|
These handles are manipulated by the following
|
|
functions:
|
|
NwNdsCreateBuffer (NDS_SCHEMA_DEFINE_CLASS),
|
|
NwNdsPutInBuffer, and NwNdsFreeBuffer.
|
|
|
|
- OR -
|
|
|
|
Handles can be NULL to indicate that no list
|
|
is associated with the specific class defintion
|
|
item.
|
|
|
|
Returns:
|
|
|
|
NO_ERROR
|
|
UNSUCCESSFUL - Call GetLastError for Win32 error code.
|
|
*/
|
|
{
|
|
DWORD nwstatus;
|
|
DWORD status = NO_ERROR;
|
|
NTSTATUS ntstatus = STATUS_SUCCESS;
|
|
DWORD dwReplyLength;
|
|
BYTE NdsReply[NDS_BUFFER_SIZE];
|
|
LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hTree;
|
|
UNICODE_STRING ClassName;
|
|
LPNDS_BUFFER lpSuperClasses = (LPNDS_BUFFER) hSuperClasses;
|
|
LPNDS_BUFFER lpContainmentClasses = (LPNDS_BUFFER) hContainmentClasses;
|
|
LPNDS_BUFFER lpNamingAttributes = (LPNDS_BUFFER) hNamingAttributes;
|
|
LPNDS_BUFFER lpMandatoryAttributes = (LPNDS_BUFFER) hMandatoryAttributes;
|
|
LPNDS_BUFFER lpOptionalAttributes = (LPNDS_BUFFER) hOptionalAttributes;
|
|
|
|
DWORD NumberOfSuperClasses = 0;
|
|
DWORD NumberOfContainmentClasses = 0;
|
|
DWORD NumberOfNamingAttributes = 0;
|
|
DWORD NumberOfMandatoryAttributes = 0;
|
|
DWORD NumberOfOptionalAttributes = 0;
|
|
|
|
WORD SuperClassesBufferLength = 0;
|
|
WORD ContainmentClassesBufferLength = 0;
|
|
WORD NamingAttributesBufferLength = 0;
|
|
WORD MandatoryAttributesBufferLength = 0;
|
|
WORD OptionalAttributesBufferLength = 0;
|
|
|
|
LPBYTE SuperClassesBuffer = NULL;
|
|
LPBYTE ContainmentClassesBuffer = NULL;
|
|
LPBYTE NamingAttributesBuffer = NULL;
|
|
LPBYTE MandatoryAttributesBuffer = NULL;
|
|
LPBYTE OptionalAttributesBuffer = NULL;
|
|
|
|
if ( szClassName == NULL ||
|
|
lpNdsObject == NULL ||
|
|
lpNdsObject->Signature != NDS_SIGNATURE )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
if ( lpSuperClasses )
|
|
{
|
|
if ( lpSuperClasses->dwBufferId != NDS_SIGNATURE ||
|
|
lpSuperClasses->dwOperation != NDS_SCHEMA_DEFINE_CLASS )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
NumberOfSuperClasses = lpSuperClasses->dwNumberOfRequestEntries,
|
|
SuperClassesBuffer = lpSuperClasses->lpRequestBuffer,
|
|
SuperClassesBufferLength = (WORD)lpSuperClasses->dwLengthOfRequestData;
|
|
}
|
|
|
|
if ( lpContainmentClasses )
|
|
{
|
|
if ( lpContainmentClasses->dwBufferId != NDS_SIGNATURE ||
|
|
lpContainmentClasses->dwOperation != NDS_SCHEMA_DEFINE_CLASS )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
NumberOfContainmentClasses =
|
|
lpContainmentClasses->dwNumberOfRequestEntries,
|
|
ContainmentClassesBuffer =
|
|
lpContainmentClasses->lpRequestBuffer,
|
|
ContainmentClassesBufferLength =
|
|
(WORD)lpContainmentClasses->dwLengthOfRequestData;
|
|
}
|
|
|
|
if ( lpNamingAttributes )
|
|
{
|
|
if ( lpNamingAttributes->dwBufferId != NDS_SIGNATURE ||
|
|
lpNamingAttributes->dwOperation != NDS_SCHEMA_DEFINE_CLASS )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
NumberOfNamingAttributes =
|
|
lpNamingAttributes->dwNumberOfRequestEntries,
|
|
NamingAttributesBuffer =
|
|
lpNamingAttributes->lpRequestBuffer,
|
|
NamingAttributesBufferLength =
|
|
(WORD)lpNamingAttributes->dwLengthOfRequestData;
|
|
}
|
|
|
|
if ( lpMandatoryAttributes )
|
|
{
|
|
if ( lpMandatoryAttributes->dwBufferId != NDS_SIGNATURE ||
|
|
lpMandatoryAttributes->dwOperation != NDS_SCHEMA_DEFINE_CLASS )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
NumberOfMandatoryAttributes =
|
|
lpMandatoryAttributes->dwNumberOfRequestEntries,
|
|
MandatoryAttributesBuffer =
|
|
lpMandatoryAttributes->lpRequestBuffer,
|
|
MandatoryAttributesBufferLength =
|
|
(WORD)lpMandatoryAttributes->dwLengthOfRequestData;
|
|
}
|
|
|
|
if ( lpOptionalAttributes )
|
|
{
|
|
if ( lpOptionalAttributes->dwBufferId != NDS_SIGNATURE ||
|
|
lpOptionalAttributes->dwOperation != NDS_SCHEMA_DEFINE_CLASS )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
NumberOfOptionalAttributes =
|
|
lpOptionalAttributes->dwNumberOfRequestEntries,
|
|
OptionalAttributesBuffer =
|
|
lpOptionalAttributes->lpRequestBuffer,
|
|
OptionalAttributesBufferLength =
|
|
(WORD)lpOptionalAttributes->dwLengthOfRequestData;
|
|
}
|
|
|
|
RtlInitUnicodeString( &ClassName, szClassName );
|
|
|
|
ntstatus =
|
|
FragExWithWait(
|
|
lpNdsObject->NdsTree,
|
|
NETWARE_NDS_FUNCTION_DEFINE_CLASS,
|
|
NdsReply,
|
|
NDS_BUFFER_SIZE,
|
|
&dwReplyLength,
|
|
"DDSDDrDrDrDrDr",
|
|
0, // Version
|
|
dwFlags,
|
|
&ClassName,
|
|
0, // ASN1 Id
|
|
NumberOfSuperClasses,
|
|
SuperClassesBuffer,
|
|
SuperClassesBufferLength,
|
|
NumberOfContainmentClasses,
|
|
ContainmentClassesBuffer,
|
|
ContainmentClassesBufferLength,
|
|
NumberOfNamingAttributes,
|
|
NamingAttributesBuffer,
|
|
NamingAttributesBufferLength,
|
|
NumberOfMandatoryAttributes,
|
|
MandatoryAttributesBuffer,
|
|
MandatoryAttributesBufferLength,
|
|
NumberOfOptionalAttributes,
|
|
OptionalAttributesBuffer,
|
|
OptionalAttributesBufferLength
|
|
);
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsDefineClass: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
ntstatus = ParseResponse( NdsReply,
|
|
dwReplyLength,
|
|
"GD",
|
|
&nwstatus );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsDefineClass: The define class response was undecipherable.\n" ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
SetLastError( MapNetwareErrorCode( nwstatus ) );
|
|
return nwstatus;
|
|
}
|
|
|
|
|
|
DWORD
|
|
NwNdsDeleteAttrDef(
|
|
IN HANDLE hTree,
|
|
IN LPWSTR szAttributeName )
|
|
/*
|
|
NwNdsDeleteAttrDef()
|
|
|
|
This function is used to remove an attribute definition from the schema of
|
|
NDS tree hTree.
|
|
|
|
Arguments:
|
|
|
|
HANDLE hTree - A handle to the directory tree to be
|
|
manipulated. Handle is obtained by calling
|
|
NwNdsOpenObject.
|
|
|
|
LPWSTR szAttributeName - The name of the attribute
|
|
defintion to remove.
|
|
|
|
Returns:
|
|
|
|
NO_ERROR
|
|
UNSUCCESSFUL - Call GetLastError for Win32 error code.
|
|
*/
|
|
{
|
|
DWORD nwstatus;
|
|
DWORD status = NO_ERROR;
|
|
NTSTATUS ntstatus = STATUS_SUCCESS;
|
|
DWORD dwReplyLength;
|
|
BYTE NdsReply[NDS_BUFFER_SIZE];
|
|
LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hTree;
|
|
UNICODE_STRING AttributeName;
|
|
|
|
if ( szAttributeName == NULL ||
|
|
lpNdsObject == NULL ||
|
|
lpNdsObject->Signature != NDS_SIGNATURE )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
RtlInitUnicodeString( &AttributeName, szAttributeName );
|
|
|
|
ntstatus =
|
|
FragExWithWait(
|
|
lpNdsObject->NdsTree,
|
|
NETWARE_NDS_FUNCTION_REMOVE_ATTR_DEF,
|
|
NdsReply,
|
|
NDS_BUFFER_SIZE,
|
|
&dwReplyLength,
|
|
"DS",
|
|
0, // Version
|
|
&AttributeName
|
|
);
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsDeleteAttrDef: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
ntstatus = ParseResponse( NdsReply,
|
|
dwReplyLength,
|
|
"GD",
|
|
&nwstatus );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsDeleteAttrDef: The delete attribute response was undecipherable.\n" ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
SetLastError( MapNetwareErrorCode( nwstatus ) );
|
|
return nwstatus;
|
|
}
|
|
|
|
|
|
DWORD
|
|
NwNdsDeleteClassDef(
|
|
IN HANDLE hTree,
|
|
IN LPWSTR szClassName )
|
|
/*
|
|
NwNdsDeleteClassDef()
|
|
|
|
This function is used to remove a class definition from the schema of
|
|
NDS tree hTree.
|
|
|
|
Arguments:
|
|
|
|
HANDLE hTree - A handle to the directory tree to be
|
|
manipulated. Handle is obtained by calling
|
|
NwNdsOpenObject.
|
|
|
|
LPWSTR szClassName - The name of the class defintion to remove.
|
|
|
|
Returns:
|
|
|
|
NO_ERROR
|
|
UNSUCCESSFUL - Call GetLastError for Win32 error code.
|
|
*/
|
|
{
|
|
DWORD nwstatus;
|
|
DWORD status = NO_ERROR;
|
|
NTSTATUS ntstatus = STATUS_SUCCESS;
|
|
DWORD dwReplyLength;
|
|
BYTE NdsReply[NDS_BUFFER_SIZE];
|
|
LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hTree;
|
|
UNICODE_STRING ClassName;
|
|
|
|
if ( szClassName == NULL ||
|
|
lpNdsObject == NULL ||
|
|
lpNdsObject->Signature != NDS_SIGNATURE )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
RtlInitUnicodeString( &ClassName, szClassName );
|
|
|
|
ntstatus =
|
|
FragExWithWait(
|
|
lpNdsObject->NdsTree,
|
|
NETWARE_NDS_FUNCTION_REMOVE_CLASS_DEF,
|
|
NdsReply,
|
|
NDS_BUFFER_SIZE,
|
|
&dwReplyLength,
|
|
"DS",
|
|
0, // Version
|
|
&ClassName
|
|
);
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsDeleteClassDef: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
ntstatus = ParseResponse( NdsReply,
|
|
dwReplyLength,
|
|
"GD",
|
|
&nwstatus );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsDeleteClassDef: The delete class response was undecipherable.\n" ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
SetLastError( MapNetwareErrorCode( nwstatus ) );
|
|
return nwstatus;
|
|
}
|
|
|
|
|
|
VOID
|
|
NwNdsDeleteQueryNode(
|
|
IN LPQUERY_NODE lpQueryNode
|
|
)
|
|
/*
|
|
NwNdsDeleteQueryNode()
|
|
|
|
This function is used to free a tree node that was part of a query
|
|
used with the function NwNdsSearch.
|
|
|
|
Arguments:
|
|
|
|
LPQUERY_NODE lpQueryNode - A pointer to a particular node of
|
|
a query tree that defines a search. The tree is
|
|
created manually by the user through the function
|
|
NwNdsCreateQueryNode.
|
|
|
|
Returns:
|
|
|
|
Nothing
|
|
*/
|
|
{
|
|
(void) LocalFree( (HLOCAL) lpQueryNode );
|
|
|
|
lpQueryNode = NULL;
|
|
}
|
|
|
|
|
|
DWORD
|
|
NwNdsDeleteQueryTree(
|
|
IN LPQUERY_TREE lpQueryTree
|
|
)
|
|
/*
|
|
NwNdsDeleteQueryTree()
|
|
|
|
This function is used to free a tree that describes a query that was
|
|
used with the function NwNdsSearch.
|
|
|
|
Arguments:
|
|
|
|
LPQUERY_TREE lpQueryTree - A pointer to the root of a query
|
|
tree that defines a search.
|
|
|
|
Returns:
|
|
|
|
NO_ERROR
|
|
UNSUCCESSFUL - Call GetLastError for Win32 error code.
|
|
*/
|
|
{
|
|
DWORD status;
|
|
|
|
switch( lpQueryTree->dwOperation )
|
|
{
|
|
case NDS_QUERY_OR :
|
|
case NDS_QUERY_AND :
|
|
|
|
if ( lpQueryTree->lpLVal == NULL || lpQueryTree->lpRVal == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsDeleteQueryTree was not passed a pointer to an L or R value.\n" ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
status = NwNdsDeleteQueryTree( lpQueryTree->lpLVal );
|
|
|
|
if ( status != NO_ERROR )
|
|
{
|
|
return status;
|
|
}
|
|
|
|
lpQueryTree->lpLVal = NULL;
|
|
|
|
status = NwNdsDeleteQueryTree( lpQueryTree->lpRVal );
|
|
|
|
if ( status != NO_ERROR )
|
|
{
|
|
return status;
|
|
}
|
|
|
|
lpQueryTree->lpRVal = NULL;
|
|
|
|
NwNdsDeleteQueryNode( lpQueryTree );
|
|
|
|
break;
|
|
|
|
case NDS_QUERY_NOT :
|
|
|
|
if ( lpQueryTree->lpLVal == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsCreateQueryNode was not passed a pointer to an L value.\n" ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
status = NwNdsDeleteQueryTree( lpQueryTree->lpLVal );
|
|
|
|
if ( status != NO_ERROR )
|
|
{
|
|
return status;
|
|
}
|
|
|
|
lpQueryTree->lpLVal = NULL;
|
|
|
|
NwNdsDeleteQueryNode( lpQueryTree );
|
|
|
|
break;
|
|
|
|
case NDS_QUERY_EQUAL :
|
|
case NDS_QUERY_GE :
|
|
case NDS_QUERY_LE :
|
|
case NDS_QUERY_APPROX :
|
|
case NDS_QUERY_PRESENT :
|
|
|
|
NwNdsDeleteQueryNode( lpQueryTree );
|
|
|
|
break;
|
|
|
|
default :
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsDeleteQueryTree was passed an unidentified operation - 0x%.8X.\n", lpQueryTree->dwOperation ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
DWORD
|
|
NwNdsFreeBuffer(
|
|
IN HANDLE hOperationData
|
|
)
|
|
/*
|
|
NwNdsFreeBuffer()
|
|
|
|
This function is used to free the buffer used to describe object
|
|
operations to a specific object in an NDS directory tree. The buffer must
|
|
be one created by NwNdsCreateBuffer, or returned by calling NwNdsReadObject,
|
|
NwNdsReadAttrDef, or NwNdsReadClassDef.
|
|
|
|
Arguments:
|
|
|
|
HANDLE hOperationData - Handle to buffer that is to be freed.
|
|
|
|
Returns:
|
|
|
|
NO_ERROR
|
|
UNSUCCESSFUL - Call GetLastError for Win32 error code.
|
|
*/
|
|
{
|
|
DWORD status = NO_ERROR;
|
|
LPNDS_BUFFER lpNdsBuffer = (LPNDS_BUFFER) hOperationData;
|
|
|
|
if ( lpNdsBuffer == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsFreeBuffer was passed a NULL buffer pointer.\n" ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
if ( lpNdsBuffer->dwBufferId != NDS_SIGNATURE )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsFreeBuffer was passed an unidentified buffer.\n" ));
|
|
ASSERT( FALSE );
|
|
#endif
|
|
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// If this buffer contains a pointer to an index buffer. Need to free
|
|
// the index buffer.
|
|
//
|
|
if ( lpNdsBuffer->lpIndexBuffer )
|
|
{
|
|
if ( lpNdsBuffer->dwOperation == NDS_SEARCH &&
|
|
lpNdsBuffer->dwNumberOfIndexEntries )
|
|
{
|
|
LPNDS_OBJECT_INFO lpObjectInfo = (LPNDS_OBJECT_INFO)
|
|
lpNdsBuffer->lpIndexBuffer;
|
|
DWORD iter;
|
|
|
|
for ( iter = 0; iter < lpNdsBuffer->dwNumberOfIndexEntries; iter++ )
|
|
{
|
|
(void) LocalFree( (HLOCAL) lpObjectInfo[iter].lpAttribute );
|
|
lpObjectInfo[iter].lpAttribute = NULL;
|
|
lpObjectInfo[iter].dwNumberOfAttributes = 0;
|
|
}
|
|
}
|
|
|
|
(void) LocalFree( (HLOCAL) lpNdsBuffer->lpIndexBuffer );
|
|
lpNdsBuffer->lpIndexBuffer = NULL;
|
|
}
|
|
|
|
//
|
|
// If this buffer contains a pointer to a reply buffer. Need to free
|
|
// the reply buffer.
|
|
//
|
|
if ( lpNdsBuffer->lpReplyBuffer )
|
|
{
|
|
(void) LocalFree( (HLOCAL) lpNdsBuffer->lpReplyBuffer );
|
|
lpNdsBuffer->lpReplyBuffer = NULL;
|
|
}
|
|
|
|
//
|
|
// If this buffer contains a pointer to a request buffer. Need to free
|
|
// the request buffer.
|
|
//
|
|
if ( lpNdsBuffer->lpRequestBuffer )
|
|
{
|
|
(void) LocalFree( (HLOCAL) lpNdsBuffer->lpRequestBuffer );
|
|
lpNdsBuffer->lpRequestBuffer = NULL;
|
|
}
|
|
|
|
//
|
|
// If this buffer contains a pointer to a syntax buffer. Need to free
|
|
// the syntax buffer.
|
|
//
|
|
if ( lpNdsBuffer->lpSyntaxBuffer )
|
|
{
|
|
(void) LocalFree( (HLOCAL) lpNdsBuffer->lpSyntaxBuffer );
|
|
lpNdsBuffer->lpSyntaxBuffer = NULL;
|
|
}
|
|
|
|
//
|
|
// Now free the handle buffer.
|
|
//
|
|
(void) LocalFree((HLOCAL) lpNdsBuffer);
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
DWORD
|
|
NwNdsGetAttrDefListFromBuffer(
|
|
IN HANDLE hOperationData,
|
|
OUT LPDWORD lpdwNumberOfEntries,
|
|
OUT LPDWORD lpdwInformationType,
|
|
OUT LPVOID * lppEntries )
|
|
/*
|
|
NwNdsGetAttrDefListFromBuffer()
|
|
|
|
This function is used to retrieve an array of attribute definition entries
|
|
for a schema that was read with a prior call to NwNdsReadAttrDef.
|
|
|
|
Arguments:
|
|
|
|
HANDLE hOperationData - Buffer containing the read
|
|
response from calling NwNdsReadAttrDef.
|
|
|
|
LPDWORD lpdwNumberOfEntries - The address of a DWORD to
|
|
receive the number of array elements pointed to by
|
|
lppEntries.
|
|
|
|
LPDWORD lpdwInformationType - The address of a DWORD to
|
|
receive a value that indicates the type of information
|
|
returned by the call to NwNdsReadAttrDef.
|
|
|
|
LPVOID * lppEntries - The address of a pointer to the beginning
|
|
of an array of attribute schema structures. Each
|
|
structure contains the details of each attribute
|
|
definition read from a given schema by calling
|
|
NwNdsReadAttrDef. The lppEntries value should be
|
|
cast to either a LPNDS_ATTR_DEF or LPNDS_NAME_ONLY
|
|
structure depending on the value returned in
|
|
lpdwInformationType.
|
|
|
|
Returns:
|
|
|
|
NO_ERROR
|
|
UNSUCCESSFUL - Call GetLastError for Win32 error code.
|
|
*/
|
|
{
|
|
LPNDS_BUFFER lpNdsBuffer = (LPNDS_BUFFER) hOperationData;
|
|
|
|
//
|
|
// Check to see if the data handle is one for reading attribute definitions.
|
|
//
|
|
if ( lpNdsBuffer == NULL ||
|
|
lpNdsBuffer->dwBufferId != NDS_SIGNATURE ||
|
|
lpNdsBuffer->dwOperation != NDS_SCHEMA_READ_ATTR_DEF )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// Check to see if NwNdsReadAttrDef has been called yet.
|
|
//
|
|
if ( lpNdsBuffer->lpReplyBuffer == NULL )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// Check to see if the call to NwNdsReadAttrDef returned any attributes.
|
|
//
|
|
if ( lpNdsBuffer->dwNumberOfReplyEntries == 0 )
|
|
{
|
|
SetLastError( ERROR_NO_DATA );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// If TRUE, we need to walk raw response to set indexes to data within.
|
|
//
|
|
if ( lpNdsBuffer->lpIndexBuffer == NULL )
|
|
{
|
|
DWORD status;
|
|
|
|
if ( lpNdsBuffer->dwReplyInformationType == NDS_INFO_NAMES )
|
|
{
|
|
status = IndexReadNameReplyBuffer( lpNdsBuffer );
|
|
}
|
|
else
|
|
{
|
|
status = IndexReadAttrDefReplyBuffer( lpNdsBuffer );
|
|
}
|
|
|
|
if ( status )
|
|
{
|
|
SetLastError( status );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
}
|
|
|
|
lpNdsBuffer->dwCurrentIndexEntry = 0;
|
|
*lpdwNumberOfEntries = lpNdsBuffer->dwNumberOfIndexEntries;
|
|
*lpdwInformationType = lpNdsBuffer->dwReplyInformationType;
|
|
*lppEntries = (LPVOID) lpNdsBuffer->lpIndexBuffer;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
DWORD
|
|
NwNdsGetAttrListFromBuffer(
|
|
IN HANDLE hOperationData,
|
|
OUT LPDWORD lpdwNumberOfEntries,
|
|
OUT LPNDS_ATTR_INFO * lppEntries )
|
|
/*
|
|
NwNdsGetAttrListFromBuffer()
|
|
|
|
This function is used to retrieve an array of attribute entries for an
|
|
object that was read with a prior call to NwNdsReadObject.
|
|
|
|
Arguments:
|
|
|
|
HANDLE hOperationData - Buffer containing the read
|
|
response from calling NwNdsReadObject.
|
|
|
|
LPDWORD lpdwNumberOfEntries - The address of a DWORD to
|
|
receive the number of array elements pointed to by
|
|
lppEntries.
|
|
|
|
LPNDS_ATTR_INFO *
|
|
lppEntries - The address of a pointer to the beginning
|
|
of an array of NDS_ATTR_INFO structures. Each
|
|
structure contains the details of each attribute read
|
|
from a given object by calling NwNdsReadObject.
|
|
|
|
Returns:
|
|
|
|
NO_ERROR
|
|
UNSUCCESSFUL - Call GetLastError for Win32 error code.
|
|
*/
|
|
{
|
|
LPNDS_BUFFER lpNdsBuffer = (LPNDS_BUFFER) hOperationData;
|
|
|
|
//
|
|
// Check to see if the data handle is one for reading attributes.
|
|
//
|
|
if ( lpNdsBuffer == NULL ||
|
|
lpNdsBuffer->dwBufferId != NDS_SIGNATURE ||
|
|
lpNdsBuffer->dwOperation != NDS_OBJECT_READ )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// Check to see if NwNdsReadObject has been called yet.
|
|
//
|
|
if ( lpNdsBuffer->lpReplyBuffer == NULL )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// Check to see if the call to NwNdsReadObject returned any attributes.
|
|
//
|
|
if ( lpNdsBuffer->dwNumberOfReplyEntries == 0 )
|
|
{
|
|
SetLastError( ERROR_NO_DATA );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// If TRUE, we need to walk raw response to set indexes to data within.
|
|
//
|
|
if ( lpNdsBuffer->lpIndexBuffer == NULL )
|
|
{
|
|
DWORD status;
|
|
|
|
if ( lpNdsBuffer->dwReplyInformationType == NDS_INFO_NAMES )
|
|
{
|
|
status = IndexReadNameReplyBuffer( lpNdsBuffer );
|
|
}
|
|
else
|
|
{
|
|
status = IndexReadObjectReplyBuffer( lpNdsBuffer );
|
|
}
|
|
|
|
if ( status )
|
|
{
|
|
SetLastError( status );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
}
|
|
|
|
ASSERT( lpNdsBuffer->lpIndexBuffer != NULL );
|
|
|
|
lpNdsBuffer->dwCurrentIndexEntry = 0;
|
|
*lpdwNumberOfEntries = lpNdsBuffer->dwNumberOfIndexEntries;
|
|
*lppEntries = (LPNDS_ATTR_INFO) lpNdsBuffer->lpIndexBuffer;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
DWORD
|
|
NwNdsGetClassDefListFromBuffer(
|
|
IN HANDLE hOperationData,
|
|
OUT LPDWORD lpdwNumberOfEntries,
|
|
OUT LPDWORD lpdwInformationType,
|
|
OUT LPVOID * lppEntries )
|
|
/*
|
|
NwNdsGetClassDefListFromBuffer()
|
|
|
|
This function is used to retrieve an array of class definition entries
|
|
for a schema that was read with a prior call to NwNdsReadClassDef.
|
|
|
|
Arguments:
|
|
|
|
HANDLE hOperationData - Buffer containing the read
|
|
response from calling NwNdsReadClassDef.
|
|
|
|
LPDWORD lpdwNumberOfEntries - The address of a DWORD to
|
|
receive the number of array elements pointed to by
|
|
lppEntries.
|
|
|
|
LPDWORD lpdwInformationType - The address of a DWORD to
|
|
receive a value that indicates the type of information
|
|
returned by the call to NwNdsReadClassDef.
|
|
|
|
LPVOID * lppEntries - The address of a pointer to the beginning
|
|
of an array of schema class structures. Each
|
|
structure contains the details of each class
|
|
definition read from a given schema by calling
|
|
NwNdsReadClassDef. The lppEntries value should be
|
|
cast to either a LPNDS_CLASS_DEF or LPNDS_DEF_NAME_ONLY
|
|
structure depending on the value returned in
|
|
lpdwInformationType.
|
|
|
|
Returns:
|
|
|
|
NO_ERROR
|
|
UNSUCCESSFUL - Call GetLastError for Win32 error code.
|
|
*/
|
|
{
|
|
LPNDS_BUFFER lpNdsBuffer = (LPNDS_BUFFER) hOperationData;
|
|
|
|
//
|
|
// Check to see if the data handle is one for reading class definitions.
|
|
//
|
|
if ( lpNdsBuffer == NULL ||
|
|
lpNdsBuffer->dwBufferId != NDS_SIGNATURE ||
|
|
lpNdsBuffer->dwOperation != NDS_SCHEMA_READ_CLASS_DEF )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// Check to see if NwNdsReadClassDef has been called yet.
|
|
//
|
|
if ( lpNdsBuffer->lpReplyBuffer == NULL )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// Check to see if the call to NwNdsReadClassDef returned any classes.
|
|
//
|
|
if ( lpNdsBuffer->dwNumberOfReplyEntries == 0 )
|
|
{
|
|
SetLastError( ERROR_NO_DATA );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// If TRUE, we need to walk raw response to set indexes to data within.
|
|
//
|
|
if ( lpNdsBuffer->lpIndexBuffer == NULL )
|
|
{
|
|
DWORD status;
|
|
|
|
if ( lpNdsBuffer->dwReplyInformationType == NDS_INFO_NAMES )
|
|
{
|
|
status = IndexReadNameReplyBuffer( lpNdsBuffer );
|
|
}
|
|
else
|
|
{
|
|
status = IndexReadClassDefReplyBuffer( lpNdsBuffer );
|
|
}
|
|
|
|
if ( status )
|
|
{
|
|
SetLastError( status );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
}
|
|
|
|
ASSERT( lpNdsBuffer->lpIndexBuffer != NULL );
|
|
|
|
lpNdsBuffer->dwCurrentIndexEntry = 0;
|
|
*lpdwNumberOfEntries = lpNdsBuffer->dwNumberOfIndexEntries;
|
|
*lpdwInformationType = lpNdsBuffer->dwReplyInformationType;
|
|
*lppEntries = (LPVOID) lpNdsBuffer->lpIndexBuffer;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
DWORD
|
|
NwNdsGetEffectiveRights(
|
|
IN HANDLE hObject,
|
|
IN LPWSTR szSubjectName,
|
|
IN LPWSTR szAttributeName,
|
|
OUT LPDWORD lpdwRights )
|
|
/*
|
|
NwNdsGetEffectiveRights()
|
|
|
|
This function is used to determine the effective rights of a particular
|
|
subject on a particular object in the NDS tree. The user needs to have
|
|
appropriate priveleges to make the determination.
|
|
|
|
Arguments:
|
|
|
|
HANDLE hObject - A handle to the object in the directory
|
|
tree to determine effective rights on. Handle is
|
|
obtained by calling NwNdsOpenObject.
|
|
|
|
LPWSTR szSubjectName - The distinguished name of user whose
|
|
rights we're interested in determining.
|
|
|
|
LPWSTR szAttributeName - Regular attribute name (i.e.
|
|
L"Surname" , L"CN" ) for reading a particular
|
|
attribute right, or L"[All Attribute Rights]" and
|
|
L"[Entry Rights]" can be used to determine the default
|
|
attribute rights and object rights respectively.
|
|
|
|
LPDWORD lpdwRights - A pointer to a DWORD to receive the
|
|
results. If the call is successful, lpdwRights will
|
|
contain a mask representing the subject's rights:
|
|
|
|
Attribute rights - NDS_RIGHT_COMPARE_ATTR,
|
|
NDS_RIGHT_READ_ATTR, NDS_RIGHT_WRITE_ATTR,
|
|
NDS_RIGHT_ADD_SELF_ATTR, and
|
|
NDS_RIGHT_SUPERVISE_ATTR.
|
|
|
|
Object rights - NDS_RIGHT_BROWSE_OBJECT,
|
|
NDS_RIGHT_CREATE_OBJECT, NDS_RIGHT_DELETE_OBJECT,
|
|
NDS_RIGHT_RENAME_OBJECT, and
|
|
NDS_RIGHT_SUPERVISE_OBJECT.
|
|
|
|
Returns:
|
|
|
|
NO_ERROR
|
|
UNSUCCESSFUL - Call GetLastError for Win32 error code.
|
|
*/
|
|
{
|
|
DWORD nwstatus;
|
|
DWORD status = NO_ERROR;
|
|
NTSTATUS ntstatus = STATUS_SUCCESS;
|
|
DWORD dwReplyLength;
|
|
BYTE NdsReply[NDS_BUFFER_SIZE];
|
|
LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hObject;
|
|
UNICODE_STRING SubjectName;
|
|
UNICODE_STRING AttributeName;
|
|
|
|
if ( szAttributeName == NULL ||
|
|
szSubjectName == NULL ||
|
|
lpNdsObject == NULL ||
|
|
lpNdsObject->Signature != NDS_SIGNATURE )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
RtlInitUnicodeString( &SubjectName, szSubjectName );
|
|
RtlInitUnicodeString( &AttributeName, szAttributeName );
|
|
|
|
ntstatus =
|
|
FragExWithWait(
|
|
lpNdsObject->NdsTree,
|
|
NETWARE_NDS_FUNCTION_GET_EFFECTIVE_RIGHTS,
|
|
NdsReply,
|
|
NDS_BUFFER_SIZE,
|
|
&dwReplyLength,
|
|
"DDSS",
|
|
0, // Version
|
|
lpNdsObject->ObjectId,
|
|
&SubjectName,
|
|
&AttributeName
|
|
);
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsGetEffectiveRights: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
ntstatus = ParseResponse( NdsReply,
|
|
dwReplyLength,
|
|
"GD",
|
|
&nwstatus );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsGetEffectiveRights: The status code response was undecipherable.\n" ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
if ( nwstatus )
|
|
{
|
|
SetLastError( MapNetwareErrorCode( nwstatus ) );
|
|
return nwstatus;
|
|
}
|
|
|
|
ntstatus = ParseResponse( NdsReply,
|
|
dwReplyLength,
|
|
"G_D",
|
|
1 * sizeof(DWORD),
|
|
lpdwRights );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsGetEffectiveRights: The effective rights response was undecipherable.\n" ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
SetLastError( MapNetwareErrorCode( nwstatus ) );
|
|
return nwstatus;
|
|
}
|
|
|
|
|
|
DWORD
|
|
NwNdsGetObjectListFromBuffer(
|
|
IN HANDLE hOperationData,
|
|
OUT LPDWORD lpdwNumberOfEntries,
|
|
OUT LPDWORD lpdwAttrInformationType OPTIONAL,
|
|
OUT LPNDS_OBJECT_INFO * lppEntries )
|
|
/*
|
|
NwNdsGetObjectListFromBuffer()
|
|
|
|
This function is used to retrieve an array of object entries for
|
|
objects that were read with a prior call to either
|
|
NwNdsListSubObjects or NwNdsSearch.
|
|
|
|
Arguments:
|
|
|
|
HANDLE hOperationData - Buffer containing the read
|
|
response from calling NwNdsListSubObjects, or a
|
|
buffer containing the search results from a call
|
|
to NwNdsSearch.
|
|
|
|
LPDWORD lpdwNumberOfEntries - The address of a DWORD to
|
|
receive the number of array elements pointed to by
|
|
lppEntries.
|
|
|
|
LPDWORD lpdwAttrInformationType - The address of a DWORD to
|
|
receive a value that indicates the type of attribute
|
|
information returned by the call to NwNdsSearch.
|
|
This attribute information type determines which
|
|
buffer structure (LPNDS_ATTR_INFO or LPNDS_NAME_ONLY)
|
|
should be used for the lpAttribute field found in
|
|
each NDS_OBJECT_INFO structure below.
|
|
|
|
- or -
|
|
|
|
NULL to indicate that the callee is not interested,
|
|
especially when the object list is that from a call
|
|
to NwNdsListSubObjects.
|
|
|
|
LPNDS_OBJECT_INFO *
|
|
lppEntries - The address of a pointer to the beginning
|
|
of an array of NDS_OBJECT_INFO structures. Each
|
|
structure contains the details of each object returned
|
|
from a call to NwNdsListSubObjects or NwNdsSearch.
|
|
|
|
Returns:
|
|
|
|
NO_ERROR
|
|
UNSUCCESSFUL - Call GetLastError for Win32 error code.
|
|
*/
|
|
{
|
|
LPNDS_BUFFER lpNdsBuffer = (LPNDS_BUFFER) hOperationData;
|
|
|
|
*lpdwNumberOfEntries = 0;
|
|
*lppEntries = NULL;
|
|
|
|
//
|
|
// Check to see if the data handle is one for listing subordinates or
|
|
// for searching.
|
|
//
|
|
if ( lpNdsBuffer == NULL ||
|
|
lpNdsBuffer->dwBufferId != NDS_SIGNATURE ||
|
|
( lpNdsBuffer->dwOperation != NDS_OBJECT_LIST_SUBORDINATES &&
|
|
lpNdsBuffer->dwOperation != NDS_SEARCH ) )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// Check to see if the call to NwNdsListSubObjects returned any objects.
|
|
//
|
|
if ( lpNdsBuffer->dwOperation == NDS_OBJECT_LIST_SUBORDINATES &&
|
|
lpNdsBuffer->dwNumberOfIndexEntries == 0 )
|
|
{
|
|
SetLastError( ERROR_NO_DATA );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// Check to see if the call to NwNdsSearch returned any objects.
|
|
//
|
|
if ( lpNdsBuffer->dwOperation == NDS_SEARCH &&
|
|
lpNdsBuffer->dwNumberOfReplyEntries == 0 )
|
|
{
|
|
SetLastError( ERROR_NO_DATA );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// If TRUE, we need to walk raw response to set indexes to data within.
|
|
//
|
|
if ( lpNdsBuffer->dwOperation == NDS_SEARCH &&
|
|
lpNdsBuffer->lpIndexBuffer == NULL )
|
|
{
|
|
DWORD status;
|
|
|
|
status = IndexSearchObjectReplyBuffer( lpNdsBuffer );
|
|
|
|
if ( status )
|
|
{
|
|
SetLastError( status );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
}
|
|
|
|
ASSERT( lpNdsBuffer->lpIndexBuffer != NULL );
|
|
|
|
lpNdsBuffer->dwCurrentIndexEntry = 0;
|
|
*lpdwNumberOfEntries = lpNdsBuffer->dwNumberOfIndexEntries;
|
|
*lppEntries = (LPNDS_OBJECT_INFO) lpNdsBuffer->lpIndexBuffer;
|
|
|
|
if ( lpdwAttrInformationType )
|
|
{
|
|
*lpdwAttrInformationType = lpNdsBuffer->dwReplyInformationType;
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
DWORD
|
|
NwNdsGetSyntaxID(
|
|
IN HANDLE hTree,
|
|
IN LPWSTR szlpAttributeName,
|
|
OUT LPDWORD lpdwSyntaxID )
|
|
/*
|
|
NwNdsGetObjListFromBuffer()
|
|
|
|
This function is used to retrieve the Syntax ID of a given attribute name.
|
|
|
|
Arguments:
|
|
|
|
HANDLE hTree - A handle to the directory tree to be
|
|
manipulated. Handle is obtained by calling
|
|
NwNdsOpenObject.
|
|
|
|
LPWSTR szlpAttributeName - The attribute name whose Syntax ID
|
|
is requested.
|
|
|
|
LPDWORD lpdwSyntaxID - The address of a DWORD to receive the
|
|
SyntaxID.
|
|
|
|
Returns:
|
|
|
|
NO_ERROR
|
|
UNSUCCESSFUL - Call GetLastError for Win32 error code.
|
|
*/
|
|
{
|
|
DWORD nwstatus;
|
|
DWORD status = NO_ERROR;
|
|
NTSTATUS ntstatus = STATUS_SUCCESS;
|
|
DWORD dwReplyLength;
|
|
BYTE NdsReply[NDS_BUFFER_SIZE];
|
|
LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hTree;
|
|
UNICODE_STRING AttributeName;
|
|
DWORD dwNumEntries;
|
|
DWORD dwStringLen;
|
|
LPBYTE lpByte;
|
|
DWORD LengthInBytes;
|
|
LPBYTE lpTempEntry = NULL;
|
|
|
|
if ( lpNdsObject == NULL ||
|
|
szlpAttributeName == NULL ||
|
|
lpNdsObject->Signature != NDS_SIGNATURE )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
RtlInitUnicodeString( &AttributeName, szlpAttributeName );
|
|
|
|
// allocate enough extra space for the padding PrepareReadEntry will do
|
|
lpTempEntry = LocalAlloc( LPTR, AttributeName.Length + (2*sizeof(DWORD)) );
|
|
|
|
if ( ! lpTempEntry )
|
|
{
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
PrepareReadEntry( lpTempEntry,
|
|
AttributeName,
|
|
&LengthInBytes );
|
|
|
|
|
|
ntstatus = FragExWithWait( lpNdsObject->NdsTree,
|
|
NETWARE_NDS_FUNCTION_READ_ATTR_DEF,
|
|
NdsReply,
|
|
NDS_BUFFER_SIZE,
|
|
&dwReplyLength,
|
|
"DDDDDr",
|
|
0, // Version
|
|
NDS_NO_MORE_ITERATIONS, // Initial iteration
|
|
NDS_INFO_NAMES_DEFS,
|
|
(DWORD) FALSE, // All attributes indicator
|
|
1, // Number of attributes
|
|
lpTempEntry,
|
|
LengthInBytes);
|
|
|
|
(void) LocalFree((HLOCAL) lpTempEntry );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsGetSyntaxID: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
ntstatus = ParseResponse( NdsReply,
|
|
dwReplyLength,
|
|
"GD",
|
|
&nwstatus );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsGetSyntaxID: The get syntax id response was undecipherable.\n" ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
if ( nwstatus )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsGetSyntaxID: NetWare error 0x%.8X reading %ws.\n", nwstatus, szlpAttributeName ));
|
|
#endif
|
|
SetLastError( MapNetwareErrorCode( nwstatus ) );
|
|
return nwstatus;
|
|
}
|
|
|
|
ntstatus = ParseResponse( NdsReply,
|
|
dwReplyLength,
|
|
"G_D",
|
|
3 * sizeof(DWORD),
|
|
&dwNumEntries );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsGetSyntaxID: The attribute read response was undecipherable.\n" ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
ASSERT( dwNumEntries == 1 );
|
|
|
|
//
|
|
// Set lpByte to the point in the reply buffer that has the attribute
|
|
// name length.
|
|
//
|
|
lpByte = NdsReply + ( 4 * sizeof(DWORD) );
|
|
|
|
//
|
|
// Get the attribute name length and move lpByte to beginning of
|
|
// attribute name
|
|
//
|
|
dwStringLen = * (LPDWORD) lpByte;
|
|
lpByte += sizeof(DWORD);
|
|
|
|
//
|
|
// Move lpByte past the attribute name so that it points to the
|
|
// attribute flags value
|
|
//
|
|
lpByte += ROUND_UP_COUNT( dwStringLen,
|
|
ALIGN_DWORD);
|
|
|
|
//
|
|
// Move lpByte past the attribute flags value so that it now points to
|
|
// the attribute syntax id value
|
|
//
|
|
lpByte += sizeof(DWORD);
|
|
*lpdwSyntaxID = * (LPDWORD) lpByte;
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
DWORD
|
|
NwNdsListSubObjects(
|
|
IN HANDLE hParentObject,
|
|
IN DWORD dwEntriesRequested,
|
|
OUT LPDWORD lpdwEntriesReturned,
|
|
IN LPNDS_FILTER_LIST lpFilters OPTIONAL,
|
|
OUT HANDLE * lphOperationData )
|
|
/*
|
|
NwNdsListSubObjects()
|
|
|
|
This function is used to enumerate the subordinate objects for a particular
|
|
parent object. A filter can be passed in to restrict enumeration to a
|
|
a specific class type or list of class types.
|
|
|
|
Arguments:
|
|
|
|
HANDLE hParentObject - A handle to the object in the directory
|
|
tree whose subordinate objects (if any) will be
|
|
enumerated.
|
|
|
|
DWORD dwEntriesRequested - The number of subordinate objects
|
|
to list. A subsequent call to NwNdsListSubObjects will
|
|
continue enumeration following the last item returned.
|
|
|
|
LPDWORD lpdwEntriesReturned - A pointer to a DWORD that will
|
|
contain the actual number of subobjects enumerated in
|
|
the call.
|
|
|
|
LPNDS_FILTER_LIST lpFilters - The caller can specify the object class
|
|
names for the kinds of objects that they would like
|
|
to enumerate. For example if just User and Group
|
|
object classes should be enumerated, then a filter
|
|
for class names NDS_CLASS_USER and NDS_CLASS_GROUP
|
|
should be pass in.
|
|
|
|
- or -
|
|
|
|
NULL to indicate that all objects should be returned
|
|
(no filter).
|
|
|
|
HANDLE * lphOperationData - Address of a HANDLE handle to
|
|
receive created buffer that contains the list of
|
|
subordinate objects read from the object
|
|
hParentObject. This handle is manipulated by the
|
|
following functions:
|
|
NwNdsGetObjListFromBuffer and NwNdsFreeBuffer.
|
|
|
|
Returns:
|
|
|
|
NO_ERROR
|
|
UNSUCCESSFUL - Call GetLastError for Win32 error code.
|
|
*/
|
|
{
|
|
DWORD status = NO_ERROR;
|
|
LPNDS_BUFFER lpNdsBuffer = NULL;
|
|
LPNDS_OBJECT_PRIV lpNdsParentObject = (LPNDS_OBJECT_PRIV) hParentObject;
|
|
LPBYTE FixedPortion = NULL;
|
|
LPWSTR EndOfVariableData = NULL;
|
|
BOOL FitInBuffer = TRUE;
|
|
|
|
//
|
|
// Test the parameters.
|
|
//
|
|
if ( lpNdsParentObject == NULL ||
|
|
lpNdsParentObject->Signature != NDS_SIGNATURE )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
if ( lpNdsParentObject->ResumeId == NDS_NO_MORE_ITERATIONS )
|
|
{
|
|
if ( lpNdsParentObject->NdsRawDataBuffer )
|
|
{
|
|
(void) LocalFree( (HLOCAL) lpNdsParentObject->NdsRawDataBuffer );
|
|
lpNdsParentObject->NdsRawDataBuffer = 0;
|
|
lpNdsParentObject->NdsRawDataSize = 0;
|
|
lpNdsParentObject->NdsRawDataId = INITIAL_ITERATION;
|
|
lpNdsParentObject->NdsRawDataCount = 0;
|
|
}
|
|
|
|
//
|
|
// Reached the end of enumeration.
|
|
//
|
|
return WN_NO_MORE_ENTRIES;
|
|
}
|
|
|
|
//
|
|
// Allocate a results buffer
|
|
//
|
|
status = NwNdsCreateBuffer( NDS_OBJECT_LIST_SUBORDINATES,
|
|
(HANDLE *) &lpNdsBuffer );
|
|
|
|
if ( status )
|
|
{
|
|
return status;
|
|
}
|
|
|
|
FixedPortion = lpNdsBuffer->lpIndexBuffer;
|
|
EndOfVariableData = (LPWSTR) ((DWORD_PTR) FixedPortion +
|
|
ROUND_DOWN_COUNT(
|
|
lpNdsBuffer->dwIndexAvailableBytes,
|
|
ALIGN_DWORD ) );
|
|
|
|
*lpdwEntriesReturned = 0;
|
|
*lphOperationData = NULL;
|
|
|
|
while ( FitInBuffer &&
|
|
dwEntriesRequested > *lpdwEntriesReturned &&
|
|
status == NO_ERROR )
|
|
{
|
|
if ( lpNdsParentObject->ResumeId == 0 )
|
|
{
|
|
//
|
|
// Get the first subtree entry.
|
|
//
|
|
status = GetFirstNdsSubTreeEntry( lpNdsParentObject,
|
|
lpNdsBuffer->dwRequestAvailableBytes );
|
|
}
|
|
|
|
//
|
|
// Either ResumeId contains the first entry we just got from
|
|
// GetFirstNdsSubTreeEntry or it contains the next directory
|
|
// entry to return.
|
|
//
|
|
if (status == NO_ERROR && lpNdsParentObject->ResumeId != 0)
|
|
{
|
|
WORD tempStrLen;
|
|
LPWSTR newPathStr = NULL;
|
|
LPWSTR tempStr = NULL;
|
|
LPWSTR ClassName;
|
|
LPWSTR ObjectName;
|
|
DWORD ClassNameLen;
|
|
DWORD ObjectNameLen;
|
|
DWORD EntryId;
|
|
DWORD SubordinateCount;
|
|
DWORD ModificationTime;
|
|
BOOL fWriteThisObject = FALSE;
|
|
|
|
//
|
|
// Get current subtree data from lpNdsParentObject
|
|
//
|
|
GetSubTreeData( lpNdsParentObject->ResumeId,
|
|
&EntryId,
|
|
&SubordinateCount,
|
|
&ModificationTime,
|
|
&ClassNameLen,
|
|
&ClassName,
|
|
&ObjectNameLen,
|
|
&ObjectName );
|
|
|
|
if ( lpFilters )
|
|
{
|
|
DWORD iter;
|
|
|
|
for ( iter = 0; iter < lpFilters->dwNumberOfFilters; iter++ )
|
|
{
|
|
if (!wcscmp(lpFilters->Filters[iter].szObjectClass, ClassName))
|
|
fWriteThisObject = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fWriteThisObject = TRUE;
|
|
}
|
|
|
|
if ( fWriteThisObject )
|
|
{
|
|
//
|
|
// Need to build a string with the new NDS UNC path
|
|
// for subtree object
|
|
//
|
|
newPathStr = (PVOID) LocalAlloc( LPTR,
|
|
( wcslen(ObjectName) +
|
|
wcslen(lpNdsParentObject->szContainerName) +
|
|
3 ) * sizeof(WCHAR) );
|
|
|
|
if ( newPathStr == NULL )
|
|
{
|
|
(void) NwNdsFreeBuffer( (HANDLE) lpNdsBuffer );
|
|
#if DBG
|
|
KdPrint(("NDS32: NwNdsListSubObjects LocalAlloc Failed 0x%.8X\n", GetLastError()));
|
|
#endif
|
|
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
tempStrLen = ParseNdsUncPath( (LPWSTR *) &tempStr,
|
|
lpNdsParentObject->szContainerName,
|
|
PARSE_NDS_GET_TREE_NAME );
|
|
|
|
tempStrLen /= sizeof(WCHAR);
|
|
|
|
if ( tempStrLen > 0 )
|
|
{
|
|
wcscpy( newPathStr, L"\\\\" );
|
|
wcsncat( newPathStr, tempStr, tempStrLen );
|
|
wcscat( newPathStr, L"\\" );
|
|
wcscat( newPathStr, ObjectName );
|
|
_wcsupr( newPathStr );
|
|
}
|
|
|
|
tempStrLen = ParseNdsUncPath( (LPWSTR *) &tempStr,
|
|
lpNdsParentObject->szContainerName,
|
|
PARSE_NDS_GET_PATH_NAME );
|
|
|
|
tempStrLen /= sizeof(WCHAR);
|
|
|
|
if ( tempStrLen > 0 )
|
|
{
|
|
wcscat( newPathStr, L"." );
|
|
wcsncat( newPathStr, tempStr, tempStrLen );
|
|
}
|
|
|
|
//
|
|
// Pack subtree name into output buffer.
|
|
//
|
|
status = WriteObjectToBuffer( &FixedPortion,
|
|
&EndOfVariableData,
|
|
newPathStr,
|
|
ObjectName,
|
|
ClassName,
|
|
EntryId,
|
|
ModificationTime,
|
|
SubordinateCount,
|
|
0, // No attribute
|
|
NULL ); // infos here
|
|
|
|
if ( status == NO_ERROR )
|
|
{
|
|
//
|
|
// Note that we've returned the current entry.
|
|
//
|
|
(*lpdwEntriesReturned)++;
|
|
(lpNdsBuffer->dwNumberOfIndexEntries)++;
|
|
}
|
|
|
|
if ( newPathStr )
|
|
(void) LocalFree( (HLOCAL) newPathStr );
|
|
}
|
|
|
|
if (status == WN_MORE_DATA)
|
|
{
|
|
//
|
|
// Could not write current entry into output buffer.
|
|
//
|
|
|
|
if (*lpdwEntriesReturned)
|
|
{
|
|
//
|
|
// Still return success because we got at least one.
|
|
//
|
|
status = NO_ERROR;
|
|
}
|
|
|
|
FitInBuffer = FALSE;
|
|
}
|
|
else if (status == NO_ERROR)
|
|
{
|
|
//
|
|
// Get next directory entry.
|
|
//
|
|
status = GetNextNdsSubTreeEntry( lpNdsParentObject );
|
|
}
|
|
} // end of if data to process
|
|
|
|
if (status == WN_NO_MORE_ENTRIES)
|
|
{
|
|
lpNdsParentObject->ResumeId = NDS_NO_MORE_ITERATIONS;
|
|
}
|
|
} //end of while loop
|
|
|
|
//
|
|
// User asked for more than there are entries. We just say that
|
|
// all is well.
|
|
//
|
|
// This is incompliance with the wierd provider API definition where
|
|
// if user gets NO_ERROR, and EntriesRequested > *EntriesRead, and
|
|
// at least one entry fit into output buffer, there's no telling if
|
|
// the buffer was too small for more entries or there are no more
|
|
// entries. The user has to call this API again and get WN_NO_MORE_ENTRIES
|
|
// before knowing that the last call had actually reached the end of list.
|
|
//
|
|
if ( *lpdwEntriesReturned && status == WN_NO_MORE_ENTRIES )
|
|
{
|
|
status = NO_ERROR;
|
|
}
|
|
|
|
if ( *lpdwEntriesReturned )
|
|
{
|
|
*lphOperationData = lpNdsBuffer;
|
|
}
|
|
|
|
if ( *lpdwEntriesReturned == 0 )
|
|
{
|
|
(void) NwNdsFreeBuffer( (HANDLE) lpNdsBuffer );
|
|
lpNdsBuffer = NULL;
|
|
}
|
|
|
|
if ( lpNdsParentObject->NdsRawDataBuffer &&
|
|
lpNdsParentObject->ResumeId == NDS_NO_MORE_ITERATIONS )
|
|
{
|
|
(void) LocalFree( (HLOCAL) lpNdsParentObject->NdsRawDataBuffer );
|
|
lpNdsParentObject->NdsRawDataBuffer = 0;
|
|
lpNdsParentObject->NdsRawDataSize = 0;
|
|
lpNdsParentObject->NdsRawDataId = INITIAL_ITERATION;
|
|
lpNdsParentObject->NdsRawDataCount = 0;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
DWORD
|
|
NwNdsModifyObject(
|
|
IN HANDLE hObject,
|
|
IN HANDLE hOperationData )
|
|
/*
|
|
NwNdsModifyObject()
|
|
|
|
This function is used to modify a leaf object in an NDS directory tree.
|
|
Modifying a leaf object means: changing, adding, removing, and clearing of
|
|
specified attributes for a given object.
|
|
|
|
Arguments:
|
|
|
|
HANDLE hObject - A handle to the object in the directory
|
|
tree to be manipulated. Handle is obtained by calling
|
|
NwNdsOpenObject.
|
|
|
|
HANDLE hOperationData - A handle to data containing a
|
|
list of attribute changes to be applied to the object.
|
|
This buffer is manipulated by the following functions:
|
|
NwNdsCreateBuffer (NDS_OBJECT_MODIFY),
|
|
NwNdsPutInBuffer, and NwNdsFreeBuffer.
|
|
|
|
Returns:
|
|
|
|
NO_ERROR
|
|
ERROR_INVALID_PARAMETER
|
|
UNSUCCESSFUL - Call GetLastError for Win32 error code.
|
|
*/
|
|
{
|
|
DWORD nwstatus;
|
|
NTSTATUS ntstatus = STATUS_SUCCESS;
|
|
DWORD dwReplyLength;
|
|
BYTE NdsReply[NDS_BUFFER_SIZE];
|
|
LPNDS_BUFFER lpNdsBuffer = (LPNDS_BUFFER) hOperationData;
|
|
LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hObject;
|
|
|
|
if ( lpNdsBuffer == NULL ||
|
|
lpNdsObject == NULL ||
|
|
lpNdsBuffer->dwOperation != NDS_OBJECT_MODIFY ||
|
|
lpNdsBuffer->dwBufferId != NDS_SIGNATURE ||
|
|
lpNdsObject->Signature != NDS_SIGNATURE )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
ntstatus =
|
|
FragExWithWait(
|
|
lpNdsObject->NdsTree,
|
|
NETWARE_NDS_FUNCTION_MODIFY_OBJECT,
|
|
NdsReply,
|
|
NDS_BUFFER_SIZE,
|
|
&dwReplyLength,
|
|
"DDDDr",
|
|
0, // Version
|
|
0, // Flags
|
|
lpNdsObject->ObjectId, // The id of the object
|
|
lpNdsBuffer->dwNumberOfRequestEntries,
|
|
lpNdsBuffer->lpRequestBuffer, // Object attribute changes
|
|
(WORD)lpNdsBuffer->dwLengthOfRequestData // Length of data
|
|
);
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsModifyObject: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
ntstatus = ParseResponse( NdsReply,
|
|
dwReplyLength,
|
|
"GD",
|
|
&nwstatus );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsModifyObject: The modify object response was undecipherable.\n" ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
SetLastError( MapNetwareErrorCode( nwstatus ) );
|
|
return nwstatus;
|
|
}
|
|
|
|
|
|
DWORD
|
|
NwNdsMoveObject(
|
|
IN HANDLE hObject,
|
|
IN LPWSTR szDestObjectParentDN )
|
|
/*
|
|
NwNdsMoveObject()
|
|
|
|
This function is used to move a leaf object in an NDS directory tree
|
|
from one container to another.
|
|
|
|
Arguments:
|
|
|
|
HANDLE hObject - A handle to the object in the directory
|
|
tree to be moved. Handle is obtained by calling
|
|
NwNdsOpenObject.
|
|
|
|
LPWSTR szDestObjectParentDN - The DN of the object's new
|
|
parent.
|
|
|
|
Returns:
|
|
|
|
NO_ERROR
|
|
UNSUCCESSFUL - Call GetLastError for Win32 error code.
|
|
*/
|
|
{
|
|
DWORD nwstatus;
|
|
DWORD status = NO_ERROR;
|
|
NTSTATUS ntstatus = STATUS_SUCCESS;
|
|
DWORD dwReplyLength;
|
|
BYTE NdsReply[NDS_BUFFER_SIZE];
|
|
LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hObject;
|
|
LPNDS_OBJECT_PRIV lpNdsDestParentObject = NULL;
|
|
WCHAR szServerDN[NDS_MAX_NAME_CHARS];
|
|
UNICODE_STRING ObjectName;
|
|
UNICODE_STRING ServerDN;
|
|
DWORD dwDestParentObjectId;
|
|
|
|
if ( szDestObjectParentDN == NULL ||
|
|
lpNdsObject == NULL ||
|
|
lpNdsObject->Signature != NDS_SIGNATURE )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
RtlZeroMemory( &szServerDN[0], sizeof( szServerDN ) );
|
|
|
|
status = NwNdsGetServerDN( lpNdsObject, szServerDN );
|
|
|
|
if ( status )
|
|
{
|
|
return status;
|
|
}
|
|
|
|
status = NwNdsOpenObject( szDestObjectParentDN,
|
|
NULL,
|
|
NULL,
|
|
(HANDLE *) &lpNdsDestParentObject,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL );
|
|
|
|
if ( status )
|
|
{
|
|
return status;
|
|
}
|
|
|
|
dwDestParentObjectId = lpNdsDestParentObject->ObjectId;
|
|
|
|
(void) NwNdsCloseObject( (HANDLE) lpNdsDestParentObject );
|
|
|
|
RtlInitUnicodeString( &ObjectName, lpNdsObject->szRelativeName );
|
|
RtlInitUnicodeString( &ServerDN, szServerDN );
|
|
|
|
ntstatus =
|
|
FragExWithWait( lpNdsObject->NdsTree,
|
|
NETWARE_NDS_FUNCTION_BEGIN_MOVE_OBJECT,
|
|
NdsReply,
|
|
NDS_BUFFER_SIZE,
|
|
&dwReplyLength,
|
|
"DDDSS",
|
|
0, // Version
|
|
0x00000000, // Some value
|
|
dwDestParentObjectId,
|
|
&ObjectName,
|
|
&ServerDN
|
|
);
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsMoveObject: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
ntstatus = ParseResponse( NdsReply,
|
|
dwReplyLength,
|
|
"GD",
|
|
&nwstatus );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsMoveObject: The status code response was undecipherable.\n" ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
if ( nwstatus )
|
|
{
|
|
SetLastError( MapNetwareErrorCode( nwstatus ) );
|
|
return nwstatus;
|
|
}
|
|
|
|
ntstatus =
|
|
FragExWithWait( lpNdsObject->NdsTree,
|
|
NETWARE_NDS_FUNCTION_FINISH_MOVE_OBJECT,
|
|
NdsReply,
|
|
NDS_BUFFER_SIZE,
|
|
&dwReplyLength,
|
|
"DDDDSS",
|
|
0, // Version
|
|
0x00000001, // Some value
|
|
lpNdsObject->ObjectId,
|
|
dwDestParentObjectId,
|
|
&ObjectName,
|
|
&ServerDN
|
|
);
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsMoveObject: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
ntstatus = ParseResponse( NdsReply,
|
|
dwReplyLength,
|
|
"GD",
|
|
&nwstatus );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsMoveObject: The status code response was undecipherable.\n" ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
if ( nwstatus )
|
|
{
|
|
SetLastError( MapNetwareErrorCode( nwstatus ) );
|
|
return nwstatus;
|
|
}
|
|
|
|
return nwstatus;
|
|
}
|
|
|
|
|
|
DWORD
|
|
NwNdsOpenObject(
|
|
IN LPWSTR szObjectDN,
|
|
IN LPWSTR UserName OPTIONAL,
|
|
IN LPWSTR Password OPTIONAL,
|
|
OUT HANDLE * lphObject,
|
|
OUT LPWSTR szObjectName OPTIONAL,
|
|
OUT LPWSTR szObjectFullName OPTIONAL,
|
|
OUT LPWSTR szObjectClassName OPTIONAL,
|
|
OUT LPDWORD lpdwModificationTime OPTIONAL,
|
|
OUT LPDWORD lpdwSubordinateCount OPTIONAL )
|
|
/*
|
|
NwNdsOpenObject()
|
|
|
|
Arguments:
|
|
|
|
LPWSTR szObjectDN - The distinguished name of the object
|
|
that we want resolved into an object handle.
|
|
|
|
LPWSTR UserName - The name of the user account to create
|
|
connection to object with.
|
|
- OR -
|
|
NULL to use the base credentials of the callee's LUID.
|
|
|
|
LPWSTR Password - The password of the user account to create
|
|
connection to object with. If password is blank, callee
|
|
should pass "".
|
|
- OR -
|
|
NULL to use the base credentials of the callee's LUID.
|
|
|
|
HANDLE * lphObject - The address of a NDS_OBJECT_HANDLE
|
|
to receive the handle of the object specified by
|
|
szObjectDN.
|
|
|
|
Optional arguments: ( Callee can pass NULL in for these parameters to
|
|
indicate ignore )
|
|
|
|
LPWSTR szObjectName - A LPWSTR buffer to receive
|
|
the object's NDS name, or NULL if not
|
|
interested. The buffer for this string must be
|
|
provided by the user. Buffer should be at least
|
|
NDS_MAX_NAME_SIZE
|
|
|
|
LPWSTR szObjectFullName - A LPWSTR buffer to receive
|
|
the object's full NDS name (DN), or NULL if not
|
|
interested. The buffer for this string must be
|
|
provided by the user. Buffer should be at least
|
|
NDS_MAX_NAME_SIZE
|
|
|
|
LPWSTR szObjectClassName - A LPWSTR buffer to receive
|
|
the class name of the object opened, or NULL if not
|
|
interested. The buffer for this string must be
|
|
provided by the user. Buffer should be at least
|
|
NDS_MAX_NAME_SIZE.
|
|
|
|
LPDWORD lpdwModificationTime - The address of a DWORD to
|
|
receive the last date/time the object was modified.
|
|
|
|
LPDWORD lpdwSubordinateCount - The address of a DWORD to
|
|
receive the number of subordinate objects that may
|
|
be found under szObjectDN, if it is a container object.
|
|
Or, NULL in not interested.
|
|
|
|
If szObjectDN is not a container, then the value is set
|
|
to zero. Although a value of zero does not imply
|
|
that object is not a container, it could just be empty.
|
|
|
|
Returns:
|
|
|
|
NO_ERROR
|
|
UNSUCCESSFUL - Call GetLastError for Win32 error code.
|
|
*/
|
|
{
|
|
DWORD status = NO_ERROR;
|
|
NTSTATUS ntstatus = STATUS_SUCCESS;
|
|
WCHAR szServerName[NW_MAX_SERVER_LEN];
|
|
UNICODE_STRING ServerName;
|
|
UNICODE_STRING ObjectName;
|
|
LPNDS_OBJECT_PRIV lpNdsObject = NULL;
|
|
#ifdef WIN95
|
|
LPWSTR pszObjectName = NULL;
|
|
LPWSTR szWin95ClassName = NULL;
|
|
#endif
|
|
if ( szObjectDN == NULL )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
lpNdsObject = (LPNDS_OBJECT_PRIV) LocalAlloc( LPTR,
|
|
sizeof(NDS_OBJECT_PRIV) );
|
|
|
|
if (lpNdsObject == NULL) {
|
|
#if DBG
|
|
KdPrint(("NDS32: NwNdsOpenObject LocalAlloc Failed 0x%.8X\n", GetLastError()));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
ServerName.Length = 0;
|
|
ServerName.MaximumLength = sizeof(szServerName);
|
|
ServerName.Buffer = szServerName;
|
|
|
|
ObjectName.Buffer = NULL;
|
|
|
|
ObjectName.MaximumLength = (wcslen( szObjectDN ) + 1) * sizeof(WCHAR);
|
|
|
|
ObjectName.Length = ParseNdsUncPath( (LPWSTR *) &ObjectName.Buffer,
|
|
szObjectDN,
|
|
PARSE_NDS_GET_TREE_NAME );
|
|
|
|
if ( ObjectName.Length == 0 || ObjectName.Buffer == NULL )
|
|
{
|
|
SetLastError( ERROR_PATH_NOT_FOUND );
|
|
goto ErrorExit;
|
|
}
|
|
|
|
if ( ObjectName.Length > NDS_MAX_NAME_SIZE ) {
|
|
SetLastError( ERROR_PATH_NOT_FOUND );
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Open a NDS tree connection handle to \\treename
|
|
//
|
|
if ( UserName && Password )
|
|
{
|
|
UNICODE_STRING usUserName;
|
|
UNICODE_STRING usPassword;
|
|
DWORD dwHandleType;
|
|
|
|
RtlInitUnicodeString( &usUserName, UserName );
|
|
RtlInitUnicodeString( &usPassword, Password );
|
|
|
|
ntstatus = NwOpenHandleWithSupplementalCredentials(
|
|
&ObjectName,
|
|
&usUserName,
|
|
&usPassword,
|
|
&dwHandleType,
|
|
&lpNdsObject->NdsTree );
|
|
|
|
if ( ntstatus == STATUS_SUCCESS &&
|
|
dwHandleType != HANDLE_TYPE_NDS_TREE )
|
|
{
|
|
SetLastError( ERROR_PATH_NOT_FOUND );
|
|
goto ErrorExit;
|
|
}
|
|
}
|
|
else if ( !UserName && !Password )
|
|
{
|
|
ntstatus = NwNdsOpenTreeHandle( &ObjectName, &lpNdsObject->NdsTree );
|
|
}
|
|
else
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
goto ErrorExit;
|
|
}
|
|
|
|
if ( ntstatus != STATUS_SUCCESS )
|
|
{
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
goto ErrorExit;
|
|
}
|
|
|
|
ObjectName.Length /= sizeof(WCHAR);
|
|
|
|
wcscpy( lpNdsObject->szContainerName, L"\\\\" );
|
|
wcsncat( lpNdsObject->szContainerName, ObjectName.Buffer, ObjectName.Length );
|
|
wcscat( lpNdsObject->szContainerName, L"\\" );
|
|
_wcsupr( lpNdsObject->szContainerName );
|
|
|
|
//
|
|
// Get the path to the container to open.
|
|
//
|
|
ObjectName.Length = ParseNdsUncPath( (LPWSTR *) &ObjectName.Buffer,
|
|
szObjectDN,
|
|
PARSE_NDS_GET_PATH_NAME );
|
|
|
|
if ( ObjectName.Length == 0 )
|
|
{
|
|
UNICODE_STRING Root;
|
|
|
|
RtlInitUnicodeString(&Root, L"[Root]");
|
|
|
|
//
|
|
// Resolve the path to get a NDS object id of [Root].
|
|
//
|
|
#ifndef WIN95
|
|
ntstatus = NwNdsResolveName( lpNdsObject->NdsTree,
|
|
&Root,
|
|
&lpNdsObject->ObjectId,
|
|
&ServerName,
|
|
NULL,
|
|
0 );
|
|
#else
|
|
ntstatus = NwNdsResolveNameWin95( lpNdsObject->NdsTree,
|
|
&Root,
|
|
&lpNdsObject->ObjectId,
|
|
&lpNdsObject->NdsTree,
|
|
NULL,
|
|
0 );
|
|
#endif
|
|
if ( ntstatus != STATUS_SUCCESS )
|
|
{
|
|
status = RtlNtStatusToDosError( ntstatus );
|
|
|
|
if ( status == ERROR_NOT_CONNECTED )
|
|
SetLastError( ERROR_PATH_NOT_FOUND );
|
|
else
|
|
SetLastError( status );
|
|
goto ErrorExit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Resolve the path to get a NDS object id.
|
|
//
|
|
#ifndef WIN95
|
|
ntstatus = NwNdsResolveName( lpNdsObject->NdsTree,
|
|
&ObjectName,
|
|
&lpNdsObject->ObjectId,
|
|
&ServerName,
|
|
NULL,
|
|
0 );
|
|
#else
|
|
|
|
ntstatus = NwNdsResolveNameWin95( lpNdsObject->NdsTree,
|
|
&ObjectName,
|
|
&lpNdsObject->ObjectId,
|
|
&lpNdsObject->NdsTree,
|
|
NULL,
|
|
0 );
|
|
#endif
|
|
|
|
if ( ntstatus != STATUS_SUCCESS )
|
|
{
|
|
status = RtlNtStatusToDosError( ntstatus );
|
|
|
|
if ( status == ERROR_NOT_CONNECTED )
|
|
SetLastError( ERROR_PATH_NOT_FOUND );
|
|
else
|
|
SetLastError( status );
|
|
goto ErrorExit;
|
|
}
|
|
}
|
|
|
|
#ifndef WIN95
|
|
if ( ServerName.Length )
|
|
{
|
|
DWORD dwHandleType;
|
|
|
|
//
|
|
// NwNdsResolveName succeeded, but we were referred to
|
|
// another server, though lpNdsObject->ObjectId is still valid.
|
|
//
|
|
if ( lpNdsObject->NdsTree )
|
|
CloseHandle( lpNdsObject->NdsTree );
|
|
|
|
lpNdsObject->NdsTree = 0;
|
|
|
|
//
|
|
// Open a NDS generic connection handle to \\ServerName
|
|
//
|
|
ntstatus = NwNdsOpenGenericHandle( &ServerName,
|
|
&dwHandleType,
|
|
&lpNdsObject->NdsTree );
|
|
|
|
if ( ntstatus != STATUS_SUCCESS )
|
|
{
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
goto ErrorExit;
|
|
}
|
|
}
|
|
{
|
|
PBYTE RawResponse = NULL;
|
|
PNDS_RESPONSE_GET_OBJECT_INFO psGetInfo;
|
|
PBYTE pbRawGetInfo;
|
|
LPWSTR szClassName;
|
|
DWORD dwStrLen;
|
|
|
|
RawResponse = LocalAlloc( LPTR, TWO_KB );
|
|
|
|
if ( ! RawResponse )
|
|
{
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
ntstatus = NwNdsReadObjectInfo( lpNdsObject->NdsTree,
|
|
lpNdsObject->ObjectId,
|
|
RawResponse,
|
|
TWO_KB );
|
|
|
|
if ( ntstatus != STATUS_SUCCESS )
|
|
{
|
|
LocalFree( RawResponse );
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
goto ErrorExit;
|
|
}
|
|
|
|
psGetInfo = ( PNDS_RESPONSE_GET_OBJECT_INFO ) RawResponse;
|
|
|
|
if ( lpdwModificationTime != NULL )
|
|
{
|
|
*lpdwModificationTime = psGetInfo->ModificationTime;
|
|
}
|
|
|
|
if ( lpdwSubordinateCount != NULL )
|
|
{
|
|
*lpdwSubordinateCount = psGetInfo->SubordinateCount;
|
|
}
|
|
|
|
//
|
|
// Dig out the two unicode strings for class name and object name.
|
|
//
|
|
|
|
pbRawGetInfo = RawResponse;
|
|
|
|
pbRawGetInfo += sizeof (NDS_RESPONSE_GET_OBJECT_INFO);
|
|
|
|
dwStrLen = * (LPDWORD) pbRawGetInfo;
|
|
pbRawGetInfo += sizeof(DWORD);
|
|
szClassName = (LPWSTR) pbRawGetInfo;
|
|
|
|
if ( szObjectClassName != NULL )
|
|
{
|
|
wcsncpy( szObjectClassName, szClassName, NDS_MAX_NAME_CHARS );
|
|
}
|
|
|
|
pbRawGetInfo += ROUNDUP4( dwStrLen );
|
|
dwStrLen = * ( DWORD * ) pbRawGetInfo;
|
|
pbRawGetInfo += sizeof(DWORD);
|
|
|
|
//
|
|
// Clean up the object's relative name ...
|
|
//
|
|
if ( wcscmp( szClassName, NDS_CLASS_TOP ) )
|
|
{
|
|
LPWSTR szTempStr = (LPWSTR) pbRawGetInfo;
|
|
|
|
while ( *szTempStr != L'=' )
|
|
{
|
|
szTempStr++;
|
|
}
|
|
|
|
szTempStr++;
|
|
|
|
wcsncpy( lpNdsObject->szRelativeName, szTempStr, NDS_MAX_NAME_CHARS );
|
|
lpNdsObject->szRelativeName[NDS_MAX_NAME_CHARS - 1] = (WCHAR)'\0';
|
|
|
|
szTempStr = lpNdsObject->szRelativeName;
|
|
|
|
while ( *szTempStr && *szTempStr != L'.' )
|
|
{
|
|
szTempStr++;
|
|
}
|
|
|
|
*szTempStr = L'\0';
|
|
}
|
|
else
|
|
{
|
|
wcsncpy( lpNdsObject->szRelativeName, (LPWSTR) pbRawGetInfo, NDS_MAX_NAME_CHARS );
|
|
lpNdsObject->szRelativeName[NDS_MAX_NAME_CHARS - 1] = (WCHAR)'\0';
|
|
}
|
|
|
|
if ( szObjectName != NULL )
|
|
{
|
|
wcscpy( szObjectName, lpNdsObject->szRelativeName );
|
|
}
|
|
|
|
if ( szObjectFullName != NULL )
|
|
{
|
|
if ( wcscmp( szClassName, NDS_CLASS_TOP ) )
|
|
{
|
|
wcsncpy( szObjectFullName, lpNdsObject->szContainerName, NDS_MAX_NAME_CHARS );
|
|
szObjectFullName[NDS_MAX_NAME_CHARS - 1] = (WCHAR)'\0';
|
|
wcsncat( szObjectFullName, (LPWSTR) pbRawGetInfo,
|
|
NDS_MAX_NAME_CHARS - wcslen( szObjectFullName ) );
|
|
szObjectFullName[NDS_MAX_NAME_CHARS - 1] = (WCHAR)'\0';
|
|
}
|
|
else
|
|
{
|
|
wcsncpy( szObjectFullName,
|
|
lpNdsObject->szContainerName,
|
|
NDS_MAX_NAME_CHARS );
|
|
szObjectFullName[NDS_MAX_NAME_CHARS - 1] = (WCHAR)'\0';
|
|
|
|
// Remove trailing slash
|
|
if ( szObjectFullName[wcslen( szObjectFullName ) - 1] == '\\' )
|
|
szObjectFullName[wcslen( szObjectFullName ) - 1] = L'\0';
|
|
}
|
|
}
|
|
|
|
//
|
|
// If the object is at a level below the root of the tree, append
|
|
// it's full DN to handle Name.
|
|
//
|
|
if ( wcscmp( szClassName, NDS_CLASS_TOP ) )
|
|
{
|
|
if ( ( wcslen(lpNdsObject->szContainerName) +
|
|
wcslen((LPWSTR) pbRawGetInfo) ) <
|
|
( sizeof(lpNdsObject->szContainerName) / sizeof(WCHAR)) )
|
|
{
|
|
wcscat(lpNdsObject->szContainerName, (LPWSTR) pbRawGetInfo);
|
|
}
|
|
else
|
|
{
|
|
LocalFree( RawResponse );
|
|
SetLastError( ERROR_PATH_NOT_FOUND );
|
|
goto ErrorExit;
|
|
}
|
|
}
|
|
|
|
if ( RawResponse )
|
|
LocalFree( RawResponse );
|
|
}
|
|
|
|
lpNdsObject->Signature = NDS_SIGNATURE;
|
|
|
|
//
|
|
// Initialize ListSubObject/Search structure values.
|
|
//
|
|
// lpNdsObject->ResumeId = 0; // Start of enumeration
|
|
//
|
|
// lpNdsObject->NdsRawDataBuffer = 0;
|
|
// lpNdsObject->NdsRawDataSize = 0;
|
|
// lpNdsObject->NdsRawDataId = 0; // These are initialized by
|
|
// lpNdsObject->NdsRawDataCount = 0; // LPTR
|
|
|
|
//
|
|
// Return the newly created object handle.
|
|
//
|
|
*lphObject = (HANDLE) lpNdsObject;
|
|
|
|
return NO_ERROR;
|
|
|
|
#else
|
|
{
|
|
DS_OBJ_INFO dsobj;
|
|
DWORD dwStrLen;
|
|
NW_STATUS nwstatus;
|
|
|
|
memset(&dsobj, 0, sizeof(DS_OBJ_INFO));
|
|
|
|
nwstatus = NDSGetObjectInfoWithId(lpNdsObject->NdsTree,
|
|
lpNdsObject->ObjectId,
|
|
&dsobj );
|
|
|
|
ntstatus = MapNwToNtStatus(nwstatus);
|
|
if ( ntstatus != STATUS_SUCCESS )
|
|
{
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
goto ErrorExit;
|
|
}
|
|
|
|
if ( lpdwSubordinateCount != NULL )
|
|
{
|
|
*lpdwSubordinateCount = dsobj.subordinateCount;
|
|
}
|
|
|
|
if (!(szWin95ClassName = AllocateUnicodeString(dsobj.className))) {
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
if ( szObjectClassName != NULL )
|
|
{
|
|
wcscpy( szObjectClassName, szWin95ClassName);
|
|
}
|
|
|
|
if (!(pszObjectName = AllocateUnicodeString(dsobj.objectName))) {
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Clean up the object's relative name ...
|
|
//
|
|
if ( wcscmp( szWin95ClassName, NDS_CLASS_TOP ) )
|
|
{
|
|
LPWSTR szTempStr = pszObjectName;
|
|
|
|
while ( *szTempStr != L'=' )
|
|
{
|
|
szTempStr++;
|
|
}
|
|
|
|
szTempStr++;
|
|
|
|
wcscpy( lpNdsObject->szRelativeName, szTempStr );
|
|
|
|
szTempStr = lpNdsObject->szRelativeName;
|
|
|
|
while ( *szTempStr && *szTempStr != L'.' )
|
|
{
|
|
szTempStr++;
|
|
}
|
|
|
|
*szTempStr = L'\0';
|
|
}
|
|
else
|
|
{
|
|
wcscpy( lpNdsObject->szRelativeName, pszObjectName );
|
|
}
|
|
|
|
if ( szObjectName != NULL )
|
|
{
|
|
wcscpy( szObjectName, lpNdsObject->szRelativeName );
|
|
}
|
|
|
|
if ( szObjectFullName != NULL )
|
|
{
|
|
if ( wcscmp( szWin95ClassName, NDS_CLASS_TOP ) )
|
|
{
|
|
wcscpy( szObjectFullName, lpNdsObject->szContainerName );
|
|
wcscat( szObjectFullName, pszObjectName );
|
|
}
|
|
else
|
|
{
|
|
wcscpy( szObjectFullName,
|
|
lpNdsObject->szContainerName );
|
|
|
|
szObjectFullName[wcslen( szObjectFullName ) - 1] = L'\0';
|
|
}
|
|
}
|
|
|
|
//
|
|
// If the object is at a level below the root of the tree, append
|
|
// it full DN to handle Name.
|
|
//
|
|
if ( wcscmp( szWin95ClassName, NDS_CLASS_TOP ) )
|
|
{
|
|
wcscat(lpNdsObject->szContainerName, pszObjectName);
|
|
}
|
|
if(szWin95ClassName){
|
|
FreeUnicodeString(szWin95ClassName);
|
|
}
|
|
if(pszObjectName){
|
|
FreeUnicodeString(pszObjectName);
|
|
}
|
|
}
|
|
|
|
lpNdsObject->Signature = NDS_SIGNATURE;
|
|
*lphObject = (HANDLE) lpNdsObject;
|
|
|
|
return NO_ERROR;
|
|
#endif
|
|
|
|
|
|
ErrorExit:
|
|
|
|
if ( lpNdsObject )
|
|
{
|
|
#ifndef WIN95
|
|
// There is no ref count in Win95, the connection will time out itself
|
|
if ( lpNdsObject->NdsTree )
|
|
CloseHandle( lpNdsObject->NdsTree );
|
|
#endif
|
|
(void) LocalFree( (HLOCAL) lpNdsObject );
|
|
}
|
|
|
|
#ifdef WIN95
|
|
if(szWin95ClassName)
|
|
{
|
|
FreeUnicodeString(szWin95ClassName);
|
|
}
|
|
|
|
if(pszObjectName)
|
|
{
|
|
FreeUnicodeString(pszObjectName);
|
|
}
|
|
#endif
|
|
|
|
*lphObject = NULL;
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
|
|
DWORD
|
|
NwNdsPutInBuffer(
|
|
IN LPWSTR szAttributeName,
|
|
IN DWORD dwSyntaxID,
|
|
IN LPVOID lpAttributeValues,
|
|
IN DWORD dwValueCount,
|
|
IN DWORD dwAttrModificationOperation,
|
|
IN OUT HANDLE hOperationData )
|
|
/*
|
|
NwNdsPutInBuffer()
|
|
|
|
This function is used to add an entry to the buffer used to describe
|
|
an object attribute or change to an object attribute. The buffer must
|
|
be created using NwNdsCreateBuffer. If the buffer was created using the
|
|
operations, NDS_OBJECT_ADD, NDS_SCHEMA_DEFINE_CLASS,
|
|
NDS_SCHEMA_READ_ATTR_DEF, or NDS_SCHEMA_READ_CLASS_DEF, then
|
|
dwAttrModificationOperation is ignored. If the buffer was created using
|
|
either the operation NDS_OBJECT_READ or NDS_SEARCH, then
|
|
dwAttrModificationOperation, puAttributeType, and lpAttributeValue are
|
|
all ingnored.
|
|
|
|
Arguments:
|
|
|
|
LPWSTR szAttributeName - A NULL terminated WCHAR string
|
|
that contains name of the attribute value to be
|
|
added to the buffer. It can be a user supplied
|
|
string, or one of the many defined string macros
|
|
in ndsnames.h.
|
|
|
|
DWORD dwSyntaxID - The ID of the syntax structure used to
|
|
represent the attribute value. Syntax IDs and their
|
|
associated structures are defined in the file
|
|
NdsSntx.h. According to the NetWare NDS schema spec,
|
|
there is and always will be, only 28 (0..27)
|
|
different syntaxes.
|
|
|
|
LPVOID lpAttributeValues - A pointer to the beginning of a
|
|
buffer containing the value(s) for a particular
|
|
object attribute with data syntax dwSyntaxID.
|
|
|
|
DWORD dwValueCount - The number of value entries found in
|
|
buffer pointed to by lpAttributeValues.
|
|
|
|
DWORD dwAttrModificationOperation - If the buffer was created
|
|
using the operation NDS_MODIFY_OBJECT, then this is
|
|
used to desribe which type of modification operation
|
|
to apply for a given attribute. These attribute
|
|
modification operations are defined near the beginning
|
|
of this file.
|
|
|
|
HANDLE hOperationData - A handle to data created by
|
|
calling NwNdsCreateBuffer. The buffer stores the
|
|
attributes used to define transactions for
|
|
NwNdsAddObject, NwNdsModifyObject, NwNdsReadObject,
|
|
NwNdsReadAttrDef, NwNdsReadClassDef, or NwNdsSearch.
|
|
|
|
Returns:
|
|
|
|
NO_ERROR
|
|
ERROR_NOT_ENOUGH_MEMORY
|
|
ERROR_INVALID_PARAMETER
|
|
*/
|
|
{
|
|
LPNDS_BUFFER lpNdsBuffer = (LPNDS_BUFFER) hOperationData;
|
|
DWORD LengthInBytes;
|
|
LPBYTE lpTempEntry = NULL;
|
|
UNICODE_STRING AttributeName;
|
|
DWORD bufferSize = TWO_KB;
|
|
|
|
if ( lpNdsBuffer == NULL ||
|
|
szAttributeName == NULL ||
|
|
lpNdsBuffer->dwBufferId != NDS_SIGNATURE )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
RtlInitUnicodeString( &AttributeName, szAttributeName );
|
|
|
|
//
|
|
// Check to see if the buffer was already used by a read operation.
|
|
//
|
|
if ( lpNdsBuffer->lpReplyBuffer )
|
|
{
|
|
SetLastError( ERROR_ACCESS_DENIED );
|
|
return NDS_ERR_NO_ACCESS;
|
|
}
|
|
|
|
if ( lpNdsBuffer->dwOperation == NDS_OBJECT_MODIFY )
|
|
{
|
|
switch( dwAttrModificationOperation )
|
|
{
|
|
case NDS_ATTR_ADD:
|
|
case NDS_ATTR_REMOVE:
|
|
case NDS_ATTR_ADD_VALUE:
|
|
case NDS_ATTR_REMOVE_VALUE:
|
|
case NDS_ATTR_ADDITIONAL_VALUE:
|
|
case NDS_ATTR_OVERWRITE_VALUE:
|
|
case NDS_ATTR_CLEAR:
|
|
case NDS_ATTR_CLEAR_VALUE:
|
|
break;
|
|
|
|
default:
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsPutInBuffer was passed an unidentified modification operation.\n" ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
}
|
|
|
|
if ( lpNdsBuffer->dwOperation == NDS_OBJECT_ADD ||
|
|
lpNdsBuffer->dwOperation == NDS_OBJECT_MODIFY )
|
|
{
|
|
bufferSize += CalculateValueDataSize ( dwSyntaxID,
|
|
lpAttributeValues,
|
|
dwValueCount );
|
|
}
|
|
|
|
lpTempEntry = LocalAlloc( LPTR, bufferSize );
|
|
|
|
if ( ! lpTempEntry )
|
|
{
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
switch ( lpNdsBuffer->dwOperation )
|
|
{
|
|
case NDS_OBJECT_ADD:
|
|
PrepareAddEntry( lpTempEntry,
|
|
AttributeName,
|
|
dwSyntaxID,
|
|
lpAttributeValues,
|
|
dwValueCount,
|
|
&LengthInBytes );
|
|
break;
|
|
|
|
case NDS_OBJECT_MODIFY:
|
|
PrepareModifyEntry( lpTempEntry,
|
|
AttributeName,
|
|
dwSyntaxID,
|
|
dwAttrModificationOperation,
|
|
lpAttributeValues,
|
|
dwValueCount,
|
|
&LengthInBytes );
|
|
break;
|
|
|
|
case NDS_OBJECT_READ:
|
|
case NDS_SCHEMA_DEFINE_CLASS:
|
|
case NDS_SCHEMA_READ_ATTR_DEF:
|
|
case NDS_SCHEMA_READ_CLASS_DEF:
|
|
case NDS_SEARCH:
|
|
//
|
|
// Check to see if this buffer has already been used. If so,
|
|
// return with error.
|
|
//
|
|
if ( lpNdsBuffer->lpReplyBuffer )
|
|
{
|
|
if ( lpTempEntry )
|
|
LocalFree( lpTempEntry );
|
|
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
PrepareReadEntry( lpTempEntry,
|
|
AttributeName,
|
|
&LengthInBytes );
|
|
break;
|
|
|
|
default:
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsPutInBuffer has unknown buffer operation!\n" ));
|
|
#endif
|
|
|
|
if ( lpTempEntry )
|
|
LocalFree( lpTempEntry );
|
|
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
if ( lpNdsBuffer->dwRequestAvailableBytes >= LengthInBytes )
|
|
{
|
|
//
|
|
// Copy temporary buffer entry into buffer and update buffer header.
|
|
//
|
|
|
|
RtlCopyMemory( (LPBYTE)&lpNdsBuffer->lpRequestBuffer[lpNdsBuffer->dwLengthOfRequestData],
|
|
lpTempEntry,
|
|
LengthInBytes );
|
|
|
|
lpNdsBuffer->dwRequestAvailableBytes -= LengthInBytes;
|
|
lpNdsBuffer->dwNumberOfRequestEntries += 1;
|
|
lpNdsBuffer->dwLengthOfRequestData += LengthInBytes;
|
|
}
|
|
else
|
|
{
|
|
LPBYTE lpNewBuffer = NULL;
|
|
|
|
//
|
|
// Need to reallocate buffer to a bigger size.
|
|
//
|
|
lpNewBuffer = (LPBYTE) LocalAlloc(
|
|
LPTR,
|
|
lpNdsBuffer->dwRequestBufferSize +
|
|
LengthInBytes +
|
|
TWO_KB );
|
|
|
|
if ( lpNewBuffer == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsPutInBuffer LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
if ( lpTempEntry )
|
|
LocalFree( lpTempEntry );
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
RtlCopyMemory( lpNewBuffer,
|
|
lpNdsBuffer->lpRequestBuffer,
|
|
lpNdsBuffer->dwLengthOfRequestData );
|
|
|
|
LocalFree( (HLOCAL) lpNdsBuffer->lpRequestBuffer );
|
|
lpNdsBuffer->lpRequestBuffer = lpNewBuffer;
|
|
lpNdsBuffer->dwRequestBufferSize += LengthInBytes + TWO_KB;
|
|
lpNdsBuffer->dwRequestAvailableBytes += LengthInBytes + TWO_KB;
|
|
|
|
//
|
|
// Copy temporary buffer entry into the resized buffer and
|
|
// update buffer header.
|
|
//
|
|
|
|
RtlCopyMemory( (LPBYTE)&lpNdsBuffer->lpRequestBuffer[lpNdsBuffer->dwLengthOfRequestData],
|
|
lpTempEntry,
|
|
LengthInBytes );
|
|
|
|
lpNdsBuffer->dwRequestAvailableBytes -= LengthInBytes;
|
|
lpNdsBuffer->dwNumberOfRequestEntries += 1;
|
|
lpNdsBuffer->dwLengthOfRequestData += LengthInBytes;
|
|
}
|
|
|
|
if ( lpTempEntry )
|
|
LocalFree( lpTempEntry );
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
DWORD
|
|
NwNdsReadAttrDef(
|
|
IN HANDLE hTree,
|
|
IN DWORD dwInformationType, // NDS_INFO_NAMES
|
|
// or NDS_INFO_NAMES_DEFS
|
|
IN OUT HANDLE * lphOperationData OPTIONAL )
|
|
/*
|
|
NwNdsReadAttrDef()
|
|
|
|
This function is used to read attribute definitions in the schema of an
|
|
NDS directory tree.
|
|
|
|
Arguments:
|
|
|
|
HANDLE hTree - A handle to the directory tree to be
|
|
manipulated. Handle is obtained by calling
|
|
NwNdsOpenObject.
|
|
|
|
DWORD dwInformationType - Indicates whether user chooses to
|
|
read only the defined attribute name(s) in the schema or
|
|
read both the attribute name(s) and definition(s)
|
|
from the schema.
|
|
|
|
HANDLE * lphOperationData - The address of a HANDLE to data
|
|
containing a list of attribute names to be read from
|
|
the schema. This handle is manipulated by the following
|
|
functions:
|
|
NwNdsCreateBuffer (NDS_SCHEMA_READ_ATTR_DEF),
|
|
NwNdsPutInBuffer, and NwNdsFreeBuffer.
|
|
|
|
- OR -
|
|
|
|
The address of a HANDLE set to NULL, which indicates
|
|
that all attributes should be read from the schema.
|
|
|
|
If these calls are successful, this handle will also
|
|
contain the read results from the call. In the later
|
|
case, a buffer will be created to contain the read
|
|
results. Attribute values can be retrieved from the
|
|
buffer with the functions:
|
|
NwNdsGetAttrDefListFromBuffer.
|
|
|
|
After the call to this function, this buffer is ONLY
|
|
manipulated by the functions:
|
|
NwNdsGetAttrDefListFromBuffer and NwNdsFreeBuffer.
|
|
|
|
Returns:
|
|
|
|
NO_ERROR
|
|
UNSUCCESSFUL - Call GetLastError for Win32 error code.
|
|
*/
|
|
{
|
|
if ( hTree == NULL ||
|
|
((LPNDS_OBJECT_PRIV) hTree)->Signature != NDS_SIGNATURE )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
if ( *lphOperationData == NULL ) // If TRUE, we need to read all attr defs
|
|
return ReadAttrDef_AllAttrs( hTree,
|
|
dwInformationType,
|
|
lphOperationData );
|
|
else // Else, we read the attr definitions specified in lphOperationData
|
|
return ReadAttrDef_SomeAttrs( hTree,
|
|
dwInformationType,
|
|
lphOperationData );
|
|
}
|
|
|
|
|
|
DWORD
|
|
NwNdsReadClassDef(
|
|
IN HANDLE hTree,
|
|
IN DWORD dwInformationType, // NDS_INFO_NAMES,
|
|
// NDS_INFO_NAMES_DEFS,
|
|
// NDS_CLASS_INFO_EXPANDED_DEFS,
|
|
// or NDS_CLASS_INFO
|
|
IN OUT HANDLE * lphOperationData OPTIONAL )
|
|
/*
|
|
NwNdsReadClassDef()
|
|
|
|
This function is used to read class definitions in the schema of an
|
|
NDS directory tree.
|
|
|
|
Arguments:
|
|
|
|
HANDLE hTree - A handle to the directory tree to be
|
|
manipulated. Handle is obtained by calling
|
|
NwNdsOpenObject.
|
|
|
|
DWORD dwInformationType - Indicates whether user chooses to
|
|
read only the defined class name(s) in the schema or
|
|
read both the class name(s) and definition(s)
|
|
from the schema.
|
|
|
|
HANDLE * lphOperationData - The address of a HANDLE to data
|
|
containing a list of class names to be read from
|
|
the schema. This handle is manipulated by the following
|
|
functions:
|
|
NwNdsCreateBuffer (NDS_SCHEMA_READ_CLASS_DEF),
|
|
NwNdsPutInBuffer, and NwNdsFreeBuffer.
|
|
|
|
- OR -
|
|
|
|
The address of a HANDLE set to NULL, which indicates
|
|
that all classes should be read from the schema.
|
|
|
|
If these calls are successful, this handle will also
|
|
contain the read results from the call. In the later
|
|
case, a buffer will be created to contain the read
|
|
results. Class read results can be retrieved from the
|
|
buffer with the functions:
|
|
NwNdsGetClassDefListFromBuffer.
|
|
|
|
After the call to this function, this buffer is ONLY
|
|
manipulated by the functions:
|
|
NwNdsGetClassDefListFromBuffer and NwNdsFreeBuffer.
|
|
|
|
Returns:
|
|
|
|
NO_ERROR
|
|
UNSUCCESSFUL - Call GetLastError for Win32 error code.
|
|
*/
|
|
{
|
|
if ( hTree == NULL ||
|
|
((LPNDS_OBJECT_PRIV) hTree)->Signature != NDS_SIGNATURE )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
if ( *lphOperationData == NULL ) // If TRUE, we need to read all class defs
|
|
return ReadClassDef_AllClasses( hTree,
|
|
dwInformationType,
|
|
lphOperationData );
|
|
else // Else, we read the class definitions specified in lphOperationData
|
|
return ReadClassDef_SomeClasses( hTree,
|
|
dwInformationType,
|
|
lphOperationData );
|
|
}
|
|
|
|
|
|
DWORD
|
|
NwNdsReadObject(
|
|
IN HANDLE hObject,
|
|
IN DWORD dwInformationType, // NDS_INFO_NAMES
|
|
// or NDS_INFO_ATTR_NAMES_VALUES
|
|
IN OUT HANDLE * lphOperationData OPTIONAL )
|
|
/*
|
|
NwNdsReadObject()
|
|
|
|
This function is used to read attributes about an object of an NDS
|
|
directory tree.
|
|
|
|
Arguments:
|
|
|
|
HANDLE hObject - A handle to the object in the directory
|
|
tree to be manipulated. Handle is obtained by calling
|
|
NwNdsOpenObject.
|
|
|
|
DWORD dwInformationType - Indicates whether user chooses to
|
|
read only the attribute name(s) on the object or
|
|
read both the attribute name(s) and value(s)
|
|
from the object.
|
|
|
|
HANDLE * lphOperationData - The address of a HANDLE to data
|
|
containing a list of attributes to be read from the
|
|
object hObject. This handle is manipulated by the
|
|
following functions:
|
|
NwNdsCreateBuffer (NDS_OBJECT_READ),
|
|
NwNdsPutInBuffer, and NwNdsFreeBuffer.
|
|
|
|
- OR -
|
|
|
|
The address of a HANDLE set to NULL, which indicates
|
|
that all object attributes should be read from object
|
|
hObject.
|
|
|
|
If these calls are successful, this pointer will also
|
|
contain the read results from the call. In the later
|
|
case, a buffer will be created to contain the read
|
|
results. Attribute values can be retrieved from the
|
|
buffer with the functions:
|
|
NwNdsGetAttrListFromBuffer
|
|
|
|
After the call to this function, this buffer is ONLY
|
|
manipulated by the functions:
|
|
NwNdsGetAttrListFromBuffer and NwNdsFreeBuffer.
|
|
|
|
Returns:
|
|
|
|
NO_ERROR
|
|
UNSUCCESSFUL - Call GetLastError for Win32 error code.
|
|
*/
|
|
{
|
|
if ( hObject == NULL ||
|
|
((LPNDS_OBJECT_PRIV) hObject)->Signature != NDS_SIGNATURE )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
if ( *lphOperationData == NULL ) // If TRUE, we need to read all attributes
|
|
return ReadObject_AllAttrs( hObject,
|
|
dwInformationType,
|
|
lphOperationData );
|
|
else // Else, we read the attributes specified in lphOperationData
|
|
return ReadObject_SomeAttrs( hObject,
|
|
dwInformationType,
|
|
lphOperationData );
|
|
}
|
|
|
|
|
|
DWORD
|
|
NwNdsRemoveObject(
|
|
IN HANDLE hParentObject,
|
|
IN LPWSTR szObjectName )
|
|
/*
|
|
NwNdsRemoveObject()
|
|
|
|
This function is used to remove a leaf object from an NDS directory tree.
|
|
|
|
Arguments:
|
|
|
|
HANDLE hParentObject - A handle to the parent object container
|
|
in the directory tree to remove leaf object from.
|
|
Handle is obtained by calling NwNdsOpenObject.
|
|
|
|
LPWSTR szObjectName - The directory name of the leaf object
|
|
to be removed.
|
|
|
|
Returns:
|
|
|
|
NO_ERROR
|
|
UNSUCCESSFUL - Call GetLastError for Win32 error code.
|
|
*/
|
|
{
|
|
DWORD nwstatus;
|
|
DWORD status = NO_ERROR;
|
|
NTSTATUS ntstatus = STATUS_SUCCESS;
|
|
DWORD dwReplyLength;
|
|
BYTE NdsReply[TWO_KB]; // A 2K buffer is plenty for a response
|
|
LPNDS_OBJECT_PRIV lpNdsParentObject = (LPNDS_OBJECT_PRIV) hParentObject;
|
|
LPNDS_OBJECT_PRIV lpNdsObject = NULL;
|
|
LPWSTR szFullObjectDN = NULL;
|
|
LPWSTR szTempStr = NULL;
|
|
DWORD length;
|
|
UNICODE_STRING ObjectName;
|
|
|
|
if ( szObjectName == NULL ||
|
|
lpNdsParentObject == NULL ||
|
|
lpNdsParentObject->Signature != NDS_SIGNATURE )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
RtlInitUnicodeString( &ObjectName, szObjectName );
|
|
|
|
//
|
|
// Create a buffer to hold the full object distinguished name.
|
|
// \\tree\<--Object Name-->.<existing container path, if any>
|
|
//
|
|
szFullObjectDN = (LPWSTR) LocalAlloc(
|
|
LPTR,
|
|
( wcslen( lpNdsParentObject->szContainerName ) *
|
|
sizeof(WCHAR) ) + // Container name
|
|
ObjectName.Length + // Object name
|
|
( 2 * sizeof(WCHAR) ) ); // Extras
|
|
|
|
//
|
|
// Check that the memory allocation was successful.
|
|
//
|
|
if ( szFullObjectDN == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsRemoveObject LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
length = ParseNdsUncPath( &szTempStr,
|
|
lpNdsParentObject->szContainerName,
|
|
PARSE_NDS_GET_TREE_NAME );
|
|
|
|
length /= sizeof(WCHAR);
|
|
|
|
wcscpy( szFullObjectDN, L"\\\\" ); // <\\>
|
|
wcsncat( szFullObjectDN, szTempStr, length ); // <\\tree>
|
|
wcscat( szFullObjectDN, L"\\" ); // <\\tree\>
|
|
wcsncat( szFullObjectDN, ObjectName.Buffer,
|
|
ObjectName.Length ); // <\\tree\obj>
|
|
|
|
length = ParseNdsUncPath( &szTempStr,
|
|
lpNdsParentObject->szContainerName,
|
|
PARSE_NDS_GET_PATH_NAME );
|
|
|
|
if ( length > 0 )
|
|
{
|
|
length /= sizeof(WCHAR);
|
|
wcscat( szFullObjectDN, L"." ); // <\\tree\obj.>
|
|
wcsncat( szFullObjectDN, szTempStr, length );// <\\tree\obj.org_unt.org>
|
|
}
|
|
|
|
status = NwNdsOpenObject( szFullObjectDN,
|
|
NULL,
|
|
NULL,
|
|
(HANDLE *) &lpNdsObject,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL );
|
|
|
|
if ( status != NO_ERROR )
|
|
{
|
|
// NwNdsOpenObject will have already set the last error . . .
|
|
goto ErrorExit;
|
|
}
|
|
|
|
(void) LocalFree( szFullObjectDN );
|
|
szFullObjectDN = NULL;
|
|
|
|
ntstatus =
|
|
FragExWithWait(
|
|
lpNdsParentObject->NdsTree,
|
|
NETWARE_NDS_FUNCTION_REMOVE_OBJECT,
|
|
NdsReply, // Response buffer.
|
|
sizeof(NdsReply), // Size of response buffer.
|
|
&dwReplyLength, // Length of response returned.
|
|
"DD", // Going to send 2 DWORDs, they are ...
|
|
0, // Version
|
|
lpNdsObject->ObjectId // The id of the object
|
|
);
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsRemoveObject: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
goto ErrorExit;
|
|
}
|
|
|
|
(void) NwNdsCloseObject( (HANDLE) lpNdsObject );
|
|
lpNdsObject = NULL;
|
|
|
|
ntstatus = ParseResponse( NdsReply,
|
|
dwReplyLength,
|
|
"GD",
|
|
&nwstatus );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsRemoveObject: The remove object response was undecipherable.\n" ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
goto ErrorExit;
|
|
}
|
|
|
|
SetLastError( MapNetwareErrorCode( nwstatus ) );
|
|
return nwstatus;
|
|
|
|
|
|
ErrorExit :
|
|
|
|
if ( szFullObjectDN )
|
|
{
|
|
(void) LocalFree( szFullObjectDN );
|
|
}
|
|
|
|
if ( lpNdsObject )
|
|
{
|
|
(void) NwNdsCloseObject( (HANDLE) lpNdsObject );
|
|
}
|
|
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
|
|
DWORD
|
|
NwNdsRenameObject(
|
|
IN HANDLE hParentObject,
|
|
IN LPWSTR szObjectName,
|
|
IN LPWSTR szNewObjectName,
|
|
IN BOOL fDeleteOldName )
|
|
/*
|
|
NwNdsRenameObject()
|
|
|
|
This function is used to rename an object in a NDS directory tree.
|
|
|
|
Arguments:
|
|
|
|
HANDLE hParentObject - A handle to the parent object container
|
|
in the directory tree to rename leaf object in.
|
|
Handle is obtained by calling NwNdsOpenObject.
|
|
|
|
LPWSTR szObjectName - The directory name of the object to be
|
|
renamed.
|
|
|
|
LPWSTR szNewObjectName - The new directory name of the object.
|
|
|
|
BOOL fDeleteOldName - If true, the old name is discarded;
|
|
Otherwise, the old name is retained as an additional
|
|
attribute.
|
|
|
|
Returns:
|
|
|
|
NO_ERROR
|
|
UNSUCCESSFUL - Call GetLastError for Win32 error code.
|
|
*/
|
|
{
|
|
DWORD nwstatus;
|
|
DWORD status = NO_ERROR;
|
|
NTSTATUS ntstatus = STATUS_SUCCESS;
|
|
DWORD dwReplyLength;
|
|
BYTE NdsReply[TWO_KB]; // A 2K buffer is plenty for a response
|
|
LPNDS_OBJECT_PRIV lpNdsParentObject = (LPNDS_OBJECT_PRIV) hParentObject;
|
|
LPNDS_OBJECT_PRIV lpNdsObject = NULL;
|
|
LPWSTR szFullObjectDN = NULL;
|
|
LPWSTR szTempStr = NULL;
|
|
DWORD length;
|
|
UNICODE_STRING ObjectName;
|
|
UNICODE_STRING NewObjectName;
|
|
|
|
if ( szObjectName == NULL ||
|
|
szNewObjectName == NULL ||
|
|
lpNdsParentObject == NULL ||
|
|
lpNdsParentObject->Signature != NDS_SIGNATURE )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
RtlInitUnicodeString( &ObjectName, szObjectName );
|
|
RtlInitUnicodeString( &NewObjectName, szNewObjectName );
|
|
|
|
//
|
|
// Create a buffer to hold the full object distinguished name.
|
|
// \\tree\<--Object Name-->.<existing container path, if any>
|
|
//
|
|
szFullObjectDN = (LPWSTR) LocalAlloc(
|
|
LPTR,
|
|
( wcslen( lpNdsParentObject->szContainerName ) *
|
|
sizeof(WCHAR) ) + // Container name
|
|
ObjectName.Length + // Object name
|
|
( 2 * sizeof(WCHAR) ) ); // Extras
|
|
|
|
//
|
|
// Check that the memory allocation was successful.
|
|
//
|
|
if ( szFullObjectDN == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsRenameObject LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
length = ParseNdsUncPath( &szTempStr,
|
|
lpNdsParentObject->szContainerName,
|
|
PARSE_NDS_GET_TREE_NAME );
|
|
|
|
length /= sizeof(WCHAR);
|
|
|
|
wcscpy( szFullObjectDN, L"\\\\" ); // <\\>
|
|
wcsncat( szFullObjectDN, szTempStr, length ); // <\\tree>
|
|
wcscat( szFullObjectDN, L"\\" ); // <\\tree\>
|
|
wcsncat( szFullObjectDN, ObjectName.Buffer,
|
|
ObjectName.Length ); // <\\tree\obj>
|
|
|
|
length = ParseNdsUncPath( &szTempStr,
|
|
lpNdsParentObject->szContainerName,
|
|
PARSE_NDS_GET_PATH_NAME );
|
|
|
|
if ( length > 0 )
|
|
{
|
|
length /= sizeof(WCHAR);
|
|
wcscat( szFullObjectDN, L"." ); // <\\tree\obj.>
|
|
wcsncat( szFullObjectDN, szTempStr, length );// <\\tree\obj.org_unt.org>
|
|
}
|
|
|
|
status = NwNdsOpenObject( szFullObjectDN,
|
|
NULL,
|
|
NULL,
|
|
(HANDLE *) &lpNdsObject,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL );
|
|
|
|
if ( status != NO_ERROR )
|
|
{
|
|
// NwNdsOpenObject will have already set the last error . . .
|
|
goto ErrorExit;
|
|
}
|
|
|
|
(void) LocalFree( szFullObjectDN );
|
|
szFullObjectDN = NULL;
|
|
|
|
ntstatus =
|
|
FragExWithWait(
|
|
lpNdsParentObject->NdsTree,
|
|
NETWARE_NDS_FUNCTION_MODIFY_RDN,
|
|
NdsReply, // Response buffer.
|
|
sizeof(NdsReply), // Size of response buffer.
|
|
&dwReplyLength, // Length of response returned.
|
|
"DDDS",
|
|
0x00000000, // Version
|
|
lpNdsObject->ObjectId,
|
|
fDeleteOldName ? 0x00021701 : 0x00021700,
|
|
&NewObjectName
|
|
);
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsRenameObject: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
goto ErrorExit;
|
|
}
|
|
|
|
(void) NwNdsCloseObject( (HANDLE) lpNdsObject );
|
|
lpNdsObject = NULL;
|
|
|
|
ntstatus = ParseResponse( NdsReply,
|
|
dwReplyLength,
|
|
"GD",
|
|
&nwstatus );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsRenameObject: The rename object response was undecipherable.\n" ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
goto ErrorExit;
|
|
}
|
|
|
|
SetLastError( MapNetwareErrorCode( nwstatus ) );
|
|
return nwstatus;
|
|
|
|
|
|
ErrorExit :
|
|
|
|
if ( szFullObjectDN )
|
|
{
|
|
(void) LocalFree( szFullObjectDN );
|
|
}
|
|
|
|
if ( lpNdsObject )
|
|
{
|
|
(void) NwNdsCloseObject( (HANDLE) lpNdsObject );
|
|
}
|
|
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
|
|
DWORD
|
|
NwNdsSearch(
|
|
IN HANDLE hStartFromObject,
|
|
IN DWORD dwInformationType, // NDS_INFO_NAMES
|
|
// or NDS_INFO_ATTR_NAMES_VALUES
|
|
IN DWORD dwScope,
|
|
IN BOOL fDerefAliases,
|
|
IN LPQUERY_TREE lpQueryTree,
|
|
IN OUT LPDWORD lpdwIterHandle,
|
|
IN OUT HANDLE * lphOperationData )
|
|
/*
|
|
NwNdsSearch()
|
|
|
|
This function is used to query an NDS directory tree to find objects of
|
|
a certain object type that match a specified search filter.
|
|
|
|
Arguments:
|
|
|
|
HANDLE hStartFromObject - A HANDLE to an object in the
|
|
directory tree to start search from. Handle is
|
|
obtained by calling NwNdsOpenObject.
|
|
|
|
DWORD dwInformationType - Indicates whether user chooses to
|
|
read only the attribute name(s) on the search result
|
|
objects or read both the attribute name(s) and value(s)
|
|
from the search result objects.
|
|
|
|
DWORD dwScope -
|
|
NDS_SCOPE_ONE_LEVEL - Search subordinates from given
|
|
object, one level only
|
|
NDS_SCOPE_SUB_TREE - Search from given object on down
|
|
NDS_SCOPE_BASE_LEVEL - Applies search to an object
|
|
|
|
BOOL fDerefAliases - If TRUE the search will dereference
|
|
aliased objects to the real objects and continue
|
|
to search in the aliased objects subtree. If FALSE
|
|
the search will not dereference aliases.
|
|
|
|
LPQUERY_TREE lpQueryTree - A pointer to the root of a
|
|
search tree which defines a query. This tree
|
|
is manipulated by the following functions:
|
|
NwNdsCreateQueryNode, NwNdsDeleteQueryNode,
|
|
and NwNdsDeleteQueryTree.
|
|
|
|
LPDWORD lpdwIterHandle - A pointer to a DWORD that has the
|
|
iteration handle value. On input, the handle value
|
|
is set to NDS_INITIAL_SEARCH or to a value previously
|
|
returned from a prior call to NwNdsSearch. On ouput,
|
|
the handle value is set to NDS_NO_MORE_ITERATIONS if
|
|
search is complete, or to some other value otherwise.
|
|
|
|
HANDLE * lphOperationData - The address of a HANDLE to data
|
|
containing a list of attributes to be read from the
|
|
objects that meet the search query. This handle is
|
|
manipulated by the following functions:
|
|
NwNdsCreateBuffer (NDS_SEARCH),
|
|
NwNdsPutInBuffer, and NwNdsFreeBuffer.
|
|
|
|
- OR -
|
|
|
|
The address of a HANDLE set to NULL, which indicates
|
|
that all object attributes should be read from the
|
|
search objects found.
|
|
|
|
If these calls are successful, this handle will also
|
|
contain the read results from the call. In the later
|
|
case, a buffer will be created to contain the read
|
|
results. Object information with attribute information
|
|
can be retrieved from the buffer with the function:
|
|
NwNdsGetObjectListFromBuffer.
|
|
|
|
After the call to this function, this buffer is ONLY
|
|
manipulated by the functions:
|
|
NwNdsGetObjectListFromBuffer,
|
|
and NwNdsFreeBuffer.
|
|
|
|
Returns:
|
|
|
|
NO_ERROR
|
|
UNSUCCESSFUL - Call GetLastError for Win32 error code.
|
|
*/
|
|
{
|
|
DWORD dwNdsScope = NDS_SEARCH_SUBTREE;
|
|
|
|
switch ( dwScope )
|
|
{
|
|
case NDS_SCOPE_ONE_LEVEL :
|
|
dwNdsScope = NDS_SEARCH_SUBORDINATES;
|
|
break;
|
|
|
|
case NDS_SCOPE_SUB_TREE :
|
|
dwNdsScope = NDS_SEARCH_SUBTREE;
|
|
break;
|
|
|
|
case NDS_SCOPE_BASE_LEVEL :
|
|
dwNdsScope = NDS_SEARCH_ENTRY;
|
|
break;
|
|
}
|
|
|
|
if ( hStartFromObject == NULL ||
|
|
lpQueryTree == NULL ||
|
|
lpdwIterHandle == NULL ||
|
|
((LPNDS_OBJECT_PRIV) hStartFromObject)->Signature != NDS_SIGNATURE )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
if ( *lphOperationData == NULL )
|
|
{
|
|
//
|
|
// The callee is asking for all attributes to be returned from search.
|
|
//
|
|
return Search_AllAttrs( hStartFromObject,
|
|
dwInformationType,
|
|
dwNdsScope,
|
|
fDerefAliases,
|
|
lpQueryTree,
|
|
lpdwIterHandle,
|
|
lphOperationData );
|
|
}
|
|
else if ( ((LPNDS_BUFFER) *lphOperationData)->lpRequestBuffer == NULL )
|
|
{
|
|
//
|
|
// The callee has a handle from a prior call to NwNdsSearch, and is
|
|
// still asking for all attributes to be returned from search.
|
|
//
|
|
return Search_AllAttrs( hStartFromObject,
|
|
dwInformationType,
|
|
dwNdsScope,
|
|
fDerefAliases,
|
|
lpQueryTree,
|
|
lpdwIterHandle,
|
|
lphOperationData );
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// The callee has a handle that they created with calls to
|
|
// NwNdsCreateBuffer and NwNdsPutInBuffer to specify attributes
|
|
// to be returned from search or NwNdsSearch was called once before
|
|
// and we are resuming the search.
|
|
//
|
|
return Search_SomeAttrs( hStartFromObject,
|
|
dwInformationType,
|
|
dwNdsScope,
|
|
fDerefAliases,
|
|
lpQueryTree,
|
|
lpdwIterHandle,
|
|
lphOperationData );
|
|
}
|
|
}
|
|
|
|
|
|
/* Local Function Implementations */
|
|
|
|
VOID
|
|
PrepareAddEntry(
|
|
LPBYTE lpTempEntry,
|
|
UNICODE_STRING AttributeName,
|
|
DWORD dwSyntaxID,
|
|
LPBYTE lpAttributeValues,
|
|
DWORD dwValueCount,
|
|
LPDWORD lpdwLengthInBytes )
|
|
{
|
|
LPBYTE lpTemp = lpTempEntry;
|
|
DWORD dwStringLen = AttributeName.Length + sizeof(WCHAR);
|
|
DWORD dwPadLen = ROUND_UP_COUNT( dwStringLen, ALIGN_DWORD ) -
|
|
dwStringLen;
|
|
|
|
*lpdwLengthInBytes = 0;
|
|
|
|
//
|
|
// tommye - MS bug 71653 - added try/except wrapper
|
|
//
|
|
|
|
try {
|
|
|
|
//
|
|
// Write attribute name length to temp entry buffer.
|
|
//
|
|
* (LPDWORD) lpTemp = dwStringLen;
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
lpTemp += sizeof(DWORD);
|
|
|
|
//
|
|
// Write attribute name to temp entry buffer.
|
|
//
|
|
RtlCopyMemory( lpTemp, AttributeName.Buffer, AttributeName.Length );
|
|
*lpdwLengthInBytes += AttributeName.Length;
|
|
lpTemp += AttributeName.Length;
|
|
|
|
//
|
|
// Add the null character.
|
|
//
|
|
* (LPWSTR) lpTemp = L'\0';
|
|
*lpdwLengthInBytes += sizeof(WCHAR);
|
|
lpTemp += sizeof(WCHAR);
|
|
|
|
//
|
|
// Write padding (if needed) to temp entry buffer.
|
|
//
|
|
if ( dwPadLen )
|
|
{
|
|
RtlZeroMemory( lpTemp, dwPadLen );
|
|
lpTemp += dwPadLen;
|
|
*lpdwLengthInBytes += dwPadLen;
|
|
}
|
|
|
|
} except ( EXCEPTION_EXECUTE_HANDLER ) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Now add the value(s) to temp entry.
|
|
//
|
|
AppendValueToEntry( lpTemp,
|
|
dwSyntaxID,
|
|
lpAttributeValues,
|
|
dwValueCount,
|
|
lpdwLengthInBytes );
|
|
}
|
|
|
|
|
|
VOID
|
|
PrepareModifyEntry(
|
|
LPBYTE lpTempEntry,
|
|
UNICODE_STRING AttributeName,
|
|
DWORD dwSyntaxID,
|
|
DWORD dwAttrModificationOperation,
|
|
LPBYTE lpAttributeValues,
|
|
DWORD dwValueCount,
|
|
LPDWORD lpdwLengthInBytes )
|
|
{
|
|
LPBYTE lpTemp = lpTempEntry;
|
|
DWORD dwStringLen = AttributeName.Length + sizeof(WCHAR);
|
|
DWORD dwPadLen = ROUND_UP_COUNT( dwStringLen, ALIGN_DWORD ) -
|
|
dwStringLen;
|
|
|
|
*lpdwLengthInBytes = 0;
|
|
|
|
//
|
|
// tommye - MS bug 71654 - added try/except wrapper
|
|
//
|
|
|
|
try {
|
|
|
|
//
|
|
// Write attribute modification operation to temp entry buffer.
|
|
//
|
|
* (LPDWORD) lpTemp = dwAttrModificationOperation;
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
|
|
//
|
|
// Write attribute name length to temp entry buffer.
|
|
//
|
|
* (LPDWORD) lpTemp = dwStringLen;
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
lpTemp += sizeof(DWORD);
|
|
|
|
//
|
|
// Write attribute name to temp entry buffer.
|
|
//
|
|
RtlCopyMemory( lpTemp, AttributeName.Buffer, AttributeName.Length );
|
|
*lpdwLengthInBytes += AttributeName.Length;
|
|
lpTemp += AttributeName.Length;
|
|
|
|
//
|
|
// Add the null character.
|
|
//
|
|
* (LPWSTR) lpTemp = L'\0';
|
|
*lpdwLengthInBytes += sizeof(WCHAR);
|
|
lpTemp += sizeof(WCHAR);
|
|
|
|
//
|
|
// Write padding (if needed) to temp entry buffer.
|
|
//
|
|
if ( dwPadLen )
|
|
{
|
|
RtlZeroMemory( lpTemp, dwPadLen );
|
|
lpTemp += dwPadLen;
|
|
*lpdwLengthInBytes += dwPadLen;
|
|
}
|
|
} except ( EXCEPTION_EXECUTE_HANDLER ) {
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Now add the value(s) to temp entry (if needed).
|
|
//
|
|
switch( dwAttrModificationOperation )
|
|
{
|
|
case NDS_ATTR_ADD_VALUE:
|
|
case NDS_ATTR_ADDITIONAL_VALUE:
|
|
case NDS_ATTR_OVERWRITE_VALUE:
|
|
case NDS_ATTR_REMOVE_VALUE:
|
|
case NDS_ATTR_CLEAR_VALUE:
|
|
case NDS_ATTR_ADD:
|
|
AppendValueToEntry( lpTemp,
|
|
dwSyntaxID,
|
|
lpAttributeValues,
|
|
dwValueCount,
|
|
lpdwLengthInBytes );
|
|
break;
|
|
|
|
case NDS_ATTR_REMOVE:
|
|
case NDS_ATTR_CLEAR:
|
|
// Don't need to do anything for these modification operations.
|
|
break;
|
|
|
|
default :
|
|
#if DBG
|
|
KdPrint(( "NDS32: PrepareModifyEntry warning, unknown modification operation 0x%.8X\n", dwAttrModificationOperation ));
|
|
ASSERT( FALSE );
|
|
#endif
|
|
; // Nothing, skip it.
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
PrepareReadEntry(
|
|
LPBYTE lpTempEntry,
|
|
UNICODE_STRING AttributeName,
|
|
LPDWORD lpdwLengthInBytes )
|
|
{
|
|
LPBYTE lpTemp = lpTempEntry;
|
|
DWORD dwStringLen = AttributeName.Length + sizeof(WCHAR);
|
|
DWORD dwPadLen = ROUND_UP_COUNT( dwStringLen, ALIGN_DWORD ) -
|
|
dwStringLen;
|
|
|
|
*lpdwLengthInBytes = 0;
|
|
|
|
//
|
|
// tommye - MS bug 71655 - added try/except wrapper
|
|
//
|
|
|
|
try {
|
|
//
|
|
// Write attribute name length to temp entry buffer.
|
|
//
|
|
* (LPDWORD) lpTemp = dwStringLen;
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
lpTemp += sizeof(DWORD);
|
|
|
|
//
|
|
// Write attribute name to temp entry buffer.
|
|
//
|
|
RtlCopyMemory( lpTemp, AttributeName.Buffer, AttributeName.Length );
|
|
*lpdwLengthInBytes += AttributeName.Length;
|
|
lpTemp += AttributeName.Length;
|
|
|
|
//
|
|
// Add the null character.
|
|
//
|
|
* (LPWSTR) lpTemp = L'\0';
|
|
*lpdwLengthInBytes += sizeof(WCHAR);
|
|
lpTemp += sizeof(WCHAR);
|
|
|
|
//
|
|
// Write padding (if needed) to temp entry buffer.
|
|
//
|
|
if ( dwPadLen )
|
|
{
|
|
RtlZeroMemory( lpTemp, dwPadLen );
|
|
lpTemp += dwPadLen;
|
|
*lpdwLengthInBytes += dwPadLen;
|
|
}
|
|
} except ( EXCEPTION_EXECUTE_HANDLER ) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
DWORD
|
|
CalculateValueDataSize(
|
|
DWORD dwSyntaxId,
|
|
LPBYTE lpAttributeValues,
|
|
DWORD dwValueCount )
|
|
{
|
|
LPBYTE lpAttrStart, lpAttrTemp = lpAttributeValues;
|
|
LPBYTE lpField1, lpField2;
|
|
DWORD numFields;
|
|
DWORD length = 0;
|
|
DWORD stringLen, stringLen2;
|
|
DWORD iter, i;
|
|
DWORD dwLengthInBytes = 0;
|
|
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
|
|
for ( iter = 0; iter < dwValueCount; iter++ )
|
|
{
|
|
switch ( dwSyntaxId )
|
|
{
|
|
case NDS_SYNTAX_ID_0 :
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_1 :
|
|
case NDS_SYNTAX_ID_2 :
|
|
case NDS_SYNTAX_ID_3 :
|
|
case NDS_SYNTAX_ID_4 :
|
|
case NDS_SYNTAX_ID_5 :
|
|
case NDS_SYNTAX_ID_10 :
|
|
case NDS_SYNTAX_ID_20 :
|
|
|
|
stringLen = wcslen(((LPASN1_TYPE_1) lpAttrTemp)->DNString);
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
dwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
lpAttrTemp += sizeof(ASN1_TYPE_1);
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_6 :
|
|
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
lpAttrStart = lpAttrTemp;
|
|
while( ((LPASN1_TYPE_6) lpAttrTemp)->Next )
|
|
{
|
|
stringLen = wcslen(((LPASN1_TYPE_6) lpAttrTemp)->String);
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
dwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*
|
|
sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
lpAttrTemp = (LPBYTE)(((LPASN1_TYPE_6) lpAttrTemp)->Next);
|
|
}
|
|
stringLen = wcslen(((LPASN1_TYPE_6) lpAttrTemp)->String);
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
dwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*
|
|
sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
lpAttrTemp = lpAttrStart + sizeof(ASN1_TYPE_6);
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_7 :
|
|
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
lpAttrTemp += sizeof(ASN1_TYPE_7);
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_8 :
|
|
case NDS_SYNTAX_ID_22 :
|
|
case NDS_SYNTAX_ID_24 :
|
|
case NDS_SYNTAX_ID_27 :
|
|
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
lpAttrTemp += sizeof(ASN1_TYPE_8);
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_9 :
|
|
|
|
stringLen = ((LPASN1_TYPE_9) lpAttrTemp)->Length;
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
dwLengthInBytes += ROUND_UP_COUNT((stringLen)*sizeof(BYTE),
|
|
ALIGN_DWORD );
|
|
lpAttrTemp += sizeof(ASN1_TYPE_9);
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_11 :
|
|
|
|
stringLen = wcslen(((LPASN1_TYPE_11) lpAttrTemp)->TelephoneNumber);
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
dwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD );
|
|
dwLengthInBytes += 2*sizeof(DWORD);
|
|
lpAttrTemp += sizeof(ASN1_TYPE_11);
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_12 :
|
|
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
dwLengthInBytes += ((LPASN1_TYPE_12)
|
|
lpAttrTemp)->AddressLength * sizeof(WCHAR);
|
|
lpAttrTemp += sizeof(ASN1_TYPE_12);
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_13 :
|
|
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
lpAttrStart = lpAttrTemp;
|
|
while ( ((LPASN1_TYPE_13) lpAttrTemp)->Next )
|
|
{
|
|
stringLen = ((LPASN1_TYPE_13) lpAttrTemp)->Length;
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
dwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*
|
|
sizeof(BYTE),
|
|
ALIGN_DWORD);
|
|
lpAttrTemp = (LPBYTE)(((LPASN1_TYPE_13) lpAttrTemp)->Next);
|
|
}
|
|
stringLen = ((LPASN1_TYPE_13) lpAttrTemp)->Length;
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
dwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*
|
|
sizeof(BYTE),
|
|
ALIGN_DWORD);
|
|
lpAttrTemp = lpAttrStart + sizeof(ASN1_TYPE_13);
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_14 :
|
|
|
|
stringLen = wcslen(((LPASN1_TYPE_14) lpAttrTemp)->Address);
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
dwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
lpAttrTemp += sizeof(ASN1_TYPE_14);
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_15 :
|
|
|
|
stringLen = wcslen(((LPASN1_TYPE_15) lpAttrTemp)->VolumeName);
|
|
stringLen2 = wcslen(((LPASN1_TYPE_15) lpAttrTemp)->Path);
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
dwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
dwLengthInBytes += ROUND_UP_COUNT((stringLen2+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
lpAttrTemp += sizeof(ASN1_TYPE_15);
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_16 :
|
|
|
|
stringLen = wcslen(((LPASN1_TYPE_16) lpAttrTemp)->ServerName);
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
dwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
lpAttrTemp += sizeof(ASN1_TYPE_16);
|
|
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_17 :
|
|
|
|
stringLen = wcslen(((LPASN1_TYPE_17) lpAttrTemp)->ProtectedAttrName);
|
|
stringLen2 = wcslen(((LPASN1_TYPE_17) lpAttrTemp)->SubjectName);
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
dwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
dwLengthInBytes += ROUND_UP_COUNT((stringLen2+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
lpAttrTemp += sizeof(ASN1_TYPE_17);
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_18 :
|
|
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
for ( i = 0; i < 6; i++ )
|
|
{
|
|
stringLen = wcslen(((LPASN1_TYPE_18) lpAttrTemp)->PostalAddress[i]);
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
dwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*
|
|
sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
}
|
|
lpAttrTemp += sizeof(ASN1_TYPE_18);
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_19 :
|
|
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
lpAttrTemp += sizeof(ASN1_TYPE_19);
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_21 :
|
|
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
lpAttrTemp += sizeof(ASN1_TYPE_21);
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_23 :
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_25 :
|
|
|
|
stringLen = wcslen(((LPASN1_TYPE_25) lpAttrTemp)->ObjectName);
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
dwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
dwLengthInBytes += sizeof(DWORD);
|
|
lpAttrTemp += sizeof(ASN1_TYPE_25);
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_26 :
|
|
break;
|
|
|
|
default :
|
|
#if DBG
|
|
KdPrint(( "NDS32: CalculateValueDataSize() unknown SyntaxId 0x%.8X.\n", dwSyntaxId ));
|
|
ASSERT( FALSE );
|
|
#endif
|
|
break; // empty statement not allowed
|
|
}
|
|
}
|
|
|
|
return dwLengthInBytes;
|
|
}
|
|
|
|
|
|
VOID
|
|
AppendValueToEntry(
|
|
LPBYTE lpBuffer,
|
|
DWORD dwSyntaxId,
|
|
LPBYTE lpAttributeValues,
|
|
DWORD dwValueCount,
|
|
LPDWORD lpdwLengthInBytes )
|
|
{
|
|
LPBYTE lpTemp = lpBuffer;
|
|
LPBYTE lpAttrStart, lpAttrTemp = lpAttributeValues;
|
|
LPBYTE lpField1, lpField2;
|
|
DWORD numFields;
|
|
DWORD length = 0;
|
|
DWORD stringLen, stringLen2;
|
|
DWORD iter, i;
|
|
|
|
*(LPDWORD)lpTemp = dwValueCount;
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
|
|
for ( iter = 0; iter < dwValueCount; iter++ )
|
|
{
|
|
switch ( dwSyntaxId )
|
|
{
|
|
case NDS_SYNTAX_ID_0 :
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_1 :
|
|
case NDS_SYNTAX_ID_2 :
|
|
case NDS_SYNTAX_ID_3 :
|
|
case NDS_SYNTAX_ID_4 :
|
|
case NDS_SYNTAX_ID_5 :
|
|
case NDS_SYNTAX_ID_10 :
|
|
case NDS_SYNTAX_ID_20 :
|
|
|
|
stringLen = wcslen(((LPASN1_TYPE_1) lpAttrTemp)->DNString);
|
|
|
|
*(LPDWORD)lpTemp = (stringLen + 1) * sizeof(WCHAR);
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
|
|
RtlCopyMemory( lpTemp,
|
|
((LPASN1_TYPE_1) lpAttrTemp)->DNString,
|
|
stringLen*sizeof(WCHAR) );
|
|
lpTemp += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
*lpdwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
|
|
lpAttrTemp += sizeof(ASN1_TYPE_1);
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_6 :
|
|
|
|
lpField1 = lpTemp; // Save field to store the number of
|
|
// bytes following
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
*(LPDWORD)lpField1 = 0;
|
|
|
|
lpField2 = lpTemp; // Save field to store the number of
|
|
// elements
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
*(LPDWORD)lpField1 += sizeof(DWORD);
|
|
|
|
numFields = 0;
|
|
|
|
lpAttrStart = lpAttrTemp;
|
|
|
|
while( ((LPASN1_TYPE_6) lpAttrTemp)->Next )
|
|
{
|
|
stringLen = wcslen(((LPASN1_TYPE_6) lpAttrTemp)->String);
|
|
|
|
*(LPDWORD)lpTemp = (stringLen + 1) * sizeof(WCHAR);
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
*(LPDWORD)lpField1 += sizeof(DWORD);
|
|
|
|
RtlCopyMemory( lpTemp,
|
|
((LPASN1_TYPE_6) lpAttrTemp)->String,
|
|
stringLen*sizeof(WCHAR) );
|
|
lpTemp += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
*lpdwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*
|
|
sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
*(LPDWORD)lpField1 += ROUND_UP_COUNT((stringLen+1)*
|
|
sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
|
|
lpAttrTemp = (LPBYTE)(((LPASN1_TYPE_6) lpAttrTemp)->Next);
|
|
|
|
numFields++;
|
|
}
|
|
|
|
stringLen = wcslen(((LPASN1_TYPE_6) lpAttrTemp)->String);
|
|
|
|
*(LPDWORD)lpTemp = (stringLen + 1) * sizeof(WCHAR);
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
*(LPDWORD)lpField1 += sizeof(DWORD);
|
|
|
|
RtlCopyMemory( lpTemp,
|
|
((LPASN1_TYPE_6) lpAttrTemp)->String,
|
|
stringLen*sizeof(WCHAR) );
|
|
lpTemp += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
*lpdwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*
|
|
sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
*(LPDWORD)lpField1 += ROUND_UP_COUNT((stringLen+1)*
|
|
sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
|
|
lpAttrTemp = lpAttrStart + sizeof(ASN1_TYPE_6);
|
|
|
|
numFields++;
|
|
|
|
*(LPDWORD)lpField2 = numFields;
|
|
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_7 :
|
|
|
|
*(LPDWORD)lpTemp = 1; // Needs to have value 1, representing one byte even though it is
|
|
// padded out to four bytes.
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
|
|
*(LPDWORD)lpTemp = 0; // This clears all bits of the DWORD
|
|
*(LPBYTE)lpTemp = (BYTE) (((LPASN1_TYPE_7)
|
|
lpAttrTemp)->Boolean);
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
|
|
lpAttrTemp += sizeof(ASN1_TYPE_7);
|
|
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_8 :
|
|
case NDS_SYNTAX_ID_22 :
|
|
case NDS_SYNTAX_ID_24 :
|
|
case NDS_SYNTAX_ID_27 :
|
|
|
|
*(LPDWORD)lpTemp = 4; // Needs to have value 4, representing four bytes - already DWORD aligned.
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
|
|
*(LPDWORD)lpTemp = ((LPASN1_TYPE_8) lpAttrTemp)->Integer;
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
|
|
lpAttrTemp += sizeof(ASN1_TYPE_8);
|
|
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_9 :
|
|
|
|
stringLen = ((LPASN1_TYPE_9) lpAttrTemp)->Length;
|
|
|
|
*(LPDWORD)lpTemp = (stringLen) * sizeof(BYTE);
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
|
|
RtlCopyMemory( lpTemp,
|
|
((LPASN1_TYPE_9) lpAttrTemp)->OctetString,
|
|
stringLen*sizeof(BYTE) );
|
|
lpTemp += ROUND_UP_COUNT((stringLen)*sizeof(BYTE),
|
|
ALIGN_DWORD );
|
|
*lpdwLengthInBytes += ROUND_UP_COUNT((stringLen)*sizeof(BYTE),
|
|
ALIGN_DWORD );
|
|
|
|
lpAttrTemp += sizeof(ASN1_TYPE_9);
|
|
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_11 :
|
|
|
|
stringLen = wcslen(((LPASN1_TYPE_11) lpAttrTemp)->TelephoneNumber);
|
|
|
|
*(LPDWORD)lpTemp = ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD) +
|
|
( 2*sizeof(DWORD) );
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
|
|
*(LPDWORD)lpTemp = (stringLen + 1) * sizeof(WCHAR);
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
|
|
RtlCopyMemory( lpTemp,
|
|
((LPASN1_TYPE_11) lpAttrTemp)->TelephoneNumber,
|
|
stringLen*sizeof(WCHAR) );
|
|
lpTemp += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),ALIGN_DWORD);
|
|
*lpdwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD );
|
|
|
|
lpTemp += 2*sizeof(DWORD);
|
|
*lpdwLengthInBytes += 2*sizeof(DWORD);
|
|
|
|
lpAttrTemp += sizeof(ASN1_TYPE_11);
|
|
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_12 :
|
|
|
|
*(LPDWORD)lpTemp =
|
|
(2*sizeof(DWORD)) +
|
|
(((LPASN1_TYPE_12) lpAttrTemp)->AddressLength*sizeof(WCHAR));
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
|
|
*(LPDWORD)lpTemp = ((LPASN1_TYPE_12) lpAttrTemp)->AddressType;
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
|
|
//
|
|
// Write address length value to buffer
|
|
//
|
|
*(LPDWORD)lpTemp = ((LPASN1_TYPE_12) lpAttrTemp)->AddressLength;
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
|
|
//
|
|
// Write the address to the buffer
|
|
//
|
|
RtlCopyMemory( lpTemp,
|
|
((LPASN1_TYPE_12) lpAttrTemp)->Address,
|
|
((LPASN1_TYPE_12) lpAttrTemp)->AddressLength
|
|
* sizeof(WCHAR) );
|
|
lpTemp += ((LPASN1_TYPE_12) lpAttrTemp)->AddressLength *
|
|
sizeof(WCHAR);
|
|
*lpdwLengthInBytes += ((LPASN1_TYPE_12)
|
|
lpAttrTemp)->AddressLength * sizeof(WCHAR);
|
|
|
|
lpAttrTemp += sizeof(ASN1_TYPE_12);
|
|
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_13 :
|
|
|
|
lpField1 = lpTemp; // Save field to store the number of
|
|
// bytes following
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
*(LPDWORD)lpField1 = 0;
|
|
|
|
lpField2 = lpTemp; // Save field to store the number of
|
|
// elements
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
*(LPDWORD)lpField1 += sizeof(DWORD);
|
|
|
|
numFields = 0;
|
|
|
|
lpAttrStart = lpAttrTemp;
|
|
|
|
while ( ((LPASN1_TYPE_13) lpAttrTemp)->Next )
|
|
{
|
|
stringLen = ((LPASN1_TYPE_13) lpAttrTemp)->Length;
|
|
|
|
*(LPDWORD)lpTemp = stringLen;
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
*(LPDWORD)lpField1 += sizeof(DWORD);
|
|
|
|
RtlCopyMemory( lpTemp,
|
|
((LPASN1_TYPE_13) lpAttrTemp)->Data,
|
|
stringLen*sizeof(BYTE) );
|
|
lpTemp += ROUND_UP_COUNT((stringLen+1)*sizeof(BYTE),
|
|
ALIGN_DWORD);
|
|
*lpdwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*
|
|
sizeof(BYTE),
|
|
ALIGN_DWORD);
|
|
*(LPDWORD)lpField1 += ROUND_UP_COUNT((stringLen+1)*
|
|
sizeof(BYTE),
|
|
ALIGN_DWORD);
|
|
|
|
lpAttrTemp = (LPBYTE)(((LPASN1_TYPE_13) lpAttrTemp)->Next);
|
|
|
|
numFields++;
|
|
}
|
|
|
|
stringLen = ((LPASN1_TYPE_13) lpAttrTemp)->Length;
|
|
|
|
*(LPDWORD)lpTemp = stringLen;
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
*(LPDWORD)lpField1 += sizeof(DWORD);
|
|
|
|
RtlCopyMemory( lpTemp,
|
|
((LPASN1_TYPE_13) lpAttrTemp)->Data,
|
|
stringLen*sizeof(BYTE) );
|
|
lpTemp += ROUND_UP_COUNT((stringLen+1)*sizeof(BYTE),
|
|
ALIGN_DWORD);
|
|
*lpdwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*
|
|
sizeof(BYTE),
|
|
ALIGN_DWORD);
|
|
*(LPDWORD)lpField1 += ROUND_UP_COUNT((stringLen+1)*
|
|
sizeof(BYTE),
|
|
ALIGN_DWORD);
|
|
|
|
lpAttrTemp = lpAttrStart + sizeof(ASN1_TYPE_13);
|
|
|
|
numFields++;
|
|
|
|
*(LPDWORD)lpField2 = numFields;
|
|
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_14 :
|
|
|
|
stringLen = wcslen(((LPASN1_TYPE_14) lpAttrTemp)->Address);
|
|
|
|
*(LPDWORD)lpTemp = ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD) +
|
|
sizeof(DWORD);
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
|
|
*(LPDWORD)lpTemp = ((LPASN1_TYPE_14) lpAttrTemp)->Type;
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
|
|
*(LPDWORD)lpTemp = (stringLen + 1)*sizeof(WCHAR);
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
|
|
RtlCopyMemory( lpTemp,
|
|
((LPASN1_TYPE_14) lpAttrTemp)->Address,
|
|
stringLen*sizeof(WCHAR) );
|
|
lpTemp += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
*lpdwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
|
|
lpAttrTemp += sizeof(ASN1_TYPE_14);
|
|
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_15 :
|
|
|
|
stringLen = wcslen(((LPASN1_TYPE_15) lpAttrTemp)->VolumeName);
|
|
stringLen2 = wcslen(((LPASN1_TYPE_15) lpAttrTemp)->Path);
|
|
|
|
*(LPDWORD)lpTemp = ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD) +
|
|
ROUND_UP_COUNT((stringLen2+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD) +
|
|
sizeof(DWORD);
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
|
|
*(LPDWORD)lpTemp = ((LPASN1_TYPE_15) lpAttrTemp)->Type;
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
|
|
*(LPDWORD)lpTemp = (stringLen+1) * sizeof(WCHAR);
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
|
|
RtlCopyMemory( lpTemp,
|
|
((LPASN1_TYPE_15) lpAttrTemp)->VolumeName,
|
|
stringLen*sizeof(WCHAR) );
|
|
lpTemp += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
*lpdwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
|
|
*(LPDWORD)lpTemp = (stringLen2+1) * sizeof(WCHAR);
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
|
|
RtlCopyMemory( lpTemp,
|
|
((LPASN1_TYPE_15) lpAttrTemp)->Path,
|
|
stringLen2*sizeof(WCHAR) );
|
|
lpTemp += ROUND_UP_COUNT((stringLen2+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
*lpdwLengthInBytes += ROUND_UP_COUNT((stringLen2+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
|
|
lpAttrTemp += sizeof(ASN1_TYPE_15);
|
|
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_16 :
|
|
|
|
stringLen = wcslen(((LPASN1_TYPE_16) lpAttrTemp)->ServerName);
|
|
|
|
*(LPDWORD)lpTemp = ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD) +
|
|
(4*sizeof(DWORD));
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
|
|
*(LPDWORD)lpTemp = (stringLen + 1) * sizeof(WCHAR);
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
|
|
RtlCopyMemory( lpTemp,
|
|
((LPASN1_TYPE_16) lpAttrTemp)->ServerName,
|
|
stringLen*sizeof(WCHAR) );
|
|
lpTemp += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
*lpdwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
|
|
*(LPDWORD)lpTemp = ((LPASN1_TYPE_16) lpAttrTemp)->ReplicaType;
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
|
|
*(LPDWORD)lpTemp = ((LPASN1_TYPE_16) lpAttrTemp)->ReplicaNumber;
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
|
|
*(LPDWORD)lpTemp = ((LPASN1_TYPE_16) lpAttrTemp)->Count;
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
|
|
lpAttrTemp += sizeof(ASN1_TYPE_16);
|
|
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_17 :
|
|
|
|
stringLen = wcslen(((LPASN1_TYPE_17) lpAttrTemp)->ProtectedAttrName);
|
|
stringLen2 = wcslen(((LPASN1_TYPE_17) lpAttrTemp)->SubjectName);
|
|
|
|
*(LPDWORD)lpTemp = ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD) +
|
|
ROUND_UP_COUNT((stringLen2+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD) +
|
|
sizeof(DWORD);
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
|
|
*(LPDWORD)lpTemp = (stringLen + 1) * sizeof(WCHAR);
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
|
|
RtlCopyMemory( lpTemp,
|
|
((LPASN1_TYPE_17)lpAttrTemp)->ProtectedAttrName,
|
|
stringLen*sizeof(WCHAR) );
|
|
lpTemp += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
*lpdwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
|
|
*(LPDWORD)lpTemp = (stringLen2 + 1) * sizeof(WCHAR);
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
|
|
RtlCopyMemory( lpTemp,
|
|
((LPASN1_TYPE_17) lpAttrTemp)->SubjectName,
|
|
stringLen2*sizeof(WCHAR) );
|
|
lpTemp += ROUND_UP_COUNT((stringLen2+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
*lpdwLengthInBytes += ROUND_UP_COUNT((stringLen2+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
|
|
*(LPDWORD)lpTemp = ((LPASN1_TYPE_17) lpAttrTemp)->Privileges;
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
|
|
lpAttrTemp += sizeof(ASN1_TYPE_17);
|
|
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_18 :
|
|
|
|
lpField1 = lpTemp; // Save field to store the number of
|
|
// bytes following
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
*(LPDWORD)lpField1 = 0;
|
|
|
|
*(LPDWORD)lpTemp = 6; // The number of postal address fields
|
|
// is always six.
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
*(LPDWORD)lpField1 += sizeof(DWORD);
|
|
|
|
for ( i = 0; i < 6; i++ )
|
|
{
|
|
stringLen = wcslen(((LPASN1_TYPE_18) lpAttrTemp)->PostalAddress[i]);
|
|
|
|
*(LPDWORD)lpTemp = (stringLen + 1) * sizeof(WCHAR);
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
*(LPDWORD)lpField1 += sizeof(DWORD);
|
|
|
|
RtlCopyMemory( lpTemp,
|
|
((LPASN1_TYPE_18) lpAttrTemp)->PostalAddress[i],
|
|
stringLen*sizeof(WCHAR) );
|
|
lpTemp += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
*lpdwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*
|
|
sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
*(LPDWORD)lpField1 += ROUND_UP_COUNT((stringLen+1)*
|
|
sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
}
|
|
|
|
lpAttrTemp += sizeof(ASN1_TYPE_18);
|
|
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_19 :
|
|
|
|
*(LPDWORD)lpTemp = ((LPASN1_TYPE_19) lpAttrTemp)->WholeSeconds;
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
|
|
*(LPDWORD)lpTemp = ((LPASN1_TYPE_19) lpAttrTemp)->EventID;
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
|
|
lpAttrTemp += sizeof(ASN1_TYPE_19);
|
|
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_21 :
|
|
|
|
*(LPDWORD)lpTemp = ((LPASN1_TYPE_21) lpAttrTemp)->Length;
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
|
|
lpAttrTemp += sizeof(ASN1_TYPE_21);
|
|
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_23 :
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_25 :
|
|
|
|
stringLen = wcslen(((LPASN1_TYPE_25) lpAttrTemp)->ObjectName);
|
|
|
|
*(LPDWORD)lpTemp = ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD) +
|
|
2*sizeof(DWORD);
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
|
|
*(LPDWORD)lpTemp = (stringLen + 1) * sizeof(WCHAR);
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
|
|
RtlCopyMemory( lpTemp,
|
|
((LPASN1_TYPE_25) lpAttrTemp)->ObjectName,
|
|
stringLen*sizeof(WCHAR) );
|
|
lpTemp += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
*lpdwLengthInBytes += ROUND_UP_COUNT((stringLen+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
|
|
*(LPDWORD)lpTemp = ((LPASN1_TYPE_25) lpAttrTemp)->Level;
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
|
|
*(LPDWORD)lpTemp = ((LPASN1_TYPE_25) lpAttrTemp)->Interval;
|
|
lpTemp += sizeof(DWORD);
|
|
*lpdwLengthInBytes += sizeof(DWORD);
|
|
|
|
lpAttrTemp += sizeof(ASN1_TYPE_25);
|
|
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_26 :
|
|
break;
|
|
|
|
default :
|
|
#if DBG
|
|
KdPrint(( "NDS32: AppendValueToEntry() unknown SyntaxId 0x%.8X.\n", dwSyntaxId ));
|
|
ASSERT( FALSE );
|
|
#endif
|
|
break; // empty statement not allowed
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
DWORD
|
|
MapNetwareErrorCode(
|
|
DWORD dwNetwareError )
|
|
{
|
|
DWORD status = NO_ERROR;
|
|
|
|
switch( dwNetwareError )
|
|
{
|
|
case NDS_ERR_SUCCESS :
|
|
status = NO_ERROR;
|
|
break;
|
|
|
|
case NDS_ERR_NO_SUCH_ENTRY :
|
|
case NDS_ERR_NO_SUCH_VALUE :
|
|
case NDS_ERR_NO_SUCH_ATTRIBUTE :
|
|
case NDS_ERR_NO_SUCH_CLASS :
|
|
case NDS_ERR_NO_SUCH_PARTITION :
|
|
status = ERROR_EXTENDED_ERROR;
|
|
break;
|
|
|
|
case NDS_ERR_ENTRY_ALREADY_EXISTS :
|
|
status = ERROR_ALREADY_EXISTS;
|
|
break;
|
|
|
|
case NDS_ERR_NOT_EFFECTIVE_CLASS :
|
|
case NDS_ERR_ILLEGAL_ATTRIBUTE :
|
|
case NDS_ERR_MISSING_MANDATORY :
|
|
case NDS_ERR_ILLEGAL_DS_NAME :
|
|
case NDS_ERR_ILLEGAL_CONTAINMENT :
|
|
case NDS_ERR_CANT_HAVE_MULTIPLE_VALUES :
|
|
case NDS_ERR_SYNTAX_VIOLATION :
|
|
case NDS_ERR_DUPLICATE_VALUE :
|
|
case NDS_ERR_ATTRIBUTE_ALREADY_EXISTS :
|
|
case NDS_ERR_MAXIMUM_ENTRIES_EXIST :
|
|
case NDS_ERR_DATABASE_FORMAT :
|
|
case NDS_ERR_INCONSISTANT_DATABASE :
|
|
case NDS_ERR_INVALID_COMPARISON :
|
|
case NDS_ERR_COMPARISON_FAILED :
|
|
case NDS_ERR_TRANSACTIONS_DISABLED :
|
|
case NDS_ERR_INVALID_TRANSPORT :
|
|
case NDS_ERR_SYNTAX_INVALID_IN_NAME :
|
|
case NDS_ERR_REPLICA_ALREADY_EXISTS :
|
|
case NDS_ERR_TRANSPORT_FAILURE :
|
|
case NDS_ERR_ALL_REFERRALS_FAILED :
|
|
case NDS_ERR_CANT_REMOVE_NAMING_VALUE :
|
|
case NDS_ERR_OBJECT_CLASS_VIOLATION :
|
|
case NDS_ERR_ENTRY_IS_NOT_LEAF :
|
|
case NDS_ERR_DIFFERENT_TREE :
|
|
case NDS_ERR_ILLEGAL_REPLICA_TYPE :
|
|
case NDS_ERR_SYSTEM_FAILURE :
|
|
case NDS_ERR_INVALID_ENTRY_FOR_ROOT :
|
|
case NDS_ERR_NO_REFERRALS :
|
|
case NDS_ERR_REMOTE_FAILURE :
|
|
case NDS_ERR_INVALID_REQUEST :
|
|
case NDS_ERR_INVALID_ITERATION :
|
|
case NDS_ERR_SCHEMA_IS_NONREMOVABLE :
|
|
case NDS_ERR_SCHEMA_IS_IN_USE :
|
|
case NDS_ERR_CLASS_ALREADY_EXISTS :
|
|
case NDS_ERR_BAD_NAMING_ATTRIBUTES :
|
|
case NDS_ERR_NOT_ROOT_PARTITION :
|
|
case NDS_ERR_INSUFFICIENT_STACK :
|
|
case NDS_ERR_INSUFFICIENT_BUFFER :
|
|
case NDS_ERR_AMBIGUOUS_CONTAINMENT :
|
|
case NDS_ERR_AMBIGUOUS_NAMING :
|
|
case NDS_ERR_DUPLICATE_MANDATORY :
|
|
case NDS_ERR_DUPLICATE_OPTIONAL :
|
|
case NDS_ERR_MULTIPLE_REPLICAS :
|
|
case NDS_ERR_CRUCIAL_REPLICA :
|
|
case NDS_ERR_SCHEMA_SYNC_IN_PROGRESS :
|
|
case NDS_ERR_SKULK_IN_PROGRESS :
|
|
case NDS_ERR_TIME_NOT_SYNCRONIZED :
|
|
case NDS_ERR_RECORD_IN_USE :
|
|
case NDS_ERR_DS_VOLUME_NOT_MOUNTED :
|
|
case NDS_ERR_DS_VOLUME_IO_FAILURE :
|
|
case NDS_ERR_DS_LOCKED :
|
|
case NDS_ERR_OLD_EPOCH :
|
|
case NDS_ERR_NEW_EPOCH :
|
|
case NDS_ERR_PARTITION_ROOT :
|
|
case NDS_ERR_ENTRY_NOT_CONTAINER :
|
|
case NDS_ERR_FAILED_AUTHENTICATION :
|
|
case NDS_ERR_NO_SUCH_PARENT :
|
|
status = ERROR_EXTENDED_ERROR;
|
|
break;
|
|
|
|
case NDS_ERR_NO_ACCESS :
|
|
status = ERROR_ACCESS_DENIED;
|
|
break;
|
|
|
|
case NDS_ERR_REPLICA_NOT_ON :
|
|
case NDS_ERR_DUPLICATE_ACL :
|
|
case NDS_ERR_PARTITION_ALREADY_EXISTS :
|
|
case NDS_ERR_NOT_SUBREF :
|
|
case NDS_ERR_ALIAS_OF_AN_ALIAS :
|
|
case NDS_ERR_AUDITING_FAILED :
|
|
case NDS_ERR_INVALID_API_VERSION :
|
|
case NDS_ERR_SECURE_NCP_VIOLATION :
|
|
case NDS_ERR_FATAL :
|
|
status = ERROR_EXTENDED_ERROR;
|
|
break;
|
|
|
|
default :
|
|
#if DBG
|
|
KdPrint(( "NDS32: MapNetwareErrorCode failed, Netware error = 0x%.8X\n", dwNetwareError ));
|
|
ASSERT( FALSE );
|
|
#endif
|
|
|
|
status = ERROR_EXTENDED_ERROR;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
DWORD
|
|
IndexReadAttrDefReplyBuffer(
|
|
LPNDS_BUFFER lpNdsBuffer )
|
|
{
|
|
LPNDS_ATTR_DEF lpReplyIndex = NULL;
|
|
DWORD iter;
|
|
LPBYTE lpByte = NULL;
|
|
DWORD dwStringLen;
|
|
|
|
//
|
|
// Make sure this is set to zero, for NwNdsGetNextXXXXFromBuffer()
|
|
//
|
|
lpNdsBuffer->dwCurrentIndexEntry = 0;
|
|
|
|
//
|
|
// Set values used to track the memory used in the index buffer.
|
|
//
|
|
lpNdsBuffer->dwIndexBufferSize = lpNdsBuffer->dwNumberOfReplyEntries *
|
|
sizeof(NDS_ATTR_DEF);
|
|
lpNdsBuffer->dwIndexAvailableBytes = lpNdsBuffer->dwIndexBufferSize;
|
|
lpNdsBuffer->dwNumberOfIndexEntries = 0;
|
|
lpNdsBuffer->dwLengthOfIndexData = 0;
|
|
|
|
//
|
|
// Create a buffer to hold the ReplyBufferIndex
|
|
//
|
|
lpReplyIndex = (LPNDS_ATTR_DEF)
|
|
LocalAlloc( LPTR, lpNdsBuffer->dwIndexBufferSize );
|
|
|
|
//
|
|
// Check that the memory allocation was successful.
|
|
//
|
|
if ( lpReplyIndex == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: IndexReadAttrDefReplyBuffer LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
lpNdsBuffer->lpIndexBuffer = (LPBYTE) lpReplyIndex;
|
|
|
|
//
|
|
// Move lpByte so that it points to the first attribute definition
|
|
//
|
|
lpByte = lpNdsBuffer->lpReplyBuffer;
|
|
|
|
// lpByte += sizeof(DWORD); // Move past Completion Code
|
|
// lpByte += sizeof(DWORD); // Move past Iteration Handle
|
|
// lpByte += sizeof(DWORD); // Move past Information Type
|
|
// lpByte += sizeof(DWORD); // Move past Amount Of Attributes
|
|
lpByte += 4 * sizeof(DWORD); // Equivalent to above
|
|
|
|
//
|
|
// In a for loop, walk the reply buffer index and fill it up with
|
|
// data by referencing the Reply buffer or Syntax buffer.
|
|
//
|
|
for ( iter = 0; iter < lpNdsBuffer->dwNumberOfReplyEntries; iter++ )
|
|
{
|
|
dwStringLen = *((LPDWORD) lpByte);
|
|
lpByte += sizeof(DWORD); // Move past Attribute Name Length
|
|
|
|
lpReplyIndex[iter].szAttributeName = (LPWSTR) lpByte;
|
|
lpByte += ROUND_UP_COUNT( dwStringLen, ALIGN_DWORD );
|
|
|
|
lpReplyIndex[iter].dwFlags = *((LPDWORD) lpByte);
|
|
lpByte += sizeof(DWORD); // Move past Flags
|
|
|
|
lpReplyIndex[iter].dwSyntaxID = *((LPDWORD) lpByte);
|
|
lpByte += sizeof(DWORD); // Move past Syntax ID
|
|
|
|
lpReplyIndex[iter].dwLowerLimit = *((LPDWORD) lpByte);
|
|
lpByte += sizeof(DWORD); // Move past Lower Limit
|
|
|
|
lpReplyIndex[iter].dwUpperLimit = *((LPDWORD) lpByte);
|
|
lpByte += sizeof(DWORD); // Move past Upper Limit
|
|
|
|
lpReplyIndex[iter].asn1ID.length = *((LPDWORD) lpByte);
|
|
lpByte += sizeof(DWORD); // Move past ASN.1 ID length
|
|
|
|
RtlCopyMemory( lpReplyIndex[iter].asn1ID.data,
|
|
lpByte,
|
|
sizeof(BYTE) * NDS_MAX_ASN1_NAME_LEN );
|
|
lpByte += sizeof(BYTE) * NDS_MAX_ASN1_NAME_LEN;
|
|
|
|
lpNdsBuffer->dwNumberOfIndexEntries++;
|
|
lpNdsBuffer->dwLengthOfIndexData += sizeof( NDS_ATTR_DEF );
|
|
lpNdsBuffer->dwIndexAvailableBytes -= sizeof( NDS_ATTR_DEF );
|
|
}
|
|
|
|
#if DBG
|
|
if ( lpNdsBuffer->dwLengthOfIndexData != lpNdsBuffer->dwIndexBufferSize )
|
|
{
|
|
KdPrint(( "ASSERT in NDS32: IndexReadAttrDefReplyBuffer\n" ));
|
|
KdPrint(( " lpNdsBuffer->dwLengthOfIndexData !=\n" ));
|
|
KdPrint(( " lpNdsBuffer->dwIndexBufferSize\n" ));
|
|
ASSERT( FALSE );
|
|
}
|
|
#endif
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
DWORD
|
|
IndexReadClassDefReplyBuffer(
|
|
LPNDS_BUFFER lpNdsBuffer )
|
|
{
|
|
LPNDS_CLASS_DEF lpReplyIndex = NULL;
|
|
DWORD iter;
|
|
LPBYTE lpByte = NULL;
|
|
DWORD LengthOfValueStructs;
|
|
DWORD dwStringLen;
|
|
|
|
//
|
|
// Make sure this is set to zero, for NwNdsGetNextXXXXFromBuffer()
|
|
//
|
|
lpNdsBuffer->dwCurrentIndexEntry = 0;
|
|
|
|
//
|
|
// Set values used to track the memory used in the index buffer.
|
|
//
|
|
lpNdsBuffer->dwIndexBufferSize = lpNdsBuffer->dwNumberOfReplyEntries *
|
|
sizeof(NDS_CLASS_DEF);
|
|
lpNdsBuffer->dwIndexAvailableBytes = lpNdsBuffer->dwIndexBufferSize;
|
|
lpNdsBuffer->dwNumberOfIndexEntries = 0;
|
|
lpNdsBuffer->dwLengthOfIndexData = 0;
|
|
|
|
//
|
|
// Create a buffer to hold the ReplyBufferIndex
|
|
//
|
|
lpReplyIndex = (LPNDS_CLASS_DEF)
|
|
LocalAlloc( LPTR,
|
|
lpNdsBuffer->dwIndexBufferSize );
|
|
|
|
//
|
|
// Check that the memory allocation was successful.
|
|
//
|
|
if ( lpReplyIndex == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: IndexReadClassDefReplyBuffer LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
lpNdsBuffer->lpIndexBuffer = (LPBYTE) lpReplyIndex;
|
|
|
|
//
|
|
// Move lpByte so that it points to the SyntaxId of the first attribute
|
|
//
|
|
lpByte = lpNdsBuffer->lpReplyBuffer;
|
|
|
|
// lpByte += sizeof(DWORD); // Move past Completion Code
|
|
// lpByte += sizeof(DWORD); // Move past Iteration Handle
|
|
// lpByte += sizeof(DWORD); // Move past Information Type
|
|
// lpByte += sizeof(DWORD); // Move past Amount Of Attributes
|
|
lpByte += 4 * sizeof(DWORD); // Equivalent to above
|
|
|
|
//
|
|
// In a for loop, walk the index buffer and fill it up with
|
|
// data by referencing the reply buffer. Note references to
|
|
// the syntax buffer are stored as offsets while un-marshalling.
|
|
//
|
|
for ( iter = 0; iter < lpNdsBuffer->dwNumberOfReplyEntries; iter++ )
|
|
{
|
|
dwStringLen = *((LPDWORD) lpByte);
|
|
lpByte += sizeof(DWORD); // Move past Class Name Length
|
|
|
|
lpReplyIndex[iter].szClassName = (LPWSTR) lpByte;
|
|
lpByte += ROUND_UP_COUNT( dwStringLen, ALIGN_DWORD );
|
|
|
|
lpReplyIndex[iter].dwFlags = *((LPDWORD) lpByte);
|
|
lpByte += sizeof(DWORD); // Move past Flags
|
|
|
|
lpReplyIndex[iter].asn1ID.length = *((LPDWORD) lpByte);
|
|
lpByte += sizeof(DWORD); // Move past ASN.1 ID length
|
|
|
|
RtlCopyMemory( lpReplyIndex[iter].asn1ID.data,
|
|
lpByte,
|
|
sizeof(BYTE) * NDS_MAX_ASN1_NAME_LEN );
|
|
lpByte += sizeof(BYTE) * NDS_MAX_ASN1_NAME_LEN;
|
|
|
|
lpReplyIndex[iter].dwNumberOfSuperClasses = *((LPDWORD) lpByte);
|
|
lpByte += sizeof(DWORD);
|
|
|
|
if ( lpReplyIndex[iter].dwNumberOfSuperClasses > 0 )
|
|
{
|
|
if ( VerifyBufferSizeForStringList(
|
|
lpNdsBuffer->dwSyntaxAvailableBytes,
|
|
lpReplyIndex[iter].dwNumberOfSuperClasses,
|
|
&LengthOfValueStructs ) != NO_ERROR )
|
|
{
|
|
if ( AllocateOrIncreaseSyntaxBuffer( lpNdsBuffer, LengthOfValueStructs ) != NO_ERROR )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: IndexReadClassDefReplyBuffer LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
}
|
|
|
|
lpByte += ParseStringListBlob(
|
|
lpByte,
|
|
lpReplyIndex[iter].dwNumberOfSuperClasses,
|
|
(LPVOID) &lpNdsBuffer->lpSyntaxBuffer[lpNdsBuffer->dwLengthOfSyntaxData] );
|
|
|
|
lpReplyIndex[iter].lpSuperClasses =
|
|
(LPWSTR_LIST) lpNdsBuffer->dwLengthOfSyntaxData;
|
|
lpNdsBuffer->dwSyntaxAvailableBytes -= LengthOfValueStructs;
|
|
lpNdsBuffer->dwLengthOfSyntaxData += LengthOfValueStructs;
|
|
}
|
|
else
|
|
{
|
|
lpReplyIndex[iter].lpSuperClasses = NULL;
|
|
}
|
|
|
|
lpReplyIndex[iter].dwNumberOfContainmentClasses = *((LPDWORD) lpByte);
|
|
lpByte += sizeof(DWORD);
|
|
|
|
if ( lpReplyIndex[iter].dwNumberOfContainmentClasses > 0 )
|
|
{
|
|
if ( VerifyBufferSizeForStringList(
|
|
lpNdsBuffer->dwSyntaxAvailableBytes,
|
|
lpReplyIndex[iter].dwNumberOfContainmentClasses,
|
|
&LengthOfValueStructs ) != NO_ERROR )
|
|
{
|
|
if ( AllocateOrIncreaseSyntaxBuffer( lpNdsBuffer, LengthOfValueStructs ) !=
|
|
NO_ERROR )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: IndexReadClassDefReplyBuffer LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
}
|
|
|
|
lpByte += ParseStringListBlob(
|
|
lpByte,
|
|
lpReplyIndex[iter].dwNumberOfContainmentClasses,
|
|
(LPVOID) &lpNdsBuffer->lpSyntaxBuffer[lpNdsBuffer->dwLengthOfSyntaxData] );
|
|
|
|
lpReplyIndex[iter].lpContainmentClasses =
|
|
(LPWSTR_LIST) lpNdsBuffer->dwLengthOfSyntaxData;
|
|
lpNdsBuffer->dwSyntaxAvailableBytes -= LengthOfValueStructs;
|
|
lpNdsBuffer->dwLengthOfSyntaxData += LengthOfValueStructs;
|
|
}
|
|
else
|
|
{
|
|
lpReplyIndex[iter].lpContainmentClasses = NULL;
|
|
}
|
|
|
|
lpReplyIndex[iter].dwNumberOfNamingAttributes = *((LPDWORD) lpByte);
|
|
lpByte += sizeof(DWORD);
|
|
|
|
if ( lpReplyIndex[iter].dwNumberOfNamingAttributes > 0 )
|
|
{
|
|
if ( VerifyBufferSizeForStringList(
|
|
lpNdsBuffer->dwSyntaxAvailableBytes,
|
|
lpReplyIndex[iter].dwNumberOfNamingAttributes,
|
|
&LengthOfValueStructs ) != NO_ERROR )
|
|
{
|
|
if ( AllocateOrIncreaseSyntaxBuffer( lpNdsBuffer, LengthOfValueStructs ) != NO_ERROR )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: IndexReadClassDefReplyBuffer LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
}
|
|
|
|
lpByte += ParseStringListBlob(
|
|
lpByte,
|
|
lpReplyIndex[iter].dwNumberOfNamingAttributes,
|
|
(LPVOID) &lpNdsBuffer->lpSyntaxBuffer[lpNdsBuffer->dwLengthOfSyntaxData] );
|
|
|
|
lpReplyIndex[iter].lpNamingAttributes =
|
|
(LPWSTR_LIST) lpNdsBuffer->dwLengthOfSyntaxData;
|
|
lpNdsBuffer->dwSyntaxAvailableBytes -= LengthOfValueStructs;
|
|
lpNdsBuffer->dwLengthOfSyntaxData += LengthOfValueStructs;
|
|
}
|
|
else
|
|
{
|
|
lpReplyIndex[iter].lpNamingAttributes = NULL;
|
|
}
|
|
|
|
lpReplyIndex[iter].dwNumberOfMandatoryAttributes = *((LPDWORD) lpByte);
|
|
lpByte += sizeof(DWORD);
|
|
|
|
if ( lpReplyIndex[iter].dwNumberOfMandatoryAttributes > 0 )
|
|
{
|
|
if ( VerifyBufferSizeForStringList(
|
|
lpNdsBuffer->dwSyntaxAvailableBytes,
|
|
lpReplyIndex[iter].dwNumberOfMandatoryAttributes,
|
|
&LengthOfValueStructs ) != NO_ERROR )
|
|
{
|
|
if ( AllocateOrIncreaseSyntaxBuffer( lpNdsBuffer, LengthOfValueStructs ) != NO_ERROR )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: IndexReadClassDefReplyBuffer LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
}
|
|
|
|
lpByte += ParseStringListBlob(
|
|
lpByte,
|
|
lpReplyIndex[iter].dwNumberOfMandatoryAttributes,
|
|
(LPVOID) &lpNdsBuffer->lpSyntaxBuffer[lpNdsBuffer->dwLengthOfSyntaxData] );
|
|
|
|
lpReplyIndex[iter].lpMandatoryAttributes =
|
|
(LPWSTR_LIST) lpNdsBuffer->dwLengthOfSyntaxData;
|
|
lpNdsBuffer->dwSyntaxAvailableBytes -= LengthOfValueStructs;
|
|
lpNdsBuffer->dwLengthOfSyntaxData += LengthOfValueStructs;
|
|
}
|
|
else
|
|
{
|
|
lpReplyIndex[iter].lpMandatoryAttributes = NULL;
|
|
}
|
|
|
|
lpReplyIndex[iter].dwNumberOfOptionalAttributes = *((LPDWORD) lpByte);
|
|
lpByte += sizeof(DWORD);
|
|
|
|
if ( lpReplyIndex[iter].dwNumberOfOptionalAttributes > 0 )
|
|
{
|
|
if ( VerifyBufferSizeForStringList(
|
|
lpNdsBuffer->dwSyntaxAvailableBytes,
|
|
lpReplyIndex[iter].dwNumberOfOptionalAttributes,
|
|
&LengthOfValueStructs ) != NO_ERROR )
|
|
{
|
|
if ( AllocateOrIncreaseSyntaxBuffer( lpNdsBuffer, LengthOfValueStructs ) != NO_ERROR )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: IndexReadClassDefReplyBuffer LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
}
|
|
|
|
lpByte += ParseStringListBlob(
|
|
lpByte,
|
|
lpReplyIndex[iter].dwNumberOfOptionalAttributes,
|
|
(LPVOID) &lpNdsBuffer->lpSyntaxBuffer[lpNdsBuffer->dwLengthOfSyntaxData] );
|
|
|
|
lpReplyIndex[iter].lpOptionalAttributes =
|
|
(LPWSTR_LIST) lpNdsBuffer->dwLengthOfSyntaxData;
|
|
lpNdsBuffer->dwSyntaxAvailableBytes -= LengthOfValueStructs;
|
|
lpNdsBuffer->dwLengthOfSyntaxData += LengthOfValueStructs;
|
|
}
|
|
else
|
|
{
|
|
lpReplyIndex[iter].lpOptionalAttributes = NULL;
|
|
}
|
|
|
|
lpNdsBuffer->dwNumberOfIndexEntries++;
|
|
lpNdsBuffer->dwLengthOfIndexData += sizeof( NDS_CLASS_DEF );
|
|
lpNdsBuffer->dwIndexAvailableBytes -= sizeof( NDS_CLASS_DEF );
|
|
}
|
|
|
|
//
|
|
// Now convert all syntax buffer references to pointers.
|
|
//
|
|
for ( iter = 0; iter < lpNdsBuffer->dwNumberOfIndexEntries; iter++ )
|
|
{
|
|
if ( lpReplyIndex[iter].dwNumberOfSuperClasses > 0 )
|
|
{
|
|
(LPBYTE) lpReplyIndex[iter].lpSuperClasses +=
|
|
(DWORD_PTR) lpNdsBuffer->lpSyntaxBuffer;
|
|
}
|
|
|
|
if ( lpReplyIndex[iter].dwNumberOfContainmentClasses > 0 )
|
|
{
|
|
(LPBYTE) lpReplyIndex[iter].lpContainmentClasses +=
|
|
(DWORD_PTR) lpNdsBuffer->lpSyntaxBuffer;
|
|
}
|
|
|
|
if ( lpReplyIndex[iter].dwNumberOfNamingAttributes > 0 )
|
|
{
|
|
(LPBYTE) lpReplyIndex[iter].lpNamingAttributes +=
|
|
(DWORD_PTR) lpNdsBuffer->lpSyntaxBuffer;
|
|
}
|
|
|
|
if ( lpReplyIndex[iter].dwNumberOfMandatoryAttributes > 0 )
|
|
{
|
|
(LPBYTE) lpReplyIndex[iter].lpMandatoryAttributes +=
|
|
(DWORD_PTR) lpNdsBuffer->lpSyntaxBuffer;
|
|
}
|
|
|
|
if ( lpReplyIndex[iter].dwNumberOfOptionalAttributes > 0 )
|
|
{
|
|
(LPBYTE) lpReplyIndex[iter].lpOptionalAttributes +=
|
|
(DWORD_PTR) lpNdsBuffer->lpSyntaxBuffer;
|
|
}
|
|
}
|
|
|
|
#if DBG
|
|
if ( lpNdsBuffer->dwLengthOfIndexData != lpNdsBuffer->dwIndexBufferSize )
|
|
{
|
|
KdPrint(( "ASSERT in NDS32: IndexReadClassDefReplyBuffer\n" ));
|
|
KdPrint(( " lpNdsBuffer->dwLengthOfIndexData !=\n" ));
|
|
KdPrint(( " lpNdsBuffer->dwIndexBufferSize\n" ));
|
|
ASSERT( FALSE );
|
|
}
|
|
#endif
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
DWORD
|
|
IndexReadObjectReplyBuffer(
|
|
LPNDS_BUFFER lpNdsBuffer )
|
|
{
|
|
LPNDS_ATTR_INFO lpReplyIndex = NULL;
|
|
DWORD iter;
|
|
LPBYTE lpByte = NULL;
|
|
DWORD LengthOfValueStructs;
|
|
DWORD dwStringLen;
|
|
|
|
//
|
|
// Make sure this is set to zero, for NwNdsGetNextXXXXFromBuffer()
|
|
//
|
|
lpNdsBuffer->dwCurrentIndexEntry = 0;
|
|
|
|
//
|
|
// Set values used to track the memory used in the index buffer.
|
|
//
|
|
lpNdsBuffer->dwIndexBufferSize = lpNdsBuffer->dwNumberOfReplyEntries *
|
|
sizeof(NDS_ATTR_INFO);
|
|
lpNdsBuffer->dwIndexAvailableBytes = lpNdsBuffer->dwIndexBufferSize;
|
|
lpNdsBuffer->dwNumberOfIndexEntries = 0;
|
|
lpNdsBuffer->dwLengthOfIndexData = 0;
|
|
|
|
//
|
|
// Create a buffer to hold the ReplyBufferIndex
|
|
//
|
|
lpReplyIndex = (LPNDS_ATTR_INFO)
|
|
LocalAlloc( LPTR, lpNdsBuffer->dwIndexBufferSize );
|
|
|
|
//
|
|
// Check that the memory allocation was successful.
|
|
//
|
|
if ( lpReplyIndex == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: IndexReadObjectReplyBuffer LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
lpNdsBuffer->lpIndexBuffer = (LPBYTE) lpReplyIndex;
|
|
|
|
//
|
|
// Move lpByte so that it points to the SyntaxId of the first attribute
|
|
//
|
|
lpByte = lpNdsBuffer->lpReplyBuffer;
|
|
|
|
// lpByte += sizeof(DWORD); // Move past Completion Code
|
|
// lpByte += sizeof(DWORD); // Move past Iteration Handle
|
|
// lpByte += sizeof(DWORD); // Move past Information Type
|
|
// lpByte += sizeof(DWORD); // Move past Amount Of Attributes
|
|
lpByte += 4 * sizeof(DWORD); // Equivalent to above
|
|
|
|
//
|
|
// In a for loop, walk the index buffer and fill it up with
|
|
// data by referencing the reply buffer. Note references to
|
|
// the syntax buffer are stored as offsets while un-marshalling.
|
|
//
|
|
for ( iter = 0; iter < lpNdsBuffer->dwNumberOfReplyEntries; iter++ )
|
|
{
|
|
lpReplyIndex[iter].dwSyntaxId = *((LPDWORD) lpByte);
|
|
lpByte += sizeof(DWORD); // Move past Syntax Id
|
|
|
|
dwStringLen = *((LPDWORD) lpByte);
|
|
lpByte += sizeof(DWORD); // Move past Attribute Name Length
|
|
|
|
lpReplyIndex[iter].szAttributeName = (LPWSTR) lpByte;
|
|
lpByte += ROUND_UP_COUNT( dwStringLen, ALIGN_DWORD );
|
|
|
|
lpReplyIndex[iter].dwNumberOfValues = *((LPDWORD) lpByte);
|
|
lpByte += sizeof(DWORD); // Move past Count Of Values
|
|
|
|
//
|
|
// See if the syntax buffer is large enough to hold the number of
|
|
// SyntaxID structures that will be used to store the value(s)
|
|
// for the current attribute. If the buffer isn't large enough
|
|
// it is reallocated to a bigger size (if possible).
|
|
//
|
|
if ( VerifyBufferSize( lpByte,
|
|
lpNdsBuffer->dwSyntaxAvailableBytes,
|
|
lpReplyIndex[iter].dwSyntaxId,
|
|
lpReplyIndex[iter].dwNumberOfValues,
|
|
&LengthOfValueStructs ) != NO_ERROR )
|
|
{
|
|
if ( AllocateOrIncreaseSyntaxBuffer( lpNdsBuffer, LengthOfValueStructs ) != NO_ERROR )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: IndexReadObjectReplyBuffer LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Parse the raw data buffer by mapping the network structures to
|
|
// the NDS Syntax structures we define in NdsSntx.h. Then move the
|
|
// pointer used to walk the raw data buffer past the ASN.1 Values.
|
|
//
|
|
lpByte += ParseASN1ValueBlob( lpByte,
|
|
lpReplyIndex[iter].dwSyntaxId,
|
|
lpReplyIndex[iter].dwNumberOfValues,
|
|
(LPVOID) &lpNdsBuffer->lpSyntaxBuffer[lpNdsBuffer->dwLengthOfSyntaxData] );
|
|
|
|
lpReplyIndex[iter].lpValue =
|
|
(LPBYTE) lpNdsBuffer->dwLengthOfSyntaxData;
|
|
lpNdsBuffer->dwSyntaxAvailableBytes -= LengthOfValueStructs;
|
|
lpNdsBuffer->dwLengthOfSyntaxData += LengthOfValueStructs;
|
|
|
|
lpNdsBuffer->dwNumberOfIndexEntries++;
|
|
lpNdsBuffer->dwLengthOfIndexData += sizeof( NDS_ATTR_INFO );
|
|
lpNdsBuffer->dwIndexAvailableBytes -= sizeof( NDS_ATTR_INFO );
|
|
}
|
|
|
|
//
|
|
// Now convert all syntax buffer references to pointers.
|
|
//
|
|
for ( iter = 0; iter < lpNdsBuffer->dwNumberOfIndexEntries; iter++ )
|
|
{
|
|
(LPBYTE) lpReplyIndex[iter].lpValue +=
|
|
(DWORD_PTR) lpNdsBuffer->lpSyntaxBuffer;
|
|
}
|
|
|
|
#if DBG
|
|
if ( lpNdsBuffer->dwLengthOfIndexData != lpNdsBuffer->dwIndexBufferSize )
|
|
{
|
|
KdPrint(( "ASSERT in NDS32: IndexReadObjectReplyBuffer\n" ));
|
|
KdPrint(( " lpNdsBuffer->dwLengthOfIndexData !=\n" ));
|
|
KdPrint(( " lpNdsBuffer->dwIndexBufferSize\n" ));
|
|
ASSERT( FALSE );
|
|
}
|
|
#endif
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
DWORD
|
|
IndexReadNameReplyBuffer(
|
|
LPNDS_BUFFER lpNdsBuffer )
|
|
{
|
|
LPNDS_NAME_ONLY lpReplyIndex = NULL;
|
|
DWORD iter;
|
|
LPBYTE lpByte = NULL;
|
|
DWORD dwStringLen;
|
|
|
|
//
|
|
// Make sure this is set to zero, for NwNdsGetNextXXXXFromBuffer()
|
|
//
|
|
lpNdsBuffer->dwCurrentIndexEntry = 0;
|
|
|
|
//
|
|
// Set values used to track the memory used in the index buffer.
|
|
//
|
|
lpNdsBuffer->dwIndexBufferSize = lpNdsBuffer->dwNumberOfReplyEntries *
|
|
sizeof(NDS_NAME_ONLY);
|
|
lpNdsBuffer->dwIndexAvailableBytes = lpNdsBuffer->dwIndexBufferSize;
|
|
lpNdsBuffer->dwNumberOfIndexEntries = 0;
|
|
lpNdsBuffer->dwLengthOfIndexData = 0;
|
|
|
|
//
|
|
// Create a buffer to hold the ReplyBufferIndex
|
|
//
|
|
lpReplyIndex = (LPNDS_NAME_ONLY)
|
|
LocalAlloc( LPTR, lpNdsBuffer->dwIndexBufferSize );
|
|
|
|
//
|
|
// Check that the memory allocation was successful.
|
|
//
|
|
if ( lpReplyIndex == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: IndexReadNameReplyBuffer LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
lpNdsBuffer->lpIndexBuffer = (LPBYTE) lpReplyIndex;
|
|
|
|
//
|
|
// Move lpByte so that it points to the first name
|
|
//
|
|
lpByte = lpNdsBuffer->lpReplyBuffer;
|
|
|
|
// lpByte += sizeof(DWORD); // Move past Completion Code
|
|
// lpByte += sizeof(DWORD); // Move past Iteration Handle
|
|
// lpByte += sizeof(DWORD); // Move past Information Type
|
|
// lpByte += sizeof(DWORD); // Move past Amount Of Attributes
|
|
lpByte += 4 * sizeof(DWORD); // Equivalent to above
|
|
|
|
//
|
|
// In a for loop, walk the reply buffer index and fill it up with
|
|
// data by referencing the Reply buffer or Syntax buffer.
|
|
//
|
|
for ( iter = 0; iter < lpNdsBuffer->dwNumberOfReplyEntries; iter++ )
|
|
{
|
|
dwStringLen = *((LPDWORD) lpByte);
|
|
lpByte += sizeof(DWORD); // Move past Attribute Name Length
|
|
|
|
lpReplyIndex[iter].szName = (LPWSTR) lpByte;
|
|
lpByte += ROUND_UP_COUNT( dwStringLen, ALIGN_DWORD );
|
|
|
|
lpNdsBuffer->dwNumberOfIndexEntries++;
|
|
lpNdsBuffer->dwLengthOfIndexData += sizeof( NDS_NAME_ONLY );
|
|
lpNdsBuffer->dwIndexAvailableBytes -= sizeof( NDS_NAME_ONLY );
|
|
}
|
|
|
|
#if DBG
|
|
if ( lpNdsBuffer->dwLengthOfIndexData != lpNdsBuffer->dwIndexBufferSize )
|
|
{
|
|
KdPrint(( "ASSERT in NDS32: IndexReadNameReplyBuffer\n" ));
|
|
KdPrint(( " lpNdsBuffer->dwLengthOfIndexData !=\n" ));
|
|
KdPrint(( " lpNdsBuffer->dwIndexBufferSize\n" ));
|
|
ASSERT( FALSE );
|
|
}
|
|
#endif
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
DWORD
|
|
IndexSearchObjectReplyBuffer(
|
|
LPNDS_BUFFER lpNdsBuffer )
|
|
{
|
|
LPNDS_OBJECT_INFO lpReplyIndex = NULL;
|
|
DWORD iter;
|
|
DWORD iter2;
|
|
LPBYTE lpByte = NULL;
|
|
DWORD LengthOfValueStructs;
|
|
DWORD dwStringLen;
|
|
LPBYTE FixedPortion;
|
|
LPWSTR EndOfVariableData;
|
|
|
|
//
|
|
// Make sure this is set to zero, for NwNdsGetNextXXXXFromBuffer()
|
|
//
|
|
lpNdsBuffer->dwCurrentIndexEntry = 0;
|
|
|
|
//
|
|
// Set values used to track the memory used in the index buffer.
|
|
//
|
|
lpNdsBuffer->dwIndexBufferSize = lpNdsBuffer->dwNumberOfReplyEntries *
|
|
( sizeof(NDS_OBJECT_INFO) +
|
|
( MAX_NDS_NAME_CHARS * 4 *
|
|
sizeof( WCHAR ) ) );
|
|
lpNdsBuffer->dwIndexAvailableBytes = lpNdsBuffer->dwIndexBufferSize;
|
|
lpNdsBuffer->dwNumberOfIndexEntries = 0;
|
|
lpNdsBuffer->dwLengthOfIndexData = 0;
|
|
|
|
//
|
|
// Create a buffer to hold the ReplyBufferIndex
|
|
//
|
|
lpReplyIndex = (LPNDS_OBJECT_INFO)
|
|
LocalAlloc( LPTR, lpNdsBuffer->dwIndexBufferSize );
|
|
|
|
//
|
|
// Check that the memory allocation was successful.
|
|
//
|
|
if ( lpReplyIndex == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: IndexSearchObjectReplyBuffer LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
lpNdsBuffer->lpIndexBuffer = (LPBYTE) lpReplyIndex;
|
|
|
|
FixedPortion = lpNdsBuffer->lpIndexBuffer;
|
|
EndOfVariableData = (LPWSTR) ((DWORD_PTR) FixedPortion +
|
|
ROUND_DOWN_COUNT(
|
|
lpNdsBuffer->dwIndexAvailableBytes,
|
|
ALIGN_DWORD ) );
|
|
|
|
//
|
|
// Move lpByte so that it points to the first object
|
|
//
|
|
lpByte = lpNdsBuffer->lpReplyBuffer;
|
|
|
|
// lpByte += sizeof(DWORD); // Move past Completion Code
|
|
// lpByte += sizeof(DWORD); // Move past Iteration Handle
|
|
// lpByte += sizeof(DWORD); // Move past Information Type
|
|
// lpByte += sizeof(DWORD); // Move past Amount Of Attributes
|
|
// lpByte += sizeof(DWORD); // Move past Length Of Search
|
|
// lpByte += sizeof(DWORD); // Move past Amount Of Entries
|
|
lpByte += 6 * sizeof(DWORD); // Equivalent to above
|
|
|
|
//
|
|
// In a for loop, walk the reply buffer index and fill it up with
|
|
// data by referencing the Reply buffer or Syntax buffer.
|
|
//
|
|
for ( iter = 0; iter < lpNdsBuffer->dwNumberOfReplyEntries; iter++ )
|
|
{
|
|
WORD tempStrLen;
|
|
LPWSTR newPathStr = NULL;
|
|
LPWSTR tempStr = NULL;
|
|
LPWSTR ClassName;
|
|
LPWSTR DistinguishedObjectName;
|
|
LPWSTR ObjectName;
|
|
DWORD ClassNameLen;
|
|
DWORD DistinguishedObjectNameLen;
|
|
DWORD Flags;
|
|
DWORD SubordinateCount;
|
|
DWORD ModificationTime;
|
|
DWORD NumberOfAttributes = 0;
|
|
LPNDS_ATTR_INFO lpAttributeInfos = NULL;
|
|
DWORD EntryInfo1;
|
|
|
|
//
|
|
// Get current subtree data from lpNdsParentObject
|
|
//
|
|
lpByte = GetSearchResultData( lpByte,
|
|
&Flags,
|
|
&SubordinateCount,
|
|
&ModificationTime,
|
|
&ClassNameLen,
|
|
&ClassName,
|
|
&DistinguishedObjectNameLen,
|
|
&DistinguishedObjectName,
|
|
&EntryInfo1,
|
|
&NumberOfAttributes );
|
|
|
|
//
|
|
// Need to build a string with the new NDS UNC path
|
|
// for search object
|
|
//
|
|
newPathStr = (PVOID) LocalAlloc( LPTR,
|
|
( wcslen( DistinguishedObjectName ) +
|
|
wcslen( lpNdsBuffer->szPath ) +
|
|
3 ) * sizeof( WCHAR ) );
|
|
|
|
if ( newPathStr == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(("NDS32: IndexSearchObjectReplyBuffer LocalAlloc Failed 0x%.8X\n", GetLastError()));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// Need to build a string for the relative object name.
|
|
//
|
|
ObjectName = (PVOID) LocalAlloc( LPTR,
|
|
( wcslen( DistinguishedObjectName ) +
|
|
1 ) * sizeof( WCHAR ) );
|
|
|
|
if ( ObjectName == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(("NDS32: IndexSearchObjectReplyBuffer LocalAlloc Failed 0x%.8X\n", GetLastError()));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
tempStrLen = ParseNdsUncPath( (LPWSTR *) &tempStr,
|
|
lpNdsBuffer->szPath,
|
|
PARSE_NDS_GET_TREE_NAME );
|
|
|
|
tempStrLen /= sizeof(WCHAR);
|
|
|
|
if ( tempStrLen > 0 )
|
|
{
|
|
wcscpy( newPathStr, L"\\\\" );
|
|
wcsncat( newPathStr, tempStr, tempStrLen );
|
|
wcscat( newPathStr, L"\\" );
|
|
wcscat( newPathStr, DistinguishedObjectName );
|
|
_wcsupr( newPathStr );
|
|
}
|
|
else
|
|
{
|
|
wcscpy( newPathStr, L"" );
|
|
}
|
|
|
|
tempStrLen = ParseNdsUncPath( (LPWSTR *) &tempStr,
|
|
newPathStr,
|
|
PARSE_NDS_GET_OBJECT_NAME );
|
|
|
|
tempStrLen /= sizeof(WCHAR);
|
|
|
|
if ( tempStrLen > 0 )
|
|
{
|
|
wcsncpy( ObjectName, tempStr, tempStrLen );
|
|
}
|
|
else
|
|
{
|
|
wcscpy( ObjectName, L"" );
|
|
}
|
|
|
|
if ( lpNdsBuffer->dwReplyInformationType == NDS_INFO_ATTR_NAMES_VALUES )
|
|
{
|
|
lpAttributeInfos = (LPNDS_ATTR_INFO) LocalAlloc(
|
|
LPTR,
|
|
NumberOfAttributes *
|
|
sizeof( NDS_ATTR_INFO )
|
|
);
|
|
|
|
if ( lpAttributeInfos == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(("NDS32: IndexSearchObjectReplyBuffer LocalAlloc Failed 0x%.8X\n", GetLastError()));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
for ( iter2 = 0; iter2 < NumberOfAttributes; iter2++ )
|
|
{
|
|
lpAttributeInfos[iter2].dwSyntaxId = *((LPDWORD) lpByte);
|
|
lpByte += sizeof(DWORD); // Move past Syntax Id
|
|
|
|
dwStringLen = *((LPDWORD) lpByte);
|
|
lpByte += sizeof(DWORD); // Move past Attribute Name Length
|
|
|
|
lpAttributeInfos[iter2].szAttributeName = (LPWSTR) lpByte;
|
|
lpByte += ROUND_UP_COUNT( dwStringLen, ALIGN_DWORD );
|
|
|
|
lpAttributeInfos[iter2].dwNumberOfValues = *((LPDWORD) lpByte);
|
|
lpByte += sizeof(DWORD); // Move past Count Of Values
|
|
|
|
//
|
|
// See if the syntax buffer is large enough to hold the number of
|
|
// SyntaxID structures that will be used to store the value(s)
|
|
// for the current attribute. If the buffer isn't large enough
|
|
// it is reallocated to a bigger size (if possible).
|
|
//
|
|
if ( VerifyBufferSize( lpByte,
|
|
lpNdsBuffer->dwSyntaxAvailableBytes,
|
|
lpAttributeInfos[iter2].dwSyntaxId,
|
|
lpAttributeInfos[iter2].dwNumberOfValues,
|
|
&LengthOfValueStructs ) != NO_ERROR )
|
|
{
|
|
if ( AllocateOrIncreaseSyntaxBuffer( lpNdsBuffer, LengthOfValueStructs ) != NO_ERROR )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: IndexSearchObjectReplyBuffer LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Parse the raw data buffer by mapping the network structures to
|
|
// the NDS Syntax structures we define in NdsSntx.h. Then move the
|
|
// pointer used to walk the raw data buffer past the ASN.1 Values.
|
|
//
|
|
lpByte += ParseASN1ValueBlob( lpByte,
|
|
lpAttributeInfos[iter2].dwSyntaxId,
|
|
lpAttributeInfos[iter2].dwNumberOfValues,
|
|
(LPVOID) &lpNdsBuffer->lpSyntaxBuffer[lpNdsBuffer->dwLengthOfSyntaxData] );
|
|
|
|
lpAttributeInfos[iter2].lpValue =
|
|
(LPBYTE) lpNdsBuffer->dwLengthOfSyntaxData;
|
|
lpNdsBuffer->dwSyntaxAvailableBytes -= LengthOfValueStructs;
|
|
lpNdsBuffer->dwLengthOfSyntaxData += LengthOfValueStructs;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lpAttributeInfos = (LPNDS_ATTR_INFO) LocalAlloc(
|
|
LPTR,
|
|
NumberOfAttributes *
|
|
sizeof( NDS_NAME_ONLY )
|
|
);
|
|
|
|
if ( lpAttributeInfos == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(("NDS32: IndexSearchObjectReplyBuffer LocalAlloc Failed 0x%.8X\n", GetLastError()));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
for ( iter2 = 0; iter2 < NumberOfAttributes; iter2++ )
|
|
{
|
|
dwStringLen = *((LPDWORD) lpByte);
|
|
lpByte += sizeof(DWORD); // Move past Attribute Name Length
|
|
|
|
((LPNDS_NAME_ONLY) lpAttributeInfos)[iter2].szName =
|
|
(LPWSTR) lpByte;
|
|
lpByte += ROUND_UP_COUNT( dwStringLen, ALIGN_DWORD );
|
|
}
|
|
}
|
|
|
|
(void) WriteObjectToBuffer( &FixedPortion,
|
|
&EndOfVariableData,
|
|
newPathStr,
|
|
ObjectName,
|
|
ClassName,
|
|
0, // Don't have this data to write out!
|
|
ModificationTime,
|
|
SubordinateCount,
|
|
NumberOfAttributes,
|
|
lpAttributeInfos );
|
|
|
|
if ( newPathStr )
|
|
{
|
|
(void) LocalFree( (HLOCAL) newPathStr );
|
|
newPathStr = NULL;
|
|
}
|
|
|
|
if ( ObjectName )
|
|
{
|
|
(void) LocalFree( (HLOCAL) ObjectName );
|
|
ObjectName = NULL;
|
|
}
|
|
|
|
lpNdsBuffer->dwNumberOfIndexEntries++;
|
|
lpNdsBuffer->dwLengthOfIndexData += sizeof( NDS_CLASS_DEF );
|
|
lpNdsBuffer->dwIndexAvailableBytes -= sizeof( NDS_CLASS_DEF );
|
|
}
|
|
|
|
|
|
//
|
|
// If the syntax buffer was used for the index, we need to convert
|
|
// offset values to pointers
|
|
//
|
|
if ( lpNdsBuffer->dwReplyInformationType == NDS_INFO_ATTR_NAMES_VALUES )
|
|
{
|
|
for ( iter = 0; iter < lpNdsBuffer->dwNumberOfIndexEntries; iter++ )
|
|
{
|
|
LPNDS_ATTR_INFO lpNdsAttr = (LPNDS_ATTR_INFO)
|
|
lpReplyIndex[iter].lpAttribute;
|
|
|
|
for ( iter2 = 0;
|
|
iter2 < lpReplyIndex[iter].dwNumberOfAttributes;
|
|
iter2++ )
|
|
{
|
|
lpNdsAttr[iter2].lpValue += (DWORD_PTR) lpNdsBuffer->lpSyntaxBuffer;
|
|
}
|
|
}
|
|
}
|
|
|
|
#if DBG
|
|
if ( lpNdsBuffer->dwLengthOfIndexData > lpNdsBuffer->dwIndexBufferSize )
|
|
{
|
|
KdPrint(( "ASSERT in NDS32: IndexSearchObjectReplyBuffer\n" ));
|
|
KdPrint(( " lpNdsBuffer->dwLengthOfIndexData >\n" ));
|
|
KdPrint(( " lpNdsBuffer->dwIndexBufferSize\n" ));
|
|
ASSERT( FALSE );
|
|
}
|
|
#endif
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
DWORD
|
|
SizeOfASN1Structure(
|
|
LPBYTE * lppRawBuffer,
|
|
DWORD dwSyntaxId )
|
|
{
|
|
DWORD dwSize = 0;
|
|
DWORD numFields = 0;
|
|
DWORD StringLen = 0;
|
|
DWORD dwBlobLength = 0;
|
|
LPBYTE lpBlobBeginning = NULL;
|
|
LPBYTE lpRawBuffer = *lppRawBuffer;
|
|
|
|
switch ( dwSyntaxId )
|
|
{
|
|
case NDS_SYNTAX_ID_1 :
|
|
dwSize = sizeof(ASN1_TYPE_1);
|
|
break;
|
|
case NDS_SYNTAX_ID_2 :
|
|
dwSize = sizeof(ASN1_TYPE_2);
|
|
break;
|
|
case NDS_SYNTAX_ID_3 :
|
|
dwSize = sizeof(ASN1_TYPE_3);
|
|
break;
|
|
case NDS_SYNTAX_ID_4 :
|
|
dwSize = sizeof(ASN1_TYPE_4);
|
|
break;
|
|
case NDS_SYNTAX_ID_5 :
|
|
dwSize = sizeof(ASN1_TYPE_5);
|
|
break;
|
|
case NDS_SYNTAX_ID_6 :
|
|
numFields = *(LPDWORD)(lpRawBuffer + sizeof(DWORD));
|
|
dwSize = sizeof(ASN1_TYPE_6)*numFields;
|
|
break;
|
|
case NDS_SYNTAX_ID_7 :
|
|
dwSize = sizeof(ASN1_TYPE_7);
|
|
break;
|
|
case NDS_SYNTAX_ID_8 :
|
|
dwSize = sizeof(ASN1_TYPE_8);
|
|
break;
|
|
case NDS_SYNTAX_ID_9 :
|
|
dwSize = sizeof(ASN1_TYPE_9);
|
|
break;
|
|
case NDS_SYNTAX_ID_10 :
|
|
dwSize = sizeof(ASN1_TYPE_10);
|
|
break;
|
|
case NDS_SYNTAX_ID_11 :
|
|
dwSize = sizeof(ASN1_TYPE_11);
|
|
break;
|
|
case NDS_SYNTAX_ID_12 :
|
|
dwSize = sizeof(ASN1_TYPE_12);
|
|
break;
|
|
case NDS_SYNTAX_ID_13 :
|
|
dwSize = sizeof(ASN1_TYPE_13);
|
|
break;
|
|
case NDS_SYNTAX_ID_14 :
|
|
dwSize = sizeof(ASN1_TYPE_14);
|
|
break;
|
|
case NDS_SYNTAX_ID_15 :
|
|
dwSize = sizeof(ASN1_TYPE_15);
|
|
break;
|
|
case NDS_SYNTAX_ID_16 :
|
|
lpBlobBeginning = lpRawBuffer;
|
|
dwBlobLength = *(LPDWORD)lpRawBuffer*sizeof(BYTE);
|
|
dwBlobLength = ROUND_UP_COUNT( dwBlobLength, ALIGN_DWORD );
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
StringLen = *(LPDWORD)lpRawBuffer;
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
//
|
|
// Skip past ServerName
|
|
//
|
|
lpRawBuffer += ROUND_UP_COUNT( StringLen, ALIGN_DWORD );
|
|
|
|
//
|
|
// Skip past ReplicaType
|
|
//
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
//
|
|
// Skip past ReplicaNumber
|
|
//
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
//
|
|
// Store address count and move past it
|
|
//
|
|
numFields = *(LPDWORD)lpRawBuffer;
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
dwSize = sizeof(ASN1_TYPE_16) - sizeof(ASN1_TYPE_12) +
|
|
( numFields * sizeof(ASN1_TYPE_12) );
|
|
|
|
*lppRawBuffer = lpBlobBeginning + dwBlobLength + sizeof(DWORD);
|
|
break;
|
|
case NDS_SYNTAX_ID_17 :
|
|
dwSize = sizeof(ASN1_TYPE_17);
|
|
break;
|
|
case NDS_SYNTAX_ID_18 :
|
|
dwSize = sizeof(ASN1_TYPE_18);
|
|
break;
|
|
case NDS_SYNTAX_ID_19 :
|
|
dwSize = sizeof(ASN1_TYPE_19);
|
|
break;
|
|
case NDS_SYNTAX_ID_20 :
|
|
dwSize = sizeof(ASN1_TYPE_20);
|
|
break;
|
|
case NDS_SYNTAX_ID_21 :
|
|
dwSize = sizeof(ASN1_TYPE_21);
|
|
break;
|
|
case NDS_SYNTAX_ID_22 :
|
|
dwSize = sizeof(ASN1_TYPE_22);
|
|
break;
|
|
case NDS_SYNTAX_ID_23 :
|
|
dwSize = sizeof(ASN1_TYPE_23);
|
|
break;
|
|
case NDS_SYNTAX_ID_24 :
|
|
dwSize = sizeof(ASN1_TYPE_24);
|
|
break;
|
|
case NDS_SYNTAX_ID_25 :
|
|
dwSize = sizeof(ASN1_TYPE_25);
|
|
break;
|
|
case NDS_SYNTAX_ID_26 :
|
|
dwSize = sizeof(ASN1_TYPE_26);
|
|
break;
|
|
case NDS_SYNTAX_ID_27 :
|
|
dwSize = sizeof(ASN1_TYPE_27);
|
|
break;
|
|
|
|
default :
|
|
KdPrint(( "NDS32: SizeOfASN1Structure() unknown SyntaxId 0x%.8X.\n", dwSyntaxId ));
|
|
ASSERT( FALSE );
|
|
}
|
|
|
|
return dwSize;
|
|
}
|
|
|
|
DWORD
|
|
ParseASN1ValueBlob(
|
|
LPBYTE RawDataBuffer,
|
|
DWORD dwSyntaxId,
|
|
DWORD dwNumberOfValues,
|
|
LPBYTE SyntaxStructure )
|
|
{
|
|
DWORD iter;
|
|
DWORD i;
|
|
DWORD length = 0;
|
|
LPBYTE lpRawBuffer = RawDataBuffer;
|
|
LPBYTE lpSyntaxBuffer = SyntaxStructure;
|
|
DWORD StringLen;
|
|
DWORD numFields;
|
|
DWORD dwBlobLength;
|
|
LPBYTE lpBlobBeginning;
|
|
|
|
for ( iter = 0; iter < dwNumberOfValues; iter++ )
|
|
{
|
|
switch ( dwSyntaxId )
|
|
{
|
|
case NDS_SYNTAX_ID_0 :
|
|
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_1 :
|
|
case NDS_SYNTAX_ID_2 :
|
|
case NDS_SYNTAX_ID_3 :
|
|
case NDS_SYNTAX_ID_4 :
|
|
case NDS_SYNTAX_ID_5 :
|
|
case NDS_SYNTAX_ID_10 :
|
|
case NDS_SYNTAX_ID_20 :
|
|
|
|
StringLen = *(LPDWORD)lpRawBuffer;
|
|
length += sizeof(DWORD);
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
((LPASN1_TYPE_1) lpSyntaxBuffer)->DNString =
|
|
StringLen == 0 ? NULL : (LPWSTR) lpRawBuffer;
|
|
lpSyntaxBuffer += sizeof(ASN1_TYPE_1);
|
|
|
|
length += ROUND_UP_COUNT( StringLen, ALIGN_DWORD );
|
|
lpRawBuffer += ROUND_UP_COUNT( StringLen, ALIGN_DWORD );
|
|
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_6 :
|
|
|
|
lpBlobBeginning = lpRawBuffer;
|
|
dwBlobLength = *(LPDWORD)lpRawBuffer*sizeof(BYTE);
|
|
dwBlobLength = ROUND_UP_COUNT( dwBlobLength, ALIGN_DWORD );
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
numFields = *(LPDWORD)lpRawBuffer;
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
for ( iter = 0; iter < numFields; iter++ )
|
|
{
|
|
StringLen = *(LPDWORD)lpRawBuffer;
|
|
lpRawBuffer += sizeof(DWORD);
|
|
((LPASN1_TYPE_6) lpSyntaxBuffer)->String =
|
|
StringLen == 0 ? NULL : (LPWSTR) lpRawBuffer;
|
|
lpRawBuffer += ROUND_UP_COUNT( StringLen, ALIGN_DWORD );
|
|
|
|
if ( (iter+1) < numFields )
|
|
{
|
|
((LPASN1_TYPE_6) lpSyntaxBuffer)->Next =
|
|
(LPASN1_TYPE_6)
|
|
(lpSyntaxBuffer +
|
|
sizeof(ASN1_TYPE_6) );
|
|
}
|
|
else
|
|
{
|
|
((LPASN1_TYPE_6) lpSyntaxBuffer)->Next = NULL;
|
|
}
|
|
|
|
lpSyntaxBuffer += sizeof(ASN1_TYPE_6);
|
|
}
|
|
|
|
length += dwBlobLength + sizeof(DWORD);
|
|
lpRawBuffer = lpBlobBeginning + dwBlobLength + sizeof(DWORD);
|
|
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_7 :
|
|
|
|
StringLen = *(LPDWORD)lpRawBuffer;
|
|
length += sizeof(DWORD);
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
ASSERT( StringLen == 1 ); // Booleans are sent as a single
|
|
// element DWORD array on the net.
|
|
// Although booleans are only the
|
|
// first single byte value.
|
|
|
|
((LPASN1_TYPE_7) lpSyntaxBuffer)->Boolean = *(LPDWORD)lpRawBuffer;
|
|
lpSyntaxBuffer += sizeof(ASN1_TYPE_7);
|
|
|
|
length += StringLen*sizeof(DWORD);
|
|
lpRawBuffer += StringLen*sizeof(DWORD);
|
|
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_8 :
|
|
case NDS_SYNTAX_ID_22 :
|
|
case NDS_SYNTAX_ID_24 :
|
|
case NDS_SYNTAX_ID_27 :
|
|
|
|
StringLen = *(LPDWORD)lpRawBuffer;
|
|
length += sizeof(DWORD);
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
ASSERT( StringLen == 4 ); // These DWORD values are all sent
|
|
// as a 4 element BYTE array on
|
|
// the net.
|
|
|
|
((LPASN1_TYPE_8) lpSyntaxBuffer)->Integer =
|
|
*(LPDWORD)lpRawBuffer;
|
|
lpSyntaxBuffer += sizeof(ASN1_TYPE_8);
|
|
|
|
length += StringLen*sizeof(BYTE);
|
|
lpRawBuffer += StringLen*sizeof(BYTE);
|
|
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_9 :
|
|
|
|
StringLen = *(LPDWORD)lpRawBuffer;
|
|
length += sizeof(DWORD);
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
((LPASN1_TYPE_9) lpSyntaxBuffer)->Length = StringLen;
|
|
((LPASN1_TYPE_9) lpSyntaxBuffer)->OctetString =
|
|
StringLen == 0 ? NULL : lpRawBuffer;
|
|
lpSyntaxBuffer += sizeof(ASN1_TYPE_9);
|
|
|
|
length += ROUND_UP_COUNT( StringLen, ALIGN_DWORD );
|
|
lpRawBuffer += ROUND_UP_COUNT( StringLen, ALIGN_DWORD );
|
|
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_11 :
|
|
|
|
lpBlobBeginning = lpRawBuffer;
|
|
dwBlobLength = *(LPDWORD)lpRawBuffer*sizeof(BYTE);
|
|
dwBlobLength = ROUND_UP_COUNT( dwBlobLength, ALIGN_DWORD );
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
StringLen = *(LPDWORD)lpRawBuffer;
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
((LPASN1_TYPE_11) lpSyntaxBuffer)->TelephoneNumber =
|
|
StringLen == 0 ? NULL : (LPWSTR) lpRawBuffer;
|
|
lpRawBuffer += ROUND_UP_COUNT( StringLen, ALIGN_DWORD );
|
|
|
|
((LPASN1_TYPE_11) lpSyntaxBuffer)->NumberOfBits =
|
|
*(LPDWORD)lpRawBuffer;
|
|
|
|
if ( ((LPASN1_TYPE_11) lpSyntaxBuffer)->NumberOfBits )
|
|
{
|
|
lpRawBuffer += sizeof(DWORD);
|
|
((LPASN1_TYPE_11) lpSyntaxBuffer)->Parameters = lpRawBuffer;
|
|
}
|
|
else
|
|
{
|
|
((LPASN1_TYPE_11) lpSyntaxBuffer)->Parameters = NULL;
|
|
}
|
|
|
|
lpSyntaxBuffer += sizeof(ASN1_TYPE_11);
|
|
|
|
length += dwBlobLength + sizeof(DWORD);
|
|
lpRawBuffer = lpBlobBeginning + dwBlobLength + sizeof(DWORD);
|
|
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_12 :
|
|
|
|
lpBlobBeginning = lpRawBuffer;
|
|
dwBlobLength = *(LPDWORD)lpRawBuffer*sizeof(BYTE);
|
|
dwBlobLength = ROUND_UP_COUNT( dwBlobLength, ALIGN_DWORD );
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
((LPASN1_TYPE_12) lpSyntaxBuffer)->AddressType =
|
|
*(LPDWORD)lpRawBuffer;
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
StringLen = *(LPDWORD)lpRawBuffer;
|
|
((LPASN1_TYPE_12) lpSyntaxBuffer)->AddressLength = StringLen;
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
((LPASN1_TYPE_12) lpSyntaxBuffer)->Address =
|
|
StringLen == 0 ? NULL : lpRawBuffer;
|
|
lpSyntaxBuffer += sizeof(ASN1_TYPE_12);
|
|
|
|
length += dwBlobLength + sizeof(DWORD);
|
|
lpRawBuffer = lpBlobBeginning + dwBlobLength + sizeof(DWORD);
|
|
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_13 :
|
|
#if DBG
|
|
KdPrint(( "NDS32: ParseASN1ValueBlob() - Don't know how to parse SyntaxId 0x%.8X. Get a sniff and give it to GlennC.\n", dwSyntaxId ));
|
|
ASSERT( FALSE );
|
|
#endif
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_14 :
|
|
|
|
lpBlobBeginning = lpRawBuffer;
|
|
dwBlobLength = *(LPDWORD)lpRawBuffer*sizeof(BYTE);
|
|
dwBlobLength = ROUND_UP_COUNT( dwBlobLength, ALIGN_DWORD );
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
((LPASN1_TYPE_14) lpSyntaxBuffer)->Type =
|
|
*(LPDWORD)lpRawBuffer;
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
StringLen = *(LPDWORD)lpRawBuffer;
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
((LPASN1_TYPE_14) lpSyntaxBuffer)->Address =
|
|
StringLen == 0 ? NULL : (LPWSTR) lpRawBuffer;
|
|
lpSyntaxBuffer += sizeof(ASN1_TYPE_14);
|
|
|
|
length += dwBlobLength + sizeof(DWORD);
|
|
lpRawBuffer = lpBlobBeginning + dwBlobLength + sizeof(DWORD);
|
|
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_15 :
|
|
|
|
lpBlobBeginning = lpRawBuffer;
|
|
dwBlobLength = *(LPDWORD)lpRawBuffer*sizeof(BYTE);
|
|
dwBlobLength = ROUND_UP_COUNT( dwBlobLength, ALIGN_DWORD );
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
((LPASN1_TYPE_15) lpSyntaxBuffer)->Type =
|
|
*(LPDWORD)lpRawBuffer;
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
StringLen = *(LPDWORD)lpRawBuffer;
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
((LPASN1_TYPE_15) lpSyntaxBuffer)->VolumeName =
|
|
StringLen == 0 ? NULL : (LPWSTR) lpRawBuffer;
|
|
lpRawBuffer += ROUND_UP_COUNT( StringLen, ALIGN_DWORD );
|
|
|
|
StringLen = *(LPDWORD)lpRawBuffer;
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
((LPASN1_TYPE_15) lpSyntaxBuffer)->Path =
|
|
StringLen == 0 ? NULL : (LPWSTR) lpRawBuffer;
|
|
lpSyntaxBuffer += sizeof(ASN1_TYPE_15);
|
|
|
|
length += dwBlobLength + sizeof(DWORD);
|
|
lpRawBuffer = lpBlobBeginning + dwBlobLength + sizeof(DWORD);
|
|
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_16 :
|
|
|
|
lpBlobBeginning = lpRawBuffer;
|
|
dwBlobLength = *(LPDWORD)lpRawBuffer*sizeof(BYTE);
|
|
dwBlobLength = ROUND_UP_COUNT( dwBlobLength, ALIGN_DWORD );
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
StringLen = *(LPDWORD)lpRawBuffer;
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
((LPASN1_TYPE_16) lpSyntaxBuffer)->ServerName =
|
|
StringLen == 0 ? NULL : (LPWSTR) lpRawBuffer;
|
|
lpRawBuffer += ROUND_UP_COUNT( StringLen, ALIGN_DWORD );
|
|
|
|
((LPASN1_TYPE_16) lpSyntaxBuffer)->ReplicaType =
|
|
*(LPDWORD)lpRawBuffer;
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
((LPASN1_TYPE_16) lpSyntaxBuffer)->ReplicaNumber =
|
|
*(LPDWORD)lpRawBuffer;
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
((LPASN1_TYPE_16) lpSyntaxBuffer)->Count =
|
|
*(LPDWORD)lpRawBuffer;
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
for ( i=0; i < ((LPASN1_TYPE_16) lpSyntaxBuffer)->Count; i++ )
|
|
{
|
|
((LPASN1_TYPE_16) lpSyntaxBuffer)->ReplicaAddressHint[i].AddressType = *(LPDWORD)lpRawBuffer;
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
StringLen = *(LPDWORD)lpRawBuffer;
|
|
((LPASN1_TYPE_16) lpSyntaxBuffer)->ReplicaAddressHint[i].AddressLength = StringLen;
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
((LPASN1_TYPE_16) lpSyntaxBuffer)->ReplicaAddressHint[i].Address = StringLen == 0 ? NULL : lpRawBuffer;
|
|
lpRawBuffer += ROUND_UP_COUNT( StringLen, ALIGN_DWORD );
|
|
}
|
|
|
|
lpSyntaxBuffer += sizeof(ASN1_TYPE_16) -
|
|
sizeof(ASN1_TYPE_12) +
|
|
( ((LPASN1_TYPE_16) lpSyntaxBuffer)->Count*
|
|
sizeof(ASN1_TYPE_12) );
|
|
|
|
length += dwBlobLength + sizeof(DWORD);
|
|
lpRawBuffer = lpBlobBeginning + dwBlobLength + sizeof(DWORD);
|
|
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_17 :
|
|
|
|
lpBlobBeginning = lpRawBuffer;
|
|
dwBlobLength = *(LPDWORD)lpRawBuffer*sizeof(BYTE);
|
|
dwBlobLength = ROUND_UP_COUNT( dwBlobLength, ALIGN_DWORD );
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
StringLen = *(LPDWORD)lpRawBuffer;
|
|
lpRawBuffer += sizeof(DWORD);
|
|
((LPASN1_TYPE_17) lpSyntaxBuffer)->ProtectedAttrName =
|
|
StringLen == 0 ? NULL : (LPWSTR) lpRawBuffer;
|
|
lpRawBuffer += ROUND_UP_COUNT( StringLen, ALIGN_DWORD );
|
|
|
|
StringLen = *(LPDWORD)lpRawBuffer;
|
|
lpRawBuffer += sizeof(DWORD);
|
|
((LPASN1_TYPE_17) lpSyntaxBuffer)->SubjectName =
|
|
StringLen == 0 ? NULL : (LPWSTR) lpRawBuffer;
|
|
lpRawBuffer += ROUND_UP_COUNT( StringLen, ALIGN_DWORD );
|
|
|
|
((LPASN1_TYPE_17) lpSyntaxBuffer)->Privileges =
|
|
*(LPDWORD)lpRawBuffer;
|
|
lpSyntaxBuffer += sizeof(ASN1_TYPE_17);
|
|
|
|
length += dwBlobLength + sizeof(DWORD);
|
|
lpRawBuffer = lpBlobBeginning + dwBlobLength + sizeof(DWORD);
|
|
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_18 :
|
|
|
|
lpBlobBeginning = lpRawBuffer;
|
|
dwBlobLength = *(LPDWORD)lpRawBuffer*sizeof(BYTE);
|
|
dwBlobLength = ROUND_UP_COUNT( dwBlobLength, ALIGN_DWORD );
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
numFields = *(LPDWORD)lpRawBuffer;
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
for ( i = 0; i < numFields; i++ )
|
|
{
|
|
StringLen = *(LPDWORD)lpRawBuffer;
|
|
lpRawBuffer += sizeof(DWORD);
|
|
((LPASN1_TYPE_18) lpSyntaxBuffer)->PostalAddress[i] =
|
|
StringLen == 0 ? NULL : (LPWSTR) lpRawBuffer;
|
|
lpRawBuffer += ROUND_UP_COUNT( StringLen, ALIGN_DWORD );
|
|
}
|
|
|
|
lpSyntaxBuffer += sizeof(ASN1_TYPE_18);
|
|
|
|
length += dwBlobLength + sizeof(DWORD);
|
|
lpRawBuffer = lpBlobBeginning + dwBlobLength + sizeof(DWORD);
|
|
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_19 :
|
|
|
|
lpBlobBeginning = lpRawBuffer;
|
|
dwBlobLength = *(LPDWORD)lpRawBuffer*sizeof(BYTE);
|
|
dwBlobLength = ROUND_UP_COUNT( dwBlobLength, ALIGN_DWORD );
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
((LPASN1_TYPE_19) lpSyntaxBuffer)->WholeSeconds =
|
|
*(LPDWORD)lpRawBuffer;
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
((LPASN1_TYPE_19) lpSyntaxBuffer)->EventID =
|
|
*(LPDWORD)lpRawBuffer;
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
lpSyntaxBuffer += sizeof(ASN1_TYPE_19);
|
|
|
|
length += dwBlobLength + sizeof(DWORD);
|
|
lpRawBuffer = lpBlobBeginning + dwBlobLength + sizeof(DWORD);
|
|
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_21 :
|
|
|
|
((LPASN1_TYPE_21) lpSyntaxBuffer)->Length =
|
|
*(LPDWORD)lpRawBuffer;
|
|
lpSyntaxBuffer += sizeof(ASN1_TYPE_21);
|
|
|
|
length += sizeof(DWORD);
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_23 :
|
|
|
|
lpBlobBeginning = lpRawBuffer;
|
|
dwBlobLength = *(LPDWORD)lpRawBuffer*sizeof(BYTE);
|
|
dwBlobLength = ROUND_UP_COUNT( dwBlobLength, ALIGN_DWORD );
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
((LPASN1_TYPE_23) lpSyntaxBuffer)->RemoteID =
|
|
*(LPDWORD)lpRawBuffer;
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
StringLen = *(LPDWORD)lpRawBuffer;
|
|
lpRawBuffer += sizeof(DWORD);
|
|
((LPASN1_TYPE_23) lpSyntaxBuffer)->ObjectName =
|
|
StringLen == 0 ? NULL : (LPWSTR) lpRawBuffer;
|
|
lpRawBuffer += ROUND_UP_COUNT( StringLen, ALIGN_DWORD );
|
|
|
|
lpSyntaxBuffer += sizeof(ASN1_TYPE_23);
|
|
|
|
length += dwBlobLength + sizeof(DWORD);
|
|
lpRawBuffer = lpBlobBeginning + dwBlobLength + sizeof(DWORD);
|
|
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_25 :
|
|
|
|
lpBlobBeginning = lpRawBuffer;
|
|
dwBlobLength = *(LPDWORD)lpRawBuffer*sizeof(BYTE);
|
|
dwBlobLength = ROUND_UP_COUNT( dwBlobLength, ALIGN_DWORD );
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
((LPASN1_TYPE_25) lpSyntaxBuffer)->Level =
|
|
*(LPDWORD)lpRawBuffer;
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
((LPASN1_TYPE_25) lpSyntaxBuffer)->Interval =
|
|
*(LPDWORD)lpRawBuffer;
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
StringLen = *(LPDWORD)lpRawBuffer;
|
|
lpRawBuffer += sizeof(DWORD);
|
|
((LPASN1_TYPE_25) lpSyntaxBuffer)->ObjectName =
|
|
StringLen == 0 ? NULL : (LPWSTR) lpRawBuffer;
|
|
lpRawBuffer += ROUND_UP_COUNT( StringLen, ALIGN_DWORD );
|
|
|
|
lpSyntaxBuffer += sizeof(ASN1_TYPE_25);
|
|
length += dwBlobLength + sizeof(DWORD);
|
|
lpRawBuffer = lpBlobBeginning + dwBlobLength + sizeof(DWORD);
|
|
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_26 :
|
|
|
|
lpBlobBeginning = lpRawBuffer;
|
|
dwBlobLength = *(LPDWORD)lpRawBuffer*sizeof(BYTE);
|
|
dwBlobLength = ROUND_UP_COUNT( dwBlobLength, ALIGN_DWORD );
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
StringLen = *(LPDWORD)lpRawBuffer;
|
|
lpRawBuffer += sizeof(DWORD);
|
|
((LPASN1_TYPE_26) lpSyntaxBuffer)->ObjectName =
|
|
StringLen == 0 ? NULL : (LPWSTR) lpRawBuffer;
|
|
lpRawBuffer += ROUND_UP_COUNT( StringLen, ALIGN_DWORD );
|
|
|
|
((LPASN1_TYPE_26) lpSyntaxBuffer)->Amount =
|
|
*(LPDWORD)lpRawBuffer;
|
|
lpRawBuffer += sizeof(DWORD);
|
|
|
|
lpSyntaxBuffer += sizeof(ASN1_TYPE_26);
|
|
|
|
length += dwBlobLength + sizeof(DWORD);
|
|
lpRawBuffer = lpBlobBeginning + dwBlobLength + sizeof(DWORD);
|
|
|
|
break;
|
|
|
|
default :
|
|
#if DBG
|
|
KdPrint(( "NDS32: ParseASN1ValueBlob() unknown SyntaxId 0x%.8X.\n", dwSyntaxId ));
|
|
ASSERT( FALSE );
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return length;
|
|
}
|
|
|
|
|
|
DWORD
|
|
ParseStringListBlob(
|
|
LPBYTE RawDataBuffer,
|
|
DWORD dwNumberOfStrings,
|
|
LPBYTE SyntaxStructure )
|
|
{
|
|
DWORD iter;
|
|
DWORD length = 0;
|
|
LPBYTE lpRawBuffer = RawDataBuffer;
|
|
LPBYTE lpSyntaxBuffer = SyntaxStructure;
|
|
DWORD StringLen;
|
|
|
|
for ( iter = 0; iter < dwNumberOfStrings; iter++ )
|
|
{
|
|
StringLen = *(LPDWORD)lpRawBuffer;
|
|
lpRawBuffer += sizeof(DWORD);
|
|
length += sizeof(DWORD);
|
|
((LPASN1_TYPE_6) lpSyntaxBuffer)->String =
|
|
StringLen == 0 ? NULL : (LPWSTR) lpRawBuffer;
|
|
lpRawBuffer += ROUND_UP_COUNT( StringLen, ALIGN_DWORD );
|
|
length += ROUND_UP_COUNT( StringLen, ALIGN_DWORD );
|
|
|
|
if ( (iter+1) < dwNumberOfStrings )
|
|
{
|
|
((LPASN1_TYPE_6) lpSyntaxBuffer)->Next = (LPASN1_TYPE_6)
|
|
(lpSyntaxBuffer +
|
|
sizeof(ASN1_TYPE_6) );
|
|
}
|
|
else
|
|
{
|
|
((LPASN1_TYPE_6) lpSyntaxBuffer)->Next = NULL;
|
|
}
|
|
|
|
lpSyntaxBuffer += sizeof(ASN1_TYPE_6);
|
|
}
|
|
|
|
return length;
|
|
}
|
|
|
|
|
|
WORD
|
|
ParseNdsUncPath(
|
|
IN OUT LPWSTR * lpszResult,
|
|
IN LPWSTR szObjectPathName,
|
|
IN DWORD flag )
|
|
{
|
|
unsigned short length = 2;
|
|
unsigned short totalLength = (USHORT) wcslen( szObjectPathName );
|
|
|
|
if ( totalLength < 2 )
|
|
return 0;
|
|
|
|
//
|
|
// Get length to indicate the character in the string that indicates the
|
|
// "\" in between the tree name and the rest of the UNC path.
|
|
//
|
|
// Example: \\<tree name>\<path to object>[\|.]<object>
|
|
// ^
|
|
// |
|
|
//
|
|
while ( length < totalLength && szObjectPathName[length] != L'\\' )
|
|
{
|
|
length++;
|
|
}
|
|
|
|
if ( flag == PARSE_NDS_GET_TREE_NAME )
|
|
{
|
|
*lpszResult = (LPWSTR) ( szObjectPathName + 2 );
|
|
|
|
return ( length - 2 ) * sizeof(WCHAR); // Take off 2 for the two \\'s
|
|
}
|
|
|
|
if ( flag == PARSE_NDS_GET_PATH_NAME && length == totalLength )
|
|
{
|
|
*lpszResult = szObjectPathName;
|
|
|
|
return 0;
|
|
}
|
|
|
|
if ( flag == PARSE_NDS_GET_PATH_NAME )
|
|
{
|
|
*lpszResult = szObjectPathName + length + 1;
|
|
|
|
return ( totalLength - length - 1 ) * sizeof(WCHAR);
|
|
}
|
|
|
|
if ( flag == PARSE_NDS_GET_OBJECT_NAME )
|
|
{
|
|
unsigned short ObjectNameLength = 0;
|
|
|
|
*lpszResult = szObjectPathName + length + 1;
|
|
|
|
length++;
|
|
|
|
while ( length < totalLength && szObjectPathName[length] != L'.' )
|
|
{
|
|
length++;
|
|
ObjectNameLength++;
|
|
}
|
|
|
|
return ObjectNameLength * sizeof(WCHAR);
|
|
}
|
|
|
|
*lpszResult = szObjectPathName + totalLength - 1;
|
|
length = 1;
|
|
|
|
while ( *lpszResult[0] != L'\\' )
|
|
{
|
|
(*lpszResult)--;
|
|
length++;
|
|
}
|
|
|
|
(*lpszResult)++;
|
|
length--;
|
|
|
|
return length * sizeof(WCHAR);
|
|
}
|
|
|
|
|
|
DWORD
|
|
ReadAttrDef_AllAttrs(
|
|
IN HANDLE hTree,
|
|
IN DWORD dwInformationType,
|
|
OUT HANDLE * lphOperationData )
|
|
{
|
|
DWORD status;
|
|
DWORD nwstatus;
|
|
NTSTATUS ntstatus;
|
|
LPNDS_BUFFER lpNdsBuffer = NULL;
|
|
DWORD dwReplyLength;
|
|
LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hTree;
|
|
DWORD dwIterHandle = NDS_NO_MORE_ITERATIONS;
|
|
DWORD dwNumEntries = 0;
|
|
DWORD dwCurrNumEntries = 0;
|
|
DWORD dwCurrBuffSize = 0;
|
|
DWORD dwCopyOffset = 0;
|
|
PVOID lpCurrBuff = NULL;
|
|
PVOID lpTempBuff = NULL;
|
|
DWORD dwInfoType = dwInformationType;
|
|
|
|
*lphOperationData = NULL;
|
|
|
|
status = NwNdsCreateBuffer( NDS_SCHEMA_READ_ATTR_DEF,
|
|
(HANDLE *) &lpNdsBuffer );
|
|
|
|
if ( status )
|
|
{
|
|
goto ErrorExit;
|
|
}
|
|
|
|
lpNdsBuffer->lpReplyBuffer = NULL;
|
|
lpNdsBuffer->dwReplyBufferSize = 0;
|
|
|
|
//
|
|
// Reasonable guess is that the response buffer needs to be 8K bytes.
|
|
//
|
|
dwCurrBuffSize = NDS_MAX_BUFFER;
|
|
|
|
lpCurrBuff = (PVOID) LocalAlloc( LPTR, dwCurrBuffSize );
|
|
|
|
//
|
|
// Check that the memory allocation was successful.
|
|
//
|
|
if ( lpCurrBuff == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadAttrDef_AllAttrs LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
do
|
|
{
|
|
SendRequest:
|
|
ntstatus = FragExWithWait( lpNdsObject->NdsTree,
|
|
NETWARE_NDS_FUNCTION_READ_ATTR_DEF,
|
|
lpCurrBuff,
|
|
dwCurrBuffSize,
|
|
&dwReplyLength,
|
|
"DDDDD",
|
|
0, // Version
|
|
dwIterHandle, // Initial iteration
|
|
dwInformationType,
|
|
(DWORD) TRUE, // All attributes indicator
|
|
0 ); // Number of attribute names
|
|
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadAttrDef_AllAttrs: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
ntstatus = ParseResponse( lpCurrBuff,
|
|
dwReplyLength,
|
|
"GD",
|
|
&nwstatus );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadAttrDef_AllAttrs: The read object response was undecipherable.\n" ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
if ( nwstatus )
|
|
{
|
|
if (nwstatus == NDS_ERR_INSUFFICIENT_BUFFER)
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadAttrDef_AllAttrs - NDS_ERR_INSUFFICIENT_BUFFER - doubling size from %ld\n", dwCurrBuffSize ));
|
|
#endif
|
|
//
|
|
// The buffer was too small, make it twice as big.
|
|
//
|
|
if ( dwCurrBuffSize <= THIRY_TWO_KB)
|
|
{ // NDS_MAX_BUFFER = 0xFC00
|
|
dwCurrBuffSize *= 2;
|
|
if (dwCurrBuffSize > NDS_MAX_BUFFER)
|
|
dwCurrBuffSize = NDS_MAX_BUFFER;
|
|
lpTempBuff = (PVOID) LocalAlloc(LPTR, dwCurrBuffSize);
|
|
if (lpTempBuff)
|
|
{
|
|
(void) LocalFree((HLOCAL) lpCurrBuff);
|
|
lpCurrBuff = lpTempBuff;
|
|
lpTempBuff = NULL;
|
|
// Error cancels iteration, so reset any previously read responses and start over
|
|
dwIterHandle = NDS_NO_MORE_ITERATIONS;
|
|
if (lpNdsBuffer->lpReplyBuffer)
|
|
{
|
|
(void) LocalFree((HLOCAL) lpNdsBuffer->lpReplyBuffer);
|
|
lpNdsBuffer->lpReplyBuffer = NULL;
|
|
lpNdsBuffer->dwReplyBufferSize = 0;
|
|
dwNumEntries = 0;
|
|
}
|
|
goto SendRequest;
|
|
}
|
|
#if DBG
|
|
else {
|
|
KdPrint(( "NDS32: ReadAttrDef_AllAttrs - Buffer ReAlloc failed to increase to %ld\n", dwCurrBuffSize ));
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadAttrDef_AllAttrs - NetWare error 0x%.8X.\n", nwstatus ));
|
|
#endif
|
|
SetLastError( MapNetwareErrorCode( nwstatus ) );
|
|
status = nwstatus;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
ntstatus = ParseResponse( (BYTE *) lpCurrBuff,
|
|
dwReplyLength,
|
|
"G_DDD",
|
|
sizeof(DWORD),
|
|
&dwIterHandle,
|
|
&dwInfoType,
|
|
&dwCurrNumEntries );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadAttrDef_AllAttrs: The read object response was undecipherable.\n" ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
if ( lpNdsBuffer->lpReplyBuffer == NULL) // first time through
|
|
{
|
|
dwCopyOffset = 0; // we want the entire buffer the first time
|
|
lpTempBuff = (PVOID) LocalAlloc( LPTR, dwCurrBuffSize ); // Allocate new reply buffer
|
|
}
|
|
else
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadAttrDef_AllAttrs - subsequent iteration, ReplyBuffer now %ld\n", lpNdsBuffer->dwReplyBufferSize + dwCurrBuffSize - dwCopyOffset ));
|
|
#endif
|
|
dwCopyOffset = 4 * sizeof(DWORD); // skip the response code, iteration handle, etc. on subsequent iterations
|
|
lpTempBuff = (PVOID) LocalAlloc (LPTR, lpNdsBuffer->dwReplyBufferSize + dwCurrBuffSize - dwCopyOffset);
|
|
// grow reply buffer to hold additional data
|
|
if (lpTempBuff)
|
|
{
|
|
RtlCopyMemory( lpTempBuff, lpNdsBuffer->lpReplyBuffer, lpNdsBuffer->dwReplyBufferSize);
|
|
(void) LocalFree((HLOCAL) lpNdsBuffer->lpReplyBuffer);
|
|
}
|
|
}
|
|
if (lpTempBuff == NULL)
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadAttrDef_AllAttrs LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
goto ErrorExit;
|
|
}
|
|
RtlCopyMemory( (LPBYTE) ((LPBYTE) (lpTempBuff) + lpNdsBuffer->dwReplyBufferSize),
|
|
(LPBYTE) ((LPBYTE) (lpCurrBuff) + dwCopyOffset),
|
|
(dwCurrBuffSize - dwCopyOffset) );
|
|
lpNdsBuffer->lpReplyBuffer = lpTempBuff;
|
|
lpNdsBuffer->dwReplyBufferSize += (ROUND_UP_COUNT( dwReplyLength, ALIGN_DWORD ) - dwCopyOffset);
|
|
dwNumEntries += dwCurrNumEntries;
|
|
RtlZeroMemory(lpCurrBuff, dwCurrBuffSize);
|
|
} while ( dwIterHandle != NDS_NO_MORE_ITERATIONS );
|
|
|
|
lpNdsBuffer->dwNumberOfReplyEntries = dwNumEntries;
|
|
lpNdsBuffer->dwReplyInformationType = dwInfoType;
|
|
*lphOperationData = lpNdsBuffer;
|
|
(void) LocalFree( (HLOCAL) lpCurrBuff );
|
|
|
|
return NO_ERROR;
|
|
|
|
ErrorExit :
|
|
|
|
if ( lpCurrBuff )
|
|
{
|
|
(void) LocalFree( (HLOCAL) lpCurrBuff );
|
|
lpCurrBuff = NULL;
|
|
}
|
|
if ( lpNdsBuffer )
|
|
{
|
|
(void) NwNdsFreeBuffer( (HANDLE) lpNdsBuffer );
|
|
lpNdsBuffer = NULL;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
DWORD
|
|
ReadAttrDef_SomeAttrs(
|
|
IN HANDLE hTree,
|
|
IN DWORD dwInformationType,
|
|
IN OUT HANDLE * lphOperationData )
|
|
{
|
|
DWORD status;
|
|
DWORD nwstatus;
|
|
NTSTATUS ntstatus;
|
|
LPNDS_BUFFER lpNdsBuffer = (LPNDS_BUFFER) *lphOperationData;
|
|
DWORD dwReplyLength;
|
|
LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hTree;
|
|
DWORD dwIterHandle = NDS_NO_MORE_ITERATIONS;
|
|
DWORD dwInfoType = dwInformationType;
|
|
DWORD dwNumEntries = 0;
|
|
DWORD dwCurrNumEntries = 0;
|
|
DWORD dwCurrBuffSize = 0;
|
|
DWORD dwCopyOffset = 0;
|
|
PVOID lpCurrBuff = NULL;
|
|
PVOID lpTempBuff = NULL;
|
|
|
|
if ( lpNdsBuffer->dwOperation != NDS_SCHEMA_READ_ATTR_DEF )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// Check to see if this buffer has already been used for a read reply.
|
|
//
|
|
if ( lpNdsBuffer->lpReplyBuffer )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
lpNdsBuffer->dwReplyBufferSize = 0;
|
|
|
|
//
|
|
// Reasonable guess is that the response buffer needs to be 8K bytes.
|
|
//
|
|
dwCurrBuffSize = NDS_MAX_BUFFER;
|
|
|
|
lpCurrBuff = (PVOID) LocalAlloc( LPTR, dwCurrBuffSize );
|
|
|
|
//
|
|
// Check that the memory allocation was successful.
|
|
//
|
|
if ( lpCurrBuff == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadAttrDef_SomeAttrs LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
do
|
|
{
|
|
SendRequest:
|
|
ntstatus = FragExWithWait( lpNdsObject->NdsTree,
|
|
NETWARE_NDS_FUNCTION_READ_ATTR_DEF,
|
|
lpCurrBuff,
|
|
dwCurrBuffSize,
|
|
&dwReplyLength,
|
|
"DDDDDr",
|
|
0, // Version
|
|
dwIterHandle, // Initial iteration
|
|
dwInformationType,
|
|
(DWORD) FALSE, // All attributes indicator
|
|
lpNdsBuffer->dwNumberOfRequestEntries,
|
|
lpNdsBuffer->lpRequestBuffer,
|
|
(WORD)lpNdsBuffer->dwLengthOfRequestData );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadAttrDef_SomeAttrs: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
ntstatus = ParseResponse( lpCurrBuff,
|
|
dwReplyLength,
|
|
"GD",
|
|
&nwstatus );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadAttrDef_SomeAttrs: The read object response was undecipherable.\n" ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
if ( nwstatus )
|
|
{
|
|
if (nwstatus == NDS_ERR_INSUFFICIENT_BUFFER)
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadAttrDef_SomeAttrs - NDS_ERR_INSUFFICIENT_BUFFER - doubling size from %ld\n", dwCurrBuffSize ));
|
|
#endif
|
|
//
|
|
// The buffer was too small, make it twice as big.
|
|
//
|
|
if ( dwCurrBuffSize <= THIRY_TWO_KB)
|
|
{ // NDS_MAX_BUFFER = 0xFC00
|
|
dwCurrBuffSize *= 2;
|
|
if (dwCurrBuffSize > NDS_MAX_BUFFER)
|
|
dwCurrBuffSize = NDS_MAX_BUFFER;
|
|
lpTempBuff = (PVOID) LocalAlloc(LPTR, dwCurrBuffSize);
|
|
if (lpTempBuff)
|
|
{
|
|
(void) LocalFree((HLOCAL) lpCurrBuff);
|
|
lpCurrBuff = lpTempBuff;
|
|
lpTempBuff = NULL;
|
|
// Error cancels iteration, so reset any previously read responses and start over
|
|
dwIterHandle = NDS_NO_MORE_ITERATIONS;
|
|
if (lpNdsBuffer->lpReplyBuffer)
|
|
{
|
|
(void) LocalFree((HLOCAL) lpNdsBuffer->lpReplyBuffer);
|
|
lpNdsBuffer->lpReplyBuffer = NULL;
|
|
lpNdsBuffer->dwReplyBufferSize = 0;
|
|
dwNumEntries = 0;
|
|
}
|
|
goto SendRequest;
|
|
}
|
|
#if DBG
|
|
else {
|
|
KdPrint(( "NDS32: ReadAttrDef_SomeAttrs - Buffer ReAlloc failed to increase to %ld\n", dwCurrBuffSize ));
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadAttrDef_SomeAttrs - NetWare error 0x%.8X.\n", nwstatus ));
|
|
#endif
|
|
SetLastError( MapNetwareErrorCode( nwstatus ) );
|
|
status = nwstatus;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
ntstatus = ParseResponse( (BYTE *) lpCurrBuff,
|
|
dwReplyLength,
|
|
"G_DDD",
|
|
sizeof(DWORD),
|
|
&dwIterHandle,
|
|
&dwInfoType,
|
|
&dwCurrNumEntries );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadAttrDef_SomeAttrs: The read object response was undecipherable.\n" ));
|
|
#endif
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
if ( lpNdsBuffer->lpReplyBuffer == NULL) // first time through
|
|
{
|
|
dwCopyOffset = 0; // we want the entire buffer the first time
|
|
lpTempBuff = (PVOID) LocalAlloc( LPTR, dwCurrBuffSize ); // Allocate new reply buffer
|
|
}
|
|
else
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadAttrDef_SomeAttrs - subsequent iteration, ReplyBuffer now %ld\n", lpNdsBuffer->dwReplyBufferSize + dwCurrBuffSize - dwCopyOffset ));
|
|
#endif
|
|
dwCopyOffset = 4 * sizeof(DWORD); // skip the response code, iteration handle, etc. on subsequent iterations
|
|
lpTempBuff = (PVOID) LocalAlloc (LPTR, lpNdsBuffer->dwReplyBufferSize + dwCurrBuffSize - dwCopyOffset);
|
|
// grow reply buffer to hold additional data
|
|
if (lpTempBuff)
|
|
{
|
|
RtlCopyMemory( lpTempBuff, lpNdsBuffer->lpReplyBuffer, lpNdsBuffer->dwReplyBufferSize);
|
|
(void) LocalFree((HLOCAL) lpNdsBuffer->lpReplyBuffer);
|
|
}
|
|
}
|
|
if (lpTempBuff == NULL)
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadAttrDef_SomeAttrs LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
goto ErrorExit;
|
|
}
|
|
RtlCopyMemory( (LPBYTE) ((LPBYTE) (lpTempBuff) + lpNdsBuffer->dwReplyBufferSize),
|
|
(LPBYTE) ((LPBYTE) (lpCurrBuff) + dwCopyOffset),
|
|
(dwCurrBuffSize - dwCopyOffset) );
|
|
lpNdsBuffer->lpReplyBuffer = lpTempBuff;
|
|
lpNdsBuffer->dwReplyBufferSize += (ROUND_UP_COUNT( dwReplyLength, ALIGN_DWORD ) - dwCopyOffset);
|
|
dwNumEntries += dwCurrNumEntries;
|
|
RtlZeroMemory(lpCurrBuff, dwCurrBuffSize);
|
|
} while ( dwIterHandle != NDS_NO_MORE_ITERATIONS );
|
|
|
|
lpNdsBuffer->dwNumberOfReplyEntries = dwNumEntries;
|
|
lpNdsBuffer->dwReplyInformationType = dwInfoType;
|
|
(void) LocalFree( (HLOCAL) lpCurrBuff );
|
|
|
|
return NO_ERROR;
|
|
|
|
ErrorExit :
|
|
|
|
if ( lpCurrBuff )
|
|
{
|
|
(void) LocalFree( (HLOCAL) lpCurrBuff );
|
|
lpCurrBuff = NULL;
|
|
}
|
|
if ( lpNdsBuffer->lpReplyBuffer )
|
|
{
|
|
(void) LocalFree( (HLOCAL) lpNdsBuffer->lpReplyBuffer );
|
|
lpNdsBuffer->lpReplyBuffer = NULL;
|
|
lpNdsBuffer->dwReplyBufferSize = 0;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
DWORD
|
|
ReadClassDef_AllClasses(
|
|
IN HANDLE hTree,
|
|
IN DWORD dwInformationType,
|
|
OUT HANDLE * lphOperationData )
|
|
{
|
|
DWORD status;
|
|
DWORD nwstatus;
|
|
NTSTATUS ntstatus;
|
|
LPNDS_BUFFER lpNdsBuffer = NULL;
|
|
DWORD dwReplyLength;
|
|
LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hTree;
|
|
DWORD dwIterHandle = NDS_NO_MORE_ITERATIONS;
|
|
DWORD dwNumEntries = 0;
|
|
DWORD dwCurrNumEntries = 0;
|
|
DWORD dwCurrBuffSize = 0;
|
|
DWORD dwCopyOffset = 0;
|
|
PVOID lpCurrBuff = NULL;
|
|
PVOID lpTempBuff = NULL;
|
|
DWORD dwInfoType = dwInformationType;
|
|
|
|
*lphOperationData = NULL;
|
|
|
|
status = NwNdsCreateBuffer( NDS_SCHEMA_READ_CLASS_DEF,
|
|
(HANDLE *) &lpNdsBuffer );
|
|
|
|
if ( status )
|
|
{
|
|
goto ErrorExit;
|
|
}
|
|
|
|
lpNdsBuffer->lpReplyBuffer = NULL;
|
|
lpNdsBuffer->dwReplyBufferSize = 0;
|
|
|
|
//
|
|
// Reasonable guess is that the response buffer needs to be 16K bytes.
|
|
//
|
|
dwCurrBuffSize = NDS_MAX_BUFFER;
|
|
|
|
lpCurrBuff = (PVOID) LocalAlloc( LPTR, dwCurrBuffSize );
|
|
|
|
//
|
|
// Check that the memory allocation was successful.
|
|
//
|
|
if ( lpCurrBuff == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadClassDef_AllClasses LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
do
|
|
{
|
|
SendRequest:
|
|
ntstatus = FragExWithWait( lpNdsObject->NdsTree,
|
|
NETWARE_NDS_FUNCTION_READ_CLASS_DEF,
|
|
lpCurrBuff,
|
|
dwCurrBuffSize,
|
|
&dwReplyLength,
|
|
"DDDDD",
|
|
0, // Version
|
|
dwIterHandle, // Initial iteration
|
|
dwInformationType,
|
|
(DWORD) TRUE, // All attributes indicator
|
|
0 ); // Number of attribute names
|
|
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadClassDef_AllClasses: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
ntstatus = ParseResponse( lpCurrBuff,
|
|
dwReplyLength,
|
|
"GD",
|
|
&nwstatus );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadClassDef_AllClasses: The read response was undecipherable.\n" ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
if ( nwstatus )
|
|
{
|
|
if (nwstatus == NDS_ERR_INSUFFICIENT_BUFFER)
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadClassDef_AllClasses - NDS_ERR_INSUFFICIENT_BUFFER - doubling size from %ld\n", dwCurrBuffSize ));
|
|
#endif
|
|
//
|
|
// The buffer was too small, make it twice as big.
|
|
//
|
|
if ( dwCurrBuffSize <= THIRY_TWO_KB)
|
|
{ // NDS_MAX_BUFFER = 0xFC00
|
|
dwCurrBuffSize *= 2;
|
|
if (dwCurrBuffSize > NDS_MAX_BUFFER)
|
|
dwCurrBuffSize = NDS_MAX_BUFFER;
|
|
lpTempBuff = (PVOID) LocalAlloc(LPTR, dwCurrBuffSize);
|
|
if (lpTempBuff)
|
|
{
|
|
(void) LocalFree((HLOCAL) lpCurrBuff);
|
|
lpCurrBuff = lpTempBuff;
|
|
lpTempBuff = NULL;
|
|
// Error cancels iteration, so reset any previously read responses and start over
|
|
dwIterHandle = NDS_NO_MORE_ITERATIONS;
|
|
if (lpNdsBuffer->lpReplyBuffer)
|
|
{
|
|
(void) LocalFree((HLOCAL) lpNdsBuffer->lpReplyBuffer);
|
|
lpNdsBuffer->lpReplyBuffer = NULL;
|
|
lpNdsBuffer->dwReplyBufferSize = 0;
|
|
dwNumEntries = 0;
|
|
}
|
|
goto SendRequest;
|
|
}
|
|
#if DBG
|
|
else {
|
|
KdPrint(( "NDS32: ReadClassDef_AllClasses - Buffer ReAlloc failed to increase to %ld\n", dwCurrBuffSize ));
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadClassDef_AllClasses - NetWare error 0x%.8X.\n", nwstatus ));
|
|
#endif
|
|
SetLastError( MapNetwareErrorCode( nwstatus ) );
|
|
status = nwstatus;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
ntstatus = ParseResponse( (BYTE *) lpCurrBuff,
|
|
dwReplyLength,
|
|
"G_DDD",
|
|
sizeof(DWORD),
|
|
&dwIterHandle,
|
|
&dwInfoType,
|
|
&dwCurrNumEntries );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadClassDef_AllClasses: The read object response was undecipherable.\n" ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
if ( lpNdsBuffer->lpReplyBuffer == NULL) // first time through
|
|
{
|
|
dwCopyOffset = 0; // we want the entire buffer the first time
|
|
lpTempBuff = (PVOID) LocalAlloc( LPTR, dwCurrBuffSize ); // Allocate new reply buffer
|
|
}
|
|
else
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadClassDef_AllClasses - subsequent iteration, ReplyBuffer now %ld\n", lpNdsBuffer->dwReplyBufferSize + dwCurrBuffSize - dwCopyOffset ));
|
|
#endif
|
|
dwCopyOffset = 4 * sizeof(DWORD); // skip the response code, iteration handle, etc. on subsequent iterations
|
|
lpTempBuff = (PVOID) LocalAlloc (LPTR, lpNdsBuffer->dwReplyBufferSize + dwCurrBuffSize - dwCopyOffset);
|
|
// grow reply buffer to hold additional data
|
|
if (lpTempBuff)
|
|
{
|
|
RtlCopyMemory( lpTempBuff, lpNdsBuffer->lpReplyBuffer, lpNdsBuffer->dwReplyBufferSize);
|
|
(void) LocalFree((HLOCAL) lpNdsBuffer->lpReplyBuffer);
|
|
}
|
|
}
|
|
if (lpTempBuff == NULL)
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadClassDef_AllClasses LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
goto ErrorExit;
|
|
}
|
|
RtlCopyMemory( (LPBYTE) ((LPBYTE) (lpTempBuff) + lpNdsBuffer->dwReplyBufferSize),
|
|
(LPBYTE) ((LPBYTE) (lpCurrBuff) + dwCopyOffset),
|
|
(dwCurrBuffSize - dwCopyOffset) );
|
|
lpNdsBuffer->lpReplyBuffer = lpTempBuff;
|
|
lpNdsBuffer->dwReplyBufferSize += ROUND_UP_COUNT( dwReplyLength, ALIGN_DWORD ) - dwCopyOffset;
|
|
dwNumEntries += dwCurrNumEntries;
|
|
RtlZeroMemory(lpCurrBuff, dwCurrBuffSize);
|
|
} while ( dwIterHandle != NDS_NO_MORE_ITERATIONS );
|
|
|
|
lpNdsBuffer->dwNumberOfReplyEntries = dwNumEntries;
|
|
lpNdsBuffer->dwReplyInformationType = dwInfoType;
|
|
*lphOperationData = lpNdsBuffer;
|
|
(void) LocalFree( (HLOCAL) lpCurrBuff );
|
|
|
|
return NO_ERROR;
|
|
|
|
ErrorExit :
|
|
|
|
if ( lpCurrBuff )
|
|
{
|
|
(void) LocalFree( (HLOCAL) lpCurrBuff );
|
|
lpCurrBuff = NULL;
|
|
}
|
|
if ( lpNdsBuffer )
|
|
{
|
|
(void) NwNdsFreeBuffer( (HANDLE) lpNdsBuffer );
|
|
lpNdsBuffer = NULL;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
DWORD
|
|
ReadClassDef_SomeClasses(
|
|
IN HANDLE hTree,
|
|
IN DWORD dwInformationType,
|
|
IN OUT HANDLE * lphOperationData )
|
|
{
|
|
DWORD status;
|
|
DWORD nwstatus;
|
|
NTSTATUS ntstatus;
|
|
LPNDS_BUFFER lpNdsBuffer = (LPNDS_BUFFER) *lphOperationData;
|
|
DWORD dwReplyLength;
|
|
LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hTree;
|
|
DWORD dwIterHandle = NDS_NO_MORE_ITERATIONS;
|
|
DWORD dwInfoType = dwInformationType;
|
|
DWORD dwNumEntries = 0;
|
|
DWORD dwCurrNumEntries = 0;
|
|
DWORD dwCurrBuffSize = 0;
|
|
DWORD dwCopyOffset = 0;
|
|
PVOID lpCurrBuff = NULL;
|
|
PVOID lpTempBuff = NULL;
|
|
|
|
if ( lpNdsBuffer->dwOperation != NDS_SCHEMA_READ_CLASS_DEF )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// Check to see if this buffer has already been used for a read reply.
|
|
//
|
|
if ( lpNdsBuffer->lpReplyBuffer )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
lpNdsBuffer->dwReplyBufferSize = 0;
|
|
|
|
//
|
|
// Reasonable guess is that the response buffer needs to be 16K bytes.
|
|
//
|
|
dwCurrBuffSize = NDS_MAX_BUFFER;
|
|
|
|
lpCurrBuff = (PVOID) LocalAlloc( LPTR, dwCurrBuffSize );
|
|
|
|
//
|
|
// Check that the memory allocation was successful.
|
|
//
|
|
if ( lpCurrBuff == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadClassDef_SomeClasses LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
do
|
|
{
|
|
SendRequest:
|
|
ntstatus = FragExWithWait( lpNdsObject->NdsTree,
|
|
NETWARE_NDS_FUNCTION_READ_CLASS_DEF,
|
|
lpCurrBuff,
|
|
dwCurrBuffSize,
|
|
&dwReplyLength,
|
|
"DDDDDr",
|
|
0, // Version
|
|
dwIterHandle, // Initial iteration
|
|
dwInformationType,
|
|
(DWORD) FALSE, // All attributes indicator
|
|
lpNdsBuffer->dwNumberOfRequestEntries,
|
|
lpNdsBuffer->lpRequestBuffer,
|
|
(WORD)lpNdsBuffer->dwLengthOfRequestData );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadClassDef_SomeClasses: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
ntstatus = ParseResponse( lpCurrBuff,
|
|
dwReplyLength,
|
|
"GD",
|
|
&nwstatus );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadClassDef_SomeClasses: The read object response was undecipherable.\n" ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
if ( nwstatus )
|
|
{
|
|
if (nwstatus == NDS_ERR_INSUFFICIENT_BUFFER)
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadClassDef_SomeClasses - NDS_ERR_INSUFFICIENT_BUFFER - doubling size from %ld\n", dwCurrBuffSize ));
|
|
#endif
|
|
//
|
|
// The buffer was too small, make it twice as big.
|
|
//
|
|
if ( dwCurrBuffSize <= THIRY_TWO_KB)
|
|
{ // NDS_MAX_BUFFER = 0xFC00
|
|
dwCurrBuffSize *= 2;
|
|
if (dwCurrBuffSize > NDS_MAX_BUFFER)
|
|
dwCurrBuffSize = NDS_MAX_BUFFER;
|
|
lpTempBuff = (PVOID) LocalAlloc(LPTR, dwCurrBuffSize);
|
|
if (lpTempBuff)
|
|
{
|
|
(void) LocalFree((HLOCAL) lpCurrBuff);
|
|
lpCurrBuff = lpTempBuff;
|
|
lpTempBuff = NULL;
|
|
// Error cancels iteration, so reset any previously read responses and start over
|
|
dwIterHandle = NDS_NO_MORE_ITERATIONS;
|
|
if (lpNdsBuffer->lpReplyBuffer)
|
|
{
|
|
(void) LocalFree((HLOCAL) lpNdsBuffer->lpReplyBuffer);
|
|
lpNdsBuffer->lpReplyBuffer = NULL;
|
|
lpNdsBuffer->dwReplyBufferSize = 0;
|
|
dwNumEntries = 0;
|
|
}
|
|
goto SendRequest;
|
|
}
|
|
#if DBG
|
|
else {
|
|
KdPrint(( "NDS32: ReadClassDef_SomeClasses - Buffer ReAlloc failed to increase to %ld\n", dwCurrBuffSize ));
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadClassDef_SomeClasses - NetWare error 0x%.8X.\n", nwstatus ));
|
|
#endif
|
|
SetLastError( MapNetwareErrorCode( nwstatus ) );
|
|
status = nwstatus;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
ntstatus = ParseResponse( (BYTE *) lpCurrBuff,
|
|
dwReplyLength,
|
|
"G_DDD",
|
|
sizeof(DWORD),
|
|
&dwIterHandle,
|
|
&dwInfoType,
|
|
&dwCurrNumEntries );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadClassDef_SomeClasses: The read object response was undecipherable.\n" ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
if ( lpNdsBuffer->lpReplyBuffer == NULL) // first time through
|
|
{
|
|
dwCopyOffset = 0; // we want the entire buffer the first time
|
|
lpTempBuff = (PVOID) LocalAlloc( LPTR, dwCurrBuffSize ); // Allocate new reply buffer
|
|
}
|
|
else
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadClassDef_SomeClasses - subsequent iteration, ReplyBuffer now %ld\n", lpNdsBuffer->dwReplyBufferSize + dwCurrBuffSize - dwCopyOffset ));
|
|
#endif
|
|
dwCopyOffset = 4 * sizeof(DWORD); // skip the response code, iteration handle, etc. on subsequent iterations
|
|
lpTempBuff = (PVOID) LocalAlloc (LPTR, lpNdsBuffer->dwReplyBufferSize + dwCurrBuffSize - dwCopyOffset);
|
|
// grow reply buffer to hold additional data
|
|
if (lpTempBuff)
|
|
{
|
|
RtlCopyMemory( lpTempBuff, lpNdsBuffer->lpReplyBuffer, lpNdsBuffer->dwReplyBufferSize);
|
|
(void) LocalFree((HLOCAL) lpNdsBuffer->lpReplyBuffer);
|
|
}
|
|
}
|
|
if (lpTempBuff == NULL)
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadClassDef_SomeClasses LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
goto ErrorExit;
|
|
}
|
|
RtlCopyMemory( (LPBYTE) ((LPBYTE) (lpTempBuff) + lpNdsBuffer->dwReplyBufferSize),
|
|
(LPBYTE) ((LPBYTE) (lpCurrBuff) + dwCopyOffset),
|
|
(dwCurrBuffSize - dwCopyOffset) );
|
|
lpNdsBuffer->lpReplyBuffer = lpTempBuff;
|
|
lpNdsBuffer->dwReplyBufferSize += (ROUND_UP_COUNT( dwReplyLength, ALIGN_DWORD ) - dwCopyOffset);
|
|
dwNumEntries += dwCurrNumEntries;
|
|
RtlZeroMemory(lpCurrBuff, dwCurrBuffSize);
|
|
} while ( dwIterHandle != NDS_NO_MORE_ITERATIONS );
|
|
|
|
lpNdsBuffer->dwNumberOfReplyEntries = dwNumEntries;
|
|
lpNdsBuffer->dwReplyInformationType = dwInfoType;
|
|
(void) LocalFree( (HLOCAL) lpCurrBuff );
|
|
|
|
return NO_ERROR;
|
|
|
|
ErrorExit :
|
|
|
|
if ( lpCurrBuff )
|
|
{
|
|
(void) LocalFree( (HLOCAL) lpCurrBuff );
|
|
lpCurrBuff = NULL;
|
|
}
|
|
if ( lpNdsBuffer->lpReplyBuffer )
|
|
{
|
|
(void) LocalFree( (HLOCAL) lpNdsBuffer->lpReplyBuffer );
|
|
lpNdsBuffer->lpReplyBuffer = NULL;
|
|
lpNdsBuffer->dwReplyBufferSize = 0;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
DWORD
|
|
ReadObject_AllAttrs(
|
|
IN HANDLE hObject,
|
|
IN DWORD dwInformationType,
|
|
OUT HANDLE * lphOperationData )
|
|
{
|
|
DWORD status;
|
|
DWORD nwstatus;
|
|
NTSTATUS ntstatus;
|
|
LPNDS_BUFFER lpNdsBuffer = NULL;
|
|
DWORD dwReplyLength;
|
|
LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hObject;
|
|
DWORD dwIterHandle = NDS_NO_MORE_ITERATIONS;
|
|
DWORD dwNumEntries = 0;
|
|
DWORD dwCurrNumEntries = 0;
|
|
DWORD dwCurrBuffSize = 0;
|
|
DWORD dwCopyOffset = 0;
|
|
PVOID lpCurrBuff = NULL;
|
|
PVOID lpTempBuff = NULL;
|
|
DWORD dwInfoType = dwInformationType;
|
|
|
|
if ( lpNdsObject->Signature != NDS_SIGNATURE )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
status = NwNdsCreateBuffer( NDS_OBJECT_READ,
|
|
(HANDLE *) &lpNdsBuffer );
|
|
|
|
if ( status )
|
|
{
|
|
goto ErrorExit;
|
|
}
|
|
|
|
lpNdsBuffer->lpReplyBuffer = NULL;
|
|
lpNdsBuffer->dwReplyBufferSize = 0;
|
|
|
|
//
|
|
// We're asking for all attribute values, so let's start with max buffer to avoid iterations.
|
|
//
|
|
dwCurrBuffSize = NDS_MAX_BUFFER;
|
|
|
|
lpCurrBuff = (PVOID) LocalAlloc( LPTR, dwCurrBuffSize );
|
|
|
|
//
|
|
// Check that the memory allocation was successful.
|
|
//
|
|
if ( lpCurrBuff == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadObject_AllAttrs LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
do
|
|
{
|
|
ntstatus = FragExWithWait( lpNdsObject->NdsTree,
|
|
NETWARE_NDS_FUNCTION_READ_OBJECT,
|
|
lpCurrBuff,
|
|
dwCurrBuffSize,
|
|
&dwReplyLength,
|
|
"DDDDDD",
|
|
0, // Version
|
|
dwIterHandle, // Initial iteration
|
|
lpNdsObject->ObjectId, // Id of the object
|
|
dwInformationType,
|
|
(DWORD) TRUE, // All attributes indicator
|
|
0 ); // Number of attribute names
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadObject_AllAttrs: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
ntstatus = ParseResponse( lpCurrBuff,
|
|
dwReplyLength,
|
|
"GD",
|
|
&nwstatus );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadObject_AllAttrs: The read object response was undecipherable.\n" ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
if ( nwstatus )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadObject_AllAttrs - NetWare error 0x%.8X.\n", nwstatus ));
|
|
#endif
|
|
SetLastError( MapNetwareErrorCode( nwstatus ) );
|
|
status = nwstatus;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
ntstatus = ParseResponse( (BYTE *) lpCurrBuff,
|
|
dwReplyLength,
|
|
"G_DDD",
|
|
sizeof(DWORD),
|
|
&dwIterHandle,
|
|
&dwInfoType,
|
|
&dwCurrNumEntries );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadObject_AllAttrs: The read object response was undecipherable.\n" ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
if ( lpNdsBuffer->lpReplyBuffer == NULL) // first time through
|
|
{
|
|
dwCopyOffset = 0; // we want the entire buffer the first time
|
|
lpTempBuff = (PVOID) LocalAlloc( LPTR, dwCurrBuffSize ); // Allocate new reply buffer
|
|
}
|
|
else
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadObject_AllAttrs - subsequent iteration, ReplyBuffer now %ld\n", lpNdsBuffer->dwReplyBufferSize + dwCurrBuffSize - dwCopyOffset ));
|
|
#endif
|
|
dwCopyOffset = 4 * sizeof(DWORD); // skip the response code, iteration handle, etc. on subsequent iterations
|
|
lpTempBuff = (PVOID) LocalAlloc (LPTR, lpNdsBuffer->dwReplyBufferSize + dwCurrBuffSize - dwCopyOffset);
|
|
// grow reply buffer to hold additional data
|
|
if (lpTempBuff)
|
|
{
|
|
RtlCopyMemory( lpTempBuff, lpNdsBuffer->lpReplyBuffer, lpNdsBuffer->dwReplyBufferSize);
|
|
(void) LocalFree((HLOCAL) lpNdsBuffer->lpReplyBuffer);
|
|
}
|
|
}
|
|
if (lpTempBuff == NULL)
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadObject_AllAttrs LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
goto ErrorExit;
|
|
}
|
|
RtlCopyMemory( (LPBYTE) ((LPBYTE) (lpTempBuff) + lpNdsBuffer->dwReplyBufferSize),
|
|
(LPBYTE) ((LPBYTE) (lpCurrBuff) + dwCopyOffset),
|
|
(dwCurrBuffSize - dwCopyOffset) );
|
|
lpNdsBuffer->lpReplyBuffer = lpTempBuff;
|
|
lpNdsBuffer->dwReplyBufferSize += (ROUND_UP_COUNT( dwReplyLength, ALIGN_DWORD ) - dwCopyOffset);
|
|
dwNumEntries += dwCurrNumEntries;
|
|
RtlZeroMemory(lpCurrBuff, dwCurrBuffSize);
|
|
} while ( dwIterHandle != NDS_NO_MORE_ITERATIONS );
|
|
|
|
lpNdsBuffer->dwNumberOfReplyEntries = dwNumEntries;
|
|
lpNdsBuffer->dwReplyInformationType = dwInfoType;
|
|
*lphOperationData = lpNdsBuffer;
|
|
(void) LocalFree( (HLOCAL) lpCurrBuff );
|
|
|
|
return NO_ERROR;
|
|
|
|
ErrorExit :
|
|
|
|
if ( lpCurrBuff )
|
|
{
|
|
(void) LocalFree( (HLOCAL) lpCurrBuff );
|
|
lpCurrBuff = NULL;
|
|
}
|
|
if ( lpNdsBuffer )
|
|
{
|
|
(void) NwNdsFreeBuffer( (HANDLE) lpNdsBuffer );
|
|
lpNdsBuffer = NULL;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
DWORD
|
|
ReadObject_SomeAttrs(
|
|
IN HANDLE hObject,
|
|
IN DWORD dwInformationType,
|
|
IN OUT HANDLE * lphOperationData )
|
|
{
|
|
DWORD status;
|
|
DWORD nwstatus;
|
|
NTSTATUS ntstatus;
|
|
LPNDS_BUFFER lpNdsBuffer = (LPNDS_BUFFER) *lphOperationData;
|
|
DWORD dwReplyLength;
|
|
LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hObject;
|
|
DWORD dwIterHandle = NDS_NO_MORE_ITERATIONS;
|
|
DWORD dwInfoType = dwInformationType;
|
|
DWORD dwNumEntries = 0;
|
|
DWORD dwCurrNumEntries = 0;
|
|
DWORD dwCurrBuffSize = 0;
|
|
DWORD dwCopyOffset = 0;
|
|
PVOID lpCurrBuff = NULL;
|
|
PVOID lpTempBuff = NULL;
|
|
|
|
if ( lpNdsObject->Signature != NDS_SIGNATURE )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
if ( lpNdsBuffer->dwOperation != NDS_OBJECT_READ )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// Check to see if this buffer has already been used for a read reply.
|
|
//
|
|
if ( lpNdsBuffer->lpReplyBuffer )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
lpNdsBuffer->dwReplyBufferSize = 0;
|
|
|
|
//
|
|
// We may be asking for all values, so let's start with max buffer to avoid iterations.
|
|
//
|
|
dwCurrBuffSize = NDS_MAX_BUFFER;
|
|
|
|
lpCurrBuff = (PVOID) LocalAlloc( LPTR, dwCurrBuffSize );
|
|
|
|
//
|
|
// Check that the memory allocation was successful.
|
|
//
|
|
if ( lpCurrBuff == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadObject_SomeAttrs LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
do
|
|
{
|
|
ntstatus = FragExWithWait( lpNdsObject->NdsTree,
|
|
NETWARE_NDS_FUNCTION_READ_OBJECT,
|
|
lpCurrBuff,
|
|
dwCurrBuffSize,
|
|
&dwReplyLength,
|
|
"DDDDDDr",
|
|
0, // Version
|
|
dwIterHandle, // Initial iteration
|
|
lpNdsObject->ObjectId, // Id of the object
|
|
dwInformationType,
|
|
(DWORD) FALSE, // All attributes indicator
|
|
lpNdsBuffer->dwNumberOfRequestEntries,
|
|
lpNdsBuffer->lpRequestBuffer, // Object info
|
|
(WORD)lpNdsBuffer->dwLengthOfRequestData );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadObject_SomeAttrs: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
ntstatus = ParseResponse( (BYTE *) lpCurrBuff,
|
|
dwReplyLength,
|
|
"GD",
|
|
&nwstatus );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadObject_SomeAttrs: The read object response was undecipherable.\n" ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
if ( nwstatus )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadClassDef_SomeClasses - NetWare error 0x%.8X.\n", nwstatus ));
|
|
#endif
|
|
SetLastError( MapNetwareErrorCode( nwstatus ) );
|
|
status = nwstatus;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
ntstatus = ParseResponse( (BYTE *) lpCurrBuff,
|
|
dwReplyLength,
|
|
"G_DDD",
|
|
sizeof(DWORD),
|
|
&dwIterHandle,
|
|
&dwInfoType,
|
|
&dwCurrNumEntries );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadObject_SomeAttrs: The read object response was undecipherable.\n" ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
if ( lpNdsBuffer->lpReplyBuffer == NULL) // first time through
|
|
{
|
|
dwCopyOffset = 0; // we want the entire buffer the first time
|
|
lpTempBuff = (PVOID) LocalAlloc( LPTR, dwCurrBuffSize ); // Allocate new reply buffer
|
|
}
|
|
else
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadObject_SomeAttrs - subsequent iteration, ReplyBuffer now %ld\n", lpNdsBuffer->dwReplyBufferSize + dwCurrBuffSize - dwCopyOffset ));
|
|
#endif
|
|
dwCopyOffset = 4 * sizeof(DWORD); // skip the response code, iteration handle, etc. on subsequent iterations
|
|
lpTempBuff = (PVOID) LocalAlloc (LPTR, lpNdsBuffer->dwReplyBufferSize + dwCurrBuffSize - dwCopyOffset);
|
|
// grow reply buffer to hold additional data
|
|
if (lpTempBuff)
|
|
{
|
|
RtlCopyMemory( lpTempBuff, lpNdsBuffer->lpReplyBuffer, lpNdsBuffer->dwReplyBufferSize);
|
|
(void) LocalFree((HLOCAL) lpNdsBuffer->lpReplyBuffer);
|
|
}
|
|
}
|
|
if (lpTempBuff == NULL)
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadObject_SomeAttrs LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
goto ErrorExit;
|
|
}
|
|
RtlCopyMemory( (LPBYTE) ((LPBYTE) (lpTempBuff) + lpNdsBuffer->dwReplyBufferSize),
|
|
(LPBYTE) ((LPBYTE) (lpCurrBuff) + dwCopyOffset),
|
|
(dwCurrBuffSize - dwCopyOffset) );
|
|
lpNdsBuffer->lpReplyBuffer = lpTempBuff;
|
|
lpNdsBuffer->dwReplyBufferSize += (ROUND_UP_COUNT( dwReplyLength, ALIGN_DWORD ) - dwCopyOffset);
|
|
dwNumEntries += dwCurrNumEntries;
|
|
RtlZeroMemory(lpCurrBuff, dwCurrBuffSize);
|
|
} while ( dwIterHandle != NDS_NO_MORE_ITERATIONS );
|
|
|
|
lpNdsBuffer->dwNumberOfReplyEntries = dwNumEntries;
|
|
lpNdsBuffer->dwReplyInformationType = dwInfoType;
|
|
(void) LocalFree( (HLOCAL) lpCurrBuff );
|
|
|
|
return NO_ERROR;
|
|
|
|
ErrorExit :
|
|
|
|
if ( lpCurrBuff )
|
|
{
|
|
(void) LocalFree( (HLOCAL) lpCurrBuff );
|
|
lpCurrBuff = NULL;
|
|
}
|
|
if ( lpNdsBuffer->lpReplyBuffer )
|
|
{
|
|
(void) LocalFree( (HLOCAL) lpNdsBuffer->lpReplyBuffer );
|
|
lpNdsBuffer->lpReplyBuffer = NULL;
|
|
lpNdsBuffer->dwReplyBufferSize = 0;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
DWORD
|
|
Search_AllAttrs(
|
|
IN HANDLE hStartFromObject,
|
|
IN DWORD dwInformationType,
|
|
IN DWORD dwScope,
|
|
IN BOOL fDerefAliases,
|
|
IN LPQUERY_TREE lpQueryTree,
|
|
IN OUT LPDWORD lpdwIterHandle,
|
|
IN OUT HANDLE * lphOperationData )
|
|
{
|
|
DWORD status;
|
|
DWORD nwstatus;
|
|
NTSTATUS ntstatus;
|
|
LPNDS_BUFFER lpNdsBuffer = NULL;
|
|
LPNDS_BUFFER lpNdsQueryTreeBuffer = NULL;
|
|
DWORD dwReplyLength;
|
|
LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hStartFromObject;
|
|
DWORD dwIterHandle;
|
|
DWORD dwNumEntries;
|
|
DWORD dwAmountOfNodesSearched;
|
|
DWORD dwLengthOfSearch;
|
|
DWORD iter;
|
|
|
|
//
|
|
// Search NCP parameters
|
|
//
|
|
DWORD dwFlags = fDerefAliases ?
|
|
NDS_DEREF_ALIASES :
|
|
NDS_DONT_DEREF_ALIASES;
|
|
DWORD dwNumNodes = 0;
|
|
DWORD dwNumAttributes = 0;
|
|
DWORD dwInfoType = dwInformationType;
|
|
|
|
LPBYTE FixedPortion;
|
|
LPWSTR EndOfVariableData;
|
|
BOOL FitInBuffer = TRUE;
|
|
|
|
if ( *lphOperationData == NULL )
|
|
{
|
|
//
|
|
// This is the first time that NwNdsSearch has been called,
|
|
// need to create a hOperationData buffer . . .
|
|
//
|
|
status = NwNdsCreateBuffer( NDS_SEARCH,
|
|
(HANDLE *) &lpNdsBuffer );
|
|
|
|
if ( status )
|
|
{
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Not specifying any particular attributes in the search request.
|
|
//
|
|
(void) LocalFree( (HLOCAL) lpNdsBuffer->lpRequestBuffer );
|
|
lpNdsBuffer->lpRequestBuffer = NULL;
|
|
lpNdsBuffer->dwRequestBufferSize = 0;
|
|
lpNdsBuffer->dwRequestAvailableBytes = 0;
|
|
lpNdsBuffer->dwNumberOfRequestEntries = 0;
|
|
lpNdsBuffer->dwLengthOfRequestData = 0;
|
|
|
|
//
|
|
// Reasonable guess is that the response buffer needs to be 16K bytes.
|
|
//
|
|
lpNdsBuffer->dwReplyBufferSize = NDS_MAX_BUFFER;
|
|
}
|
|
else if ( ((LPNDS_BUFFER) *lphOperationData)->dwBufferId == NDS_SIGNATURE &&
|
|
((LPNDS_BUFFER) *lphOperationData)->dwOperation == NDS_SEARCH &&
|
|
((LPNDS_BUFFER) *lphOperationData)->lpReplyBuffer )
|
|
{
|
|
//
|
|
// This seems to be a sub-sequent call to NwNdsSearch with a resume
|
|
// handle, need to clean up the hOperationData buffer from the last
|
|
// time this was called.
|
|
//
|
|
lpNdsBuffer = (LPNDS_BUFFER) *lphOperationData;
|
|
|
|
(void) LocalFree( (HLOCAL) lpNdsBuffer->lpReplyBuffer );
|
|
lpNdsBuffer->lpReplyBuffer = NULL;
|
|
lpNdsBuffer->dwReplyAvailableBytes = 0;
|
|
lpNdsBuffer->dwNumberOfReplyEntries = 0;
|
|
lpNdsBuffer->dwLengthOfReplyData = 0;
|
|
|
|
if ( lpNdsBuffer->lpIndexBuffer )
|
|
{
|
|
(void) LocalFree( (HLOCAL) lpNdsBuffer->lpIndexBuffer );
|
|
lpNdsBuffer->lpIndexBuffer = NULL;
|
|
lpNdsBuffer->dwIndexAvailableBytes = 0;
|
|
lpNdsBuffer->dwNumberOfIndexEntries = 0;
|
|
lpNdsBuffer->dwLengthOfIndexData = 0;
|
|
}
|
|
|
|
//
|
|
// Since the last call to NwNdsSearch needed a bigger buffer for all
|
|
// of the response data, let's continue this time with a bigger reply
|
|
// buffer. We grow the buffer up to a point, 128K bytes.
|
|
//
|
|
if ( lpNdsBuffer->dwReplyBufferSize < SIXTY_FOUR_KB )
|
|
{
|
|
lpNdsBuffer->dwReplyBufferSize *= 2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
status = NwNdsCreateBuffer( NDS_SEARCH,
|
|
(HANDLE *) &lpNdsQueryTreeBuffer );
|
|
|
|
if ( status )
|
|
{
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Prepare request buffer stream with search query.
|
|
//
|
|
status = WriteQueryTreeToBuffer( lpQueryTree, lpNdsQueryTreeBuffer );
|
|
|
|
if ( status )
|
|
{
|
|
goto ErrorExit;
|
|
}
|
|
|
|
lpNdsBuffer->lpReplyBuffer =
|
|
(PVOID) LocalAlloc( LPTR, lpNdsBuffer->dwReplyBufferSize );
|
|
|
|
//
|
|
// Check that the memory allocation was successful.
|
|
//
|
|
if ( lpNdsBuffer->lpReplyBuffer == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: Search_AllAttrs LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
/*
|
|
//
|
|
// This is the format of a version 3 search request ...
|
|
//
|
|
ntstatus = FragExWithWait( lpNdsObject->NdsTree,
|
|
NETWARE_NDS_FUNCTION_SEARCH,
|
|
lpNdsBuffer->lpReplyBuffer,
|
|
lpNdsBuffer->dwReplyBufferSize,
|
|
&dwReplyLength,
|
|
"DDDDDDDDDDr",
|
|
0x00000003, // Version
|
|
dwFlags,
|
|
*lpdwIterHandle,
|
|
lpNdsObject->ObjectId, // Id of object to
|
|
// start search from.
|
|
dwScope,
|
|
dwNumNodes,
|
|
dwInfoType,
|
|
0x0000281D, // Flags??
|
|
0x741E0000, // ??
|
|
(DWORD) TRUE, // All attributes?
|
|
lpNdsQueryTreeBuffer->lpRequestBuffer,
|
|
(WORD)lpNdsQueryTreeBuffer->dwLengthOfRequestData );
|
|
*/
|
|
|
|
ntstatus = FragExWithWait( lpNdsObject->NdsTree,
|
|
NETWARE_NDS_FUNCTION_SEARCH,
|
|
lpNdsBuffer->lpReplyBuffer,
|
|
lpNdsBuffer->dwReplyBufferSize,
|
|
&dwReplyLength,
|
|
"DDDDDDDDDr",
|
|
0x00000002, // Version
|
|
dwFlags,
|
|
*lpdwIterHandle,
|
|
lpNdsObject->ObjectId, // Id of object to
|
|
// start search from.
|
|
dwScope,
|
|
dwNumNodes,
|
|
dwInfoType,
|
|
(DWORD) TRUE, // All attributes?
|
|
dwNumAttributes,
|
|
lpNdsQueryTreeBuffer->lpRequestBuffer,
|
|
(WORD)lpNdsQueryTreeBuffer->dwLengthOfRequestData );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadAttrDef_SomeAttrs: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
ntstatus = ParseResponse( lpNdsBuffer->lpReplyBuffer,
|
|
dwReplyLength,
|
|
"GD",
|
|
&nwstatus );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadAttrDef_SomeAttrs: The read object response was undecipherable.\n" ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
if ( nwstatus )
|
|
{
|
|
SetLastError( MapNetwareErrorCode( nwstatus ) );
|
|
status = nwstatus;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
ntstatus = ParseResponse( (BYTE *) lpNdsBuffer->lpReplyBuffer,
|
|
dwReplyLength,
|
|
"G_DDDDD",
|
|
sizeof(DWORD),
|
|
&dwIterHandle,
|
|
&dwAmountOfNodesSearched,
|
|
&dwInfoType,
|
|
&dwLengthOfSearch,
|
|
&dwNumEntries );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadAttrDef_SomeAttrs: The read object response was undecipherable.\n" ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Finished the search call, free up lpNDsQueryTreeBuffer
|
|
//
|
|
(void) NwNdsFreeBuffer( (HANDLE) lpNdsQueryTreeBuffer );
|
|
lpNdsQueryTreeBuffer = NULL;
|
|
|
|
lpNdsBuffer->dwNumberOfReplyEntries = dwNumEntries;
|
|
lpNdsBuffer->dwReplyInformationType = dwInfoType;
|
|
*lpdwIterHandle = dwIterHandle;
|
|
*lphOperationData = (HANDLE) lpNdsBuffer;
|
|
|
|
//
|
|
// Keep the search from object path . . .
|
|
//
|
|
wcscpy( lpNdsBuffer->szPath, lpNdsObject->szContainerName );
|
|
|
|
return NO_ERROR;
|
|
|
|
ErrorExit :
|
|
|
|
if ( lpNdsBuffer )
|
|
{
|
|
(void) NwNdsFreeBuffer( (HANDLE) lpNdsBuffer );
|
|
lpNdsBuffer = NULL;
|
|
}
|
|
|
|
if ( lpNdsQueryTreeBuffer )
|
|
{
|
|
(void) NwNdsFreeBuffer( (HANDLE) lpNdsQueryTreeBuffer );
|
|
lpNdsQueryTreeBuffer = NULL;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
DWORD
|
|
Search_SomeAttrs(
|
|
IN HANDLE hStartFromObject,
|
|
IN DWORD dwInformationType,
|
|
IN DWORD dwScope,
|
|
IN BOOL fDerefAliases,
|
|
IN LPQUERY_TREE lpQueryTree,
|
|
IN OUT LPDWORD lpdwIterHandle,
|
|
IN OUT HANDLE * lphOperationData )
|
|
{
|
|
DWORD status;
|
|
DWORD nwstatus;
|
|
NTSTATUS ntstatus;
|
|
LPNDS_BUFFER lpNdsBuffer = (LPNDS_BUFFER) *lphOperationData;
|
|
LPNDS_BUFFER lpNdsQueryTreeBuffer = NULL;
|
|
DWORD dwReplyLength;
|
|
LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hStartFromObject;
|
|
DWORD dwIterHandle;
|
|
DWORD dwNumEntries;
|
|
DWORD dwAmountOfNodesSearched;
|
|
DWORD dwLengthOfSearch;
|
|
DWORD iter;
|
|
|
|
//
|
|
// Search NCP parameters
|
|
//
|
|
DWORD dwFlags = fDerefAliases ?
|
|
NDS_DEREF_ALIASES :
|
|
NDS_DONT_DEREF_ALIASES;
|
|
DWORD dwNumNodes = 0;
|
|
DWORD dwInfoType = dwInformationType;
|
|
|
|
LPBYTE FixedPortion;
|
|
LPWSTR EndOfVariableData;
|
|
BOOL FitInBuffer = TRUE;
|
|
|
|
//
|
|
// A quick check of the buffer passed to us.
|
|
//
|
|
if ( lpNdsBuffer->dwBufferId != NDS_SIGNATURE ||
|
|
lpNdsBuffer->dwOperation != NDS_SEARCH )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// Prepare request buffer stream with search query.
|
|
//
|
|
status = NwNdsCreateBuffer( NDS_SEARCH,
|
|
(HANDLE *) &lpNdsQueryTreeBuffer );
|
|
|
|
if ( status )
|
|
{
|
|
goto ErrorExit;
|
|
}
|
|
|
|
status = WriteQueryTreeToBuffer( lpQueryTree, lpNdsQueryTreeBuffer );
|
|
|
|
if ( status )
|
|
{
|
|
goto ErrorExit;
|
|
}
|
|
|
|
if ( lpNdsBuffer->lpReplyBuffer == NULL ||
|
|
lpNdsBuffer->dwReplyBufferSize == 0 )
|
|
{
|
|
//
|
|
// Reasonable guess is that the initial response buffer needs to
|
|
// be 16K bytes.
|
|
//
|
|
lpNdsBuffer->dwReplyBufferSize = NDS_MAX_BUFFER;
|
|
}
|
|
|
|
if ( lpNdsBuffer->lpReplyBuffer )
|
|
{
|
|
//
|
|
// This seems to be a sub-sequent call to NwNdsSearch,
|
|
// need to clean up the hOperationData buffer from the last
|
|
// time this was called.
|
|
//
|
|
(void) LocalFree( (HLOCAL) lpNdsBuffer->lpReplyBuffer );
|
|
lpNdsBuffer->lpReplyBuffer = NULL;
|
|
lpNdsBuffer->dwReplyAvailableBytes = 0;
|
|
lpNdsBuffer->dwNumberOfReplyEntries = 0;
|
|
lpNdsBuffer->dwLengthOfReplyData = 0;
|
|
|
|
if ( lpNdsBuffer->lpIndexBuffer )
|
|
{
|
|
(void) LocalFree( (HLOCAL) lpNdsBuffer->lpIndexBuffer );
|
|
lpNdsBuffer->lpIndexBuffer = NULL;
|
|
lpNdsBuffer->dwIndexAvailableBytes = 0;
|
|
lpNdsBuffer->dwNumberOfIndexEntries = 0;
|
|
lpNdsBuffer->dwLengthOfIndexData = 0;
|
|
}
|
|
|
|
//
|
|
// Since the last call to NwNdsSearch needed a bigger buffer for all
|
|
// of the response data, let's continue this time with a bigger reply
|
|
// buffer. We grow the buffer up to a point, 64K bytes.
|
|
//
|
|
if ( lpNdsBuffer->dwReplyBufferSize < SIXTY_FOUR_KB )
|
|
{
|
|
lpNdsBuffer->dwReplyBufferSize *= 2;
|
|
}
|
|
}
|
|
|
|
lpNdsBuffer->lpReplyBuffer =
|
|
(PVOID) LocalAlloc( LPTR, lpNdsBuffer->dwReplyBufferSize );
|
|
|
|
//
|
|
// Check that the memory allocation was successful.
|
|
//
|
|
if ( lpNdsBuffer->lpReplyBuffer == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: Search_SomeAttrs LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
/*
|
|
//
|
|
// This is the format of a version 3 search request ...
|
|
//
|
|
ntstatus = FragExWithWait( lpNdsObject->NdsTree,
|
|
NETWARE_NDS_FUNCTION_SEARCH,
|
|
lpNdsBuffer->lpReplyBuffer,
|
|
lpNdsBuffer->dwReplyBufferSize,
|
|
&dwReplyLength,
|
|
"DDDDDDDDDDrr",
|
|
0x00000003,
|
|
dwFlags,
|
|
*lpdwIterHandle,
|
|
lpNdsObject->ObjectId, // Id of object to
|
|
// start search from.
|
|
dwScope,
|
|
dwNumNodes,
|
|
dwInfoType,
|
|
0x0000281D, // (DWORD) FALSE,// All attributes?
|
|
0x741E0000, // dwNumAttributes,
|
|
lpNdsBuffer->dwNumberOfRequestEntries,
|
|
lpNdsBuffer->lpRequestBuffer,
|
|
lpNdsBuffer->dwLengthOfRequestData,
|
|
lpNdsQueryTreeBuffer->lpRequestBuffer,
|
|
(WORD)lpNdsQueryTreeBuffer->dwLengthOfRequestData );
|
|
*/
|
|
|
|
ntstatus = FragExWithWait( lpNdsObject->NdsTree,
|
|
NETWARE_NDS_FUNCTION_SEARCH,
|
|
lpNdsBuffer->lpReplyBuffer,
|
|
lpNdsBuffer->dwReplyBufferSize,
|
|
&dwReplyLength,
|
|
"DDDDDDDDDrr",
|
|
0x00000002,
|
|
dwFlags,
|
|
*lpdwIterHandle,
|
|
lpNdsObject->ObjectId, // Id of object to
|
|
// start search from.
|
|
dwScope,
|
|
dwNumNodes,
|
|
dwInfoType,
|
|
(DWORD) FALSE, // All attributes?
|
|
lpNdsBuffer->dwNumberOfRequestEntries,
|
|
lpNdsBuffer->lpRequestBuffer,
|
|
lpNdsBuffer->dwLengthOfRequestData,
|
|
lpNdsQueryTreeBuffer->lpRequestBuffer,
|
|
(WORD)lpNdsQueryTreeBuffer->dwLengthOfRequestData );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadAttrDef_SomeAttrs: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
ntstatus = ParseResponse( lpNdsBuffer->lpReplyBuffer,
|
|
dwReplyLength,
|
|
"GD",
|
|
&nwstatus );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadAttrDef_SomeAttrs: The read object response was undecipherable.\n" ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
if ( nwstatus )
|
|
{
|
|
SetLastError( MapNetwareErrorCode( nwstatus ) );
|
|
status = nwstatus;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
ntstatus = ParseResponse( (BYTE *) lpNdsBuffer->lpReplyBuffer,
|
|
dwReplyLength,
|
|
"G_DDDDD",
|
|
sizeof(DWORD),
|
|
&dwIterHandle,
|
|
&dwAmountOfNodesSearched,
|
|
&dwInfoType,
|
|
&dwLengthOfSearch,
|
|
&dwNumEntries );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: ReadAttrDef_SomeAttrs: The read object response was undecipherable.\n" ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
status = (DWORD) UNSUCCESSFUL;
|
|
goto ErrorExit;
|
|
}
|
|
|
|
//
|
|
// Finished the search call, free up lpNDsQueryTreeBuffer
|
|
//
|
|
(void) NwNdsFreeBuffer( (HANDLE) lpNdsQueryTreeBuffer );
|
|
lpNdsQueryTreeBuffer = NULL;
|
|
|
|
lpNdsBuffer->dwNumberOfReplyEntries = dwNumEntries;
|
|
lpNdsBuffer->dwReplyInformationType = dwInfoType;
|
|
*lpdwIterHandle = dwIterHandle;
|
|
*lphOperationData = (HANDLE) lpNdsBuffer;
|
|
|
|
//
|
|
// Keep the search from object path . . .
|
|
//
|
|
wcscpy( lpNdsBuffer->szPath, lpNdsObject->szContainerName );
|
|
|
|
return NO_ERROR;
|
|
|
|
ErrorExit :
|
|
|
|
if ( lpNdsQueryTreeBuffer )
|
|
{
|
|
(void) NwNdsFreeBuffer( (HANDLE) lpNdsQueryTreeBuffer );
|
|
lpNdsQueryTreeBuffer = NULL;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
VOID
|
|
GetSubTreeData( IN DWORD NdsRawDataPtr,
|
|
OUT LPDWORD lpdwEntryId,
|
|
OUT LPDWORD lpdwSubordinateCount,
|
|
OUT LPDWORD lpdwModificationTime,
|
|
OUT LPDWORD lpdwClassNameLen,
|
|
OUT LPWSTR * lpszClassName,
|
|
OUT LPDWORD lpdwObjectNameLen,
|
|
OUT LPWSTR * lpszObjectName )
|
|
{
|
|
PNDS_RESPONSE_SUBORDINATE_ENTRY pSubEntry =
|
|
(PNDS_RESPONSE_SUBORDINATE_ENTRY) NdsRawDataPtr;
|
|
PBYTE pbRaw;
|
|
|
|
//
|
|
// The structure of a NDS_RESPONSE_SUBORDINATE_ENTRY consists of 4 DWORDs
|
|
// followed by two standard NDS format UNICODE strings. Below we jump pbRaw
|
|
// into the buffer, past the 4 DWORDs.
|
|
//
|
|
*lpdwEntryId = pSubEntry->EntryId;
|
|
*lpdwSubordinateCount = pSubEntry->SubordinateCount;
|
|
*lpdwModificationTime = pSubEntry->ModificationTime;
|
|
|
|
pbRaw = (BYTE *) pSubEntry;
|
|
pbRaw += sizeof(NDS_RESPONSE_SUBORDINATE_ENTRY);
|
|
|
|
//
|
|
// Now we get the length of the first string (Base Class).
|
|
//
|
|
*lpdwClassNameLen = * (DWORD *) pbRaw;
|
|
|
|
//
|
|
// Now we point pbRaw to the first WCHAR of the first string (Base Class).
|
|
//
|
|
pbRaw += sizeof(DWORD);
|
|
|
|
*lpszClassName = (LPWSTR) pbRaw;
|
|
|
|
//
|
|
// Move pbRaw into the buffer, past the first UNICODE string (WORD aligned)
|
|
//
|
|
pbRaw += ROUNDUP4( *lpdwClassNameLen );
|
|
|
|
//
|
|
// Now we get the length of the second string (Entry Name).
|
|
//
|
|
*lpdwObjectNameLen = * (DWORD *) pbRaw;
|
|
|
|
//
|
|
// Now we point pbRaw to the first WCHAR of the second string (Entry Name).
|
|
//
|
|
pbRaw += sizeof(DWORD);
|
|
|
|
*lpszObjectName = (LPWSTR) pbRaw;
|
|
}
|
|
|
|
|
|
LPBYTE
|
|
GetSearchResultData( IN LPBYTE lpResultBufferPtr,
|
|
OUT LPDWORD lpdwFlags,
|
|
OUT LPDWORD lpdwSubordinateCount,
|
|
OUT LPDWORD lpdwModificationTime,
|
|
OUT LPDWORD lpdwClassNameLen,
|
|
OUT LPWSTR * lpszClassName,
|
|
OUT LPDWORD lpdwObjectNameLen,
|
|
OUT LPWSTR * lpszObjectName,
|
|
OUT LPDWORD lpdwEntryInfo1,
|
|
OUT LPDWORD lpdwEntryInfo2 )
|
|
{
|
|
LPBYTE lpRaw = lpResultBufferPtr;
|
|
|
|
*lpdwFlags = * (LPDWORD) lpRaw;
|
|
lpRaw += sizeof(DWORD);
|
|
|
|
*lpdwSubordinateCount = * (LPDWORD) lpRaw;
|
|
lpRaw += sizeof(DWORD);
|
|
|
|
*lpdwModificationTime = * (LPDWORD) lpRaw;
|
|
lpRaw += sizeof(DWORD);
|
|
|
|
//
|
|
// Now we get the length of the first string (Base Class).
|
|
//
|
|
*lpdwClassNameLen = * (DWORD *) lpRaw;
|
|
|
|
//
|
|
// Now we point lpRaw to the first WCHAR of the first string (Base Class).
|
|
//
|
|
lpRaw += sizeof(DWORD);
|
|
|
|
*lpszClassName = (LPWSTR) lpRaw;
|
|
|
|
//
|
|
// Move lpRaw into the buffer, past the first UNICODE string
|
|
// (DWORD aligned)
|
|
//
|
|
lpRaw += ROUNDUP4( *lpdwClassNameLen );
|
|
|
|
//
|
|
// Now we get the length of the second string (Entry Name).
|
|
//
|
|
*lpdwObjectNameLen = * (DWORD *) lpRaw;
|
|
|
|
//
|
|
// Now we point lpRaw to the first WCHAR of the second string (Entry Name).
|
|
//
|
|
lpRaw += sizeof(DWORD);
|
|
|
|
*lpszObjectName = (LPWSTR) lpRaw;
|
|
|
|
//
|
|
// Move lpRaw into the buffer, past the second UNICODE string
|
|
// (DWORD aligned)
|
|
//
|
|
lpRaw += ROUNDUP4( *lpdwObjectNameLen );
|
|
|
|
//
|
|
// Now skip over the last two DWORDs, I don't know what they represent?
|
|
//
|
|
*lpdwEntryInfo1 = * (LPDWORD) lpRaw;
|
|
lpRaw += sizeof(DWORD);
|
|
|
|
*lpdwEntryInfo2 = * (LPDWORD) lpRaw;
|
|
lpRaw += sizeof(DWORD);
|
|
|
|
return lpRaw;
|
|
}
|
|
|
|
|
|
DWORD
|
|
WriteObjectToBuffer(
|
|
IN OUT LPBYTE * FixedPortion,
|
|
IN OUT LPWSTR * EndOfVariableData,
|
|
IN LPWSTR szObjectFullName,
|
|
IN LPWSTR szObjectName,
|
|
IN LPWSTR szClassName,
|
|
IN DWORD EntryId,
|
|
IN DWORD ModificationTime,
|
|
IN DWORD SubordinateCount,
|
|
IN DWORD NumberOfAttributes,
|
|
IN LPNDS_ATTR_INFO lpAttributeInfos )
|
|
{
|
|
BOOL FitInBuffer = TRUE;
|
|
LPNDS_OBJECT_INFO lpNdsObjectInfo = (LPNDS_OBJECT_INFO) *FixedPortion;
|
|
DWORD EntrySize = sizeof( NDS_OBJECT_INFO ) +
|
|
( wcslen( szObjectFullName ) +
|
|
wcslen( szObjectName ) +
|
|
wcslen( szClassName ) +
|
|
3 ) * sizeof( WCHAR );
|
|
|
|
EntrySize = ROUND_UP_COUNT( EntrySize, ALIGN_DWORD );
|
|
|
|
//
|
|
// See if buffer is large enough to fit the entry.
|
|
//
|
|
if (((DWORD_PTR) *FixedPortion + EntrySize) >
|
|
(DWORD_PTR) *EndOfVariableData) {
|
|
|
|
return WN_MORE_DATA;
|
|
}
|
|
|
|
lpNdsObjectInfo->dwEntryId = EntryId;
|
|
lpNdsObjectInfo->dwModificationTime = ModificationTime;
|
|
lpNdsObjectInfo->dwSubordinateCount = SubordinateCount;
|
|
lpNdsObjectInfo->dwNumberOfAttributes = NumberOfAttributes;
|
|
lpNdsObjectInfo->lpAttribute = lpAttributeInfos;
|
|
|
|
//
|
|
// Update fixed entry pointer to next entry.
|
|
//
|
|
(DWORD_PTR) (*FixedPortion) += sizeof(NDS_OBJECT_INFO);
|
|
|
|
FitInBuffer = NwlibCopyStringToBuffer(
|
|
szObjectFullName,
|
|
wcslen(szObjectFullName),
|
|
(LPCWSTR) *FixedPortion,
|
|
EndOfVariableData,
|
|
&lpNdsObjectInfo->szObjectFullName );
|
|
|
|
ASSERT(FitInBuffer);
|
|
|
|
FitInBuffer = NwlibCopyStringToBuffer(
|
|
szObjectName,
|
|
wcslen(szObjectName),
|
|
(LPCWSTR) *FixedPortion,
|
|
EndOfVariableData,
|
|
&lpNdsObjectInfo->szObjectName );
|
|
|
|
ASSERT(FitInBuffer);
|
|
|
|
FitInBuffer = NwlibCopyStringToBuffer(
|
|
szClassName,
|
|
wcslen(szClassName),
|
|
(LPCWSTR) *FixedPortion,
|
|
EndOfVariableData,
|
|
&lpNdsObjectInfo->szObjectClass );
|
|
|
|
ASSERT(FitInBuffer);
|
|
|
|
if (! FitInBuffer)
|
|
return WN_MORE_DATA;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
DWORD
|
|
VerifyBufferSize(
|
|
IN LPBYTE lpRawBuffer,
|
|
IN DWORD dwBufferSize,
|
|
IN DWORD dwSyntaxID,
|
|
IN DWORD dwNumberOfValues,
|
|
OUT LPDWORD lpdwLength )
|
|
{
|
|
DWORD iter;
|
|
LPBYTE lpTemp = lpRawBuffer;
|
|
|
|
*lpdwLength = 0;
|
|
|
|
for ( iter = 0; iter < dwNumberOfValues; iter++ )
|
|
{
|
|
*lpdwLength += SizeOfASN1Structure( &lpTemp, dwSyntaxID );
|
|
}
|
|
|
|
if ( *lpdwLength > dwBufferSize )
|
|
{
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
DWORD
|
|
VerifyBufferSizeForStringList(
|
|
IN DWORD dwBufferSize,
|
|
IN DWORD dwNumberOfValues,
|
|
OUT LPDWORD lpdwLength )
|
|
{
|
|
*lpdwLength = sizeof(ASN1_TYPE_6) * dwNumberOfValues;
|
|
|
|
if ( *lpdwLength > dwBufferSize )
|
|
{
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
DWORD
|
|
WriteQueryTreeToBuffer(
|
|
IN LPQUERY_TREE lpQueryTree,
|
|
IN LPNDS_BUFFER lpNdsBuffer )
|
|
{
|
|
DWORD status;
|
|
|
|
switch( lpQueryTree->dwOperation )
|
|
{
|
|
case NDS_QUERY_OR :
|
|
case NDS_QUERY_AND :
|
|
|
|
if ( lpQueryTree->lpLVal == NULL || lpQueryTree->lpRVal == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: WriteQueryTreeToBuffer was not passed a pointer to an L or R value.\n" ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
status = WriteQueryNodeToBuffer( (LPQUERY_NODE) lpQueryTree,
|
|
lpNdsBuffer );
|
|
|
|
if ( status )
|
|
return status;
|
|
|
|
status = WriteQueryTreeToBuffer( (LPQUERY_TREE) lpQueryTree->lpLVal,
|
|
lpNdsBuffer );
|
|
|
|
if ( status )
|
|
return status;
|
|
|
|
status = WriteQueryTreeToBuffer( (LPQUERY_TREE) lpQueryTree->lpRVal,
|
|
lpNdsBuffer );
|
|
|
|
if ( status )
|
|
return status;
|
|
|
|
break;
|
|
|
|
case NDS_QUERY_NOT :
|
|
|
|
if ( lpQueryTree->lpLVal == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: WriteQueryTreeToBuffer was not passed a pointer to an L value.\n" ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
status = WriteQueryNodeToBuffer( (LPQUERY_NODE) lpQueryTree,
|
|
lpNdsBuffer );
|
|
|
|
if ( status )
|
|
return status;
|
|
|
|
status = WriteQueryTreeToBuffer( (LPQUERY_TREE) lpQueryTree->lpLVal,
|
|
lpNdsBuffer );
|
|
|
|
if ( status )
|
|
return status;
|
|
|
|
break;
|
|
|
|
case NDS_QUERY_EQUAL :
|
|
case NDS_QUERY_GE :
|
|
case NDS_QUERY_LE :
|
|
case NDS_QUERY_APPROX :
|
|
case NDS_QUERY_PRESENT :
|
|
|
|
status = WriteQueryNodeToBuffer( (LPQUERY_NODE) lpQueryTree,
|
|
lpNdsBuffer );
|
|
|
|
if ( status )
|
|
return status;
|
|
|
|
break;
|
|
|
|
default :
|
|
#if DBG
|
|
KdPrint(( "NDS32: WriteQueryTreeToBuffer was passed an unidentified operation - 0x%.8X.\n", lpQueryTree->dwOperation ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
DWORD
|
|
WriteQueryNodeToBuffer(
|
|
IN LPQUERY_NODE lpQueryNode,
|
|
IN LPNDS_BUFFER lpNdsBuffer )
|
|
{
|
|
DWORD LengthInBytes = 0;
|
|
DWORD stringLen;
|
|
LPBYTE lpTemp;
|
|
|
|
if ( lpNdsBuffer->dwRequestAvailableBytes < ONE_KB )
|
|
{
|
|
//
|
|
// Buffer to store query is getting small, need to increase
|
|
// request buffer size.
|
|
//
|
|
if ( AllocateOrIncreaseRequestBuffer( lpNdsBuffer ) != NO_ERROR )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: WriteQueryNodeToBuffer LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
}
|
|
|
|
lpTemp = (LPBYTE)&lpNdsBuffer->lpRequestBuffer[lpNdsBuffer->dwLengthOfRequestData];
|
|
|
|
switch( lpQueryNode->dwOperation )
|
|
{
|
|
case NDS_QUERY_OR :
|
|
case NDS_QUERY_AND :
|
|
|
|
if ( lpQueryNode->lpLVal == NULL || lpQueryNode->lpRVal == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: WriteQueryNodeToBuffer was not passed a pointer to an L or R value.\n" ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// Write out operation
|
|
//
|
|
*(LPDWORD)lpTemp = lpQueryNode->dwOperation;
|
|
lpTemp += sizeof(DWORD);
|
|
LengthInBytes += sizeof(DWORD);
|
|
|
|
*(LPDWORD)lpTemp = 2; // The number of items being ANDed or ORed.
|
|
lpTemp += sizeof(DWORD);
|
|
LengthInBytes += sizeof(DWORD);
|
|
|
|
break;
|
|
|
|
case NDS_QUERY_NOT :
|
|
|
|
if ( lpQueryNode->lpLVal == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: WriteQueryNodeToBuffer was not passed a pointer to an L value.\n" ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// Write out operation
|
|
//
|
|
*(LPDWORD)lpTemp = lpQueryNode->dwOperation;
|
|
lpTemp += sizeof(DWORD);
|
|
LengthInBytes += sizeof(DWORD);
|
|
|
|
break;
|
|
|
|
case NDS_QUERY_EQUAL :
|
|
case NDS_QUERY_GE :
|
|
case NDS_QUERY_LE :
|
|
case NDS_QUERY_APPROX :
|
|
|
|
if ( lpQueryNode->lpLVal == NULL || lpQueryNode->lpRVal == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: WriteQueryNodeToBuffer was not passed a pointer to an L or R value.\n" ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// Write out operation
|
|
//
|
|
*(LPDWORD)lpTemp = 0; // Zero represents ITEM in NDS
|
|
lpTemp += sizeof(DWORD);
|
|
LengthInBytes += sizeof(DWORD);
|
|
|
|
*(LPDWORD)lpTemp = lpQueryNode->dwOperation;
|
|
lpTemp += sizeof(DWORD);
|
|
LengthInBytes += sizeof(DWORD);
|
|
|
|
switch( lpQueryNode->dwSyntaxId )
|
|
{
|
|
case NDS_SYNTAX_ID_1 :
|
|
case NDS_SYNTAX_ID_2 :
|
|
case NDS_SYNTAX_ID_3 :
|
|
case NDS_SYNTAX_ID_4 :
|
|
case NDS_SYNTAX_ID_5 :
|
|
case NDS_SYNTAX_ID_10 :
|
|
case NDS_SYNTAX_ID_20 :
|
|
//
|
|
// Write out the attribute name stored in LVal
|
|
//
|
|
stringLen = wcslen( (LPWSTR) lpQueryNode->lpLVal );
|
|
|
|
*(LPDWORD)lpTemp = (stringLen + 1) * sizeof(WCHAR);
|
|
lpTemp += sizeof(DWORD);
|
|
LengthInBytes += sizeof(DWORD);
|
|
|
|
RtlCopyMemory( lpTemp,
|
|
lpQueryNode->lpLVal,
|
|
stringLen*sizeof(WCHAR) );
|
|
lpTemp += ROUND_UP_COUNT( (stringLen+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
LengthInBytes += ROUND_UP_COUNT( (stringLen+1) *
|
|
sizeof(WCHAR),
|
|
ALIGN_DWORD );
|
|
|
|
//
|
|
// Write out the attribute value stored in RVal
|
|
//
|
|
stringLen = wcslen( (LPWSTR) lpQueryNode->lpRVal );
|
|
|
|
*(LPDWORD)lpTemp = (stringLen + 1) * sizeof(WCHAR);
|
|
lpTemp += sizeof(DWORD);
|
|
LengthInBytes += sizeof(DWORD);
|
|
|
|
RtlCopyMemory( lpTemp,
|
|
lpQueryNode->lpRVal,
|
|
stringLen*sizeof(WCHAR) );
|
|
lpTemp += ROUND_UP_COUNT( (stringLen+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
LengthInBytes += ROUND_UP_COUNT( (stringLen+1) *
|
|
sizeof(WCHAR),
|
|
ALIGN_DWORD );
|
|
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_7 :
|
|
|
|
//
|
|
// Write out the attribute name stored in LVal
|
|
//
|
|
stringLen = wcslen( (LPWSTR) lpQueryNode->lpLVal );
|
|
|
|
*(LPDWORD)lpTemp = (stringLen + 1) * sizeof(WCHAR);
|
|
lpTemp += sizeof(DWORD);
|
|
LengthInBytes += sizeof(DWORD);
|
|
|
|
RtlCopyMemory( lpTemp,
|
|
lpQueryNode->lpLVal,
|
|
stringLen*sizeof(WCHAR) );
|
|
lpTemp += ROUND_UP_COUNT( (stringLen+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
LengthInBytes += ROUND_UP_COUNT( (stringLen+1) *
|
|
sizeof(WCHAR),
|
|
ALIGN_DWORD );
|
|
|
|
//
|
|
// Write out the attribute value stored in RVal
|
|
//
|
|
*(LPDWORD)lpTemp = 1; // Needs to have value 1,
|
|
// representing one byte
|
|
// even though it is padded
|
|
// out to four bytes.
|
|
lpTemp += sizeof(DWORD);
|
|
LengthInBytes += sizeof(DWORD);
|
|
*(LPDWORD)lpTemp = 0; // This clears all bits of the DWORD
|
|
*(LPBYTE)lpTemp = (BYTE) (((LPASN1_TYPE_7)
|
|
lpQueryNode->lpRVal)->Boolean);
|
|
lpTemp += sizeof(DWORD);
|
|
LengthInBytes += sizeof(DWORD);
|
|
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_8 :
|
|
case NDS_SYNTAX_ID_22 :
|
|
case NDS_SYNTAX_ID_24 :
|
|
case NDS_SYNTAX_ID_27 :
|
|
//
|
|
// Write out the attribute name stored in LVal
|
|
//
|
|
stringLen = wcslen( (LPWSTR) lpQueryNode->lpLVal );
|
|
|
|
*(LPDWORD)lpTemp = (stringLen + 1) * sizeof(WCHAR);
|
|
lpTemp += sizeof(DWORD);
|
|
LengthInBytes += sizeof(DWORD);
|
|
|
|
RtlCopyMemory( lpTemp,
|
|
lpQueryNode->lpLVal,
|
|
stringLen*sizeof(WCHAR) );
|
|
lpTemp += ROUND_UP_COUNT( (stringLen+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
LengthInBytes += ROUND_UP_COUNT( (stringLen+1) *
|
|
sizeof(WCHAR),
|
|
ALIGN_DWORD );
|
|
|
|
//
|
|
// Write out the attribute value stored in RVal
|
|
//
|
|
*(LPDWORD)lpTemp = sizeof( DWORD );
|
|
lpTemp += sizeof(DWORD);
|
|
LengthInBytes += sizeof(DWORD);
|
|
*(LPDWORD)lpTemp = *( (LPDWORD) lpQueryNode->lpRVal );
|
|
lpTemp += sizeof(DWORD);
|
|
LengthInBytes += sizeof(DWORD);
|
|
|
|
break;
|
|
|
|
case NDS_SYNTAX_ID_9 :
|
|
//
|
|
// Write out the attribute name stored in LVal
|
|
//
|
|
stringLen = wcslen( (LPWSTR) lpQueryNode->lpLVal );
|
|
|
|
*(LPDWORD)lpTemp = (stringLen + 1) * sizeof(WCHAR);
|
|
lpTemp += sizeof(DWORD);
|
|
LengthInBytes += sizeof(DWORD);
|
|
|
|
RtlCopyMemory( lpTemp,
|
|
lpQueryNode->lpLVal,
|
|
stringLen*sizeof(WCHAR) );
|
|
lpTemp += ROUND_UP_COUNT( (stringLen+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
LengthInBytes += ROUND_UP_COUNT( (stringLen+1) *
|
|
sizeof(WCHAR),
|
|
ALIGN_DWORD );
|
|
|
|
//
|
|
// Write out the attribute value stored in RVal
|
|
//
|
|
stringLen = ((LPASN1_TYPE_9) lpQueryNode->lpRVal)->Length;
|
|
|
|
*(LPDWORD)lpTemp = stringLen;
|
|
lpTemp += sizeof(DWORD);
|
|
LengthInBytes += sizeof(DWORD);
|
|
|
|
RtlCopyMemory( lpTemp,
|
|
&((LPASN1_TYPE_9) lpQueryNode->lpRVal)->OctetString,
|
|
stringLen );
|
|
lpTemp += ROUND_UP_COUNT( stringLen, ALIGN_DWORD);
|
|
LengthInBytes += ROUND_UP_COUNT( stringLen, ALIGN_DWORD );
|
|
|
|
break;
|
|
|
|
default :
|
|
SetLastError( ERROR_NOT_SUPPORTED );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
break;
|
|
|
|
case NDS_QUERY_PRESENT :
|
|
|
|
if ( lpQueryNode->lpLVal == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: WriteQueryNodeToBuffer was not passed a pointer to an L value.\n" ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// Write out operation
|
|
//
|
|
*(LPDWORD)lpTemp = 0; // Zero represents ITEM in NDS
|
|
lpTemp += sizeof(DWORD);
|
|
LengthInBytes += sizeof(DWORD);
|
|
|
|
*(LPDWORD)lpTemp = lpQueryNode->dwOperation;
|
|
lpTemp += sizeof(DWORD);
|
|
LengthInBytes += sizeof(DWORD);
|
|
|
|
//
|
|
// Write out the attribute name stored in LVal
|
|
//
|
|
stringLen = wcslen( (LPWSTR) lpQueryNode->lpLVal );
|
|
|
|
*(LPDWORD)lpTemp = (stringLen + 1) * sizeof(WCHAR);
|
|
lpTemp += sizeof(DWORD);
|
|
LengthInBytes += sizeof(DWORD);
|
|
|
|
RtlCopyMemory( lpTemp,
|
|
lpQueryNode->lpLVal,
|
|
stringLen*sizeof(WCHAR) );
|
|
lpTemp += ROUND_UP_COUNT( (stringLen+1)*sizeof(WCHAR),
|
|
ALIGN_DWORD);
|
|
LengthInBytes += ROUND_UP_COUNT( (stringLen+1) *
|
|
sizeof(WCHAR),
|
|
ALIGN_DWORD );
|
|
|
|
break;
|
|
|
|
default :
|
|
#if DBG
|
|
KdPrint(( "NDS32: WriteQueryNodeToBuffer was passed an unidentified operation - 0x%.8X.\n", lpQueryNode->dwOperation ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
lpNdsBuffer->dwRequestAvailableBytes -= LengthInBytes;
|
|
lpNdsBuffer->dwLengthOfRequestData += LengthInBytes;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
DWORD
|
|
NwNdsGetServerDN(
|
|
IN HANDLE hTree,
|
|
OUT LPWSTR szServerDN )
|
|
{
|
|
DWORD nwstatus;
|
|
DWORD status = NO_ERROR;
|
|
NTSTATUS ntstatus = STATUS_SUCCESS;
|
|
DWORD dwReplyLength;
|
|
BYTE NdsReply[NDS_BUFFER_SIZE];
|
|
LPNDS_OBJECT_PRIV lpNdsObject = (LPNDS_OBJECT_PRIV) hTree;
|
|
|
|
if ( lpNdsObject == NULL ||
|
|
lpNdsObject->Signature != NDS_SIGNATURE )
|
|
{
|
|
SetLastError( ERROR_INVALID_PARAMETER );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
ntstatus =
|
|
FragExWithWait( lpNdsObject->NdsTree,
|
|
NETWARE_NDS_FUNCTION_GET_SERVER_ADDRESS,
|
|
NdsReply,
|
|
NDS_BUFFER_SIZE,
|
|
&dwReplyLength,
|
|
NULL );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsGetServerInfo: The call to FragExWithWait failed with 0x%.8X.\n", ntstatus ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
ntstatus = ParseResponse( NdsReply,
|
|
dwReplyLength,
|
|
"GD",
|
|
&nwstatus );
|
|
|
|
if ( !NT_SUCCESS( ntstatus ) )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: NwNdsGetServerInfo: The get server information response was undecipherable.\n" ));
|
|
#endif
|
|
|
|
SetLastError( RtlNtStatusToDosError( ntstatus ) );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
if ( nwstatus )
|
|
{
|
|
SetLastError( MapNetwareErrorCode( nwstatus ) );
|
|
return nwstatus;
|
|
}
|
|
else
|
|
{
|
|
LPBYTE lpByte = NdsReply;
|
|
DWORD dwStrLen = 0;
|
|
DWORD dwNumPartitions = 0;
|
|
|
|
//
|
|
// Skip past status return code ...
|
|
//
|
|
lpByte += sizeof( DWORD );
|
|
|
|
//
|
|
// Skip past the length value of the Server DN string ...
|
|
//
|
|
lpByte += sizeof( DWORD );
|
|
|
|
wcsncpy( szServerDN, (LPWSTR) lpByte, NDS_MAX_NAME_CHARS );
|
|
szServerDN[NDS_MAX_NAME_CHARS - 1] = (WCHAR)0;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
}
|
|
|
|
|
|
DWORD
|
|
AllocateOrIncreaseSyntaxBuffer(
|
|
IN LPNDS_BUFFER lpNdsBuffer,
|
|
IN DWORD dwLengthNeeded )
|
|
{
|
|
DWORD LengthAdded;
|
|
|
|
if ( lpNdsBuffer->lpSyntaxBuffer )
|
|
{
|
|
LPBYTE lpTempBuffer = NULL;
|
|
|
|
//
|
|
// Figure how much we need. We figure how many four kb
|
|
// chunks and then multiply that by four kb to get the number
|
|
// or bytes needed.
|
|
//
|
|
|
|
DWORD LengthNeeded = dwLengthNeeded - lpNdsBuffer->dwSyntaxAvailableBytes;
|
|
if (LengthNeeded <= 0) {
|
|
LengthAdded = FOUR_KB;
|
|
}
|
|
else {
|
|
LengthAdded = ((LengthNeeded + (FOUR_KB) - 1) / FOUR_KB) * FOUR_KB;
|
|
}
|
|
|
|
//
|
|
// Need to reallocate buffer to a bigger size.
|
|
//
|
|
lpTempBuffer = (LPBYTE) LocalReAlloc(
|
|
(HLOCAL) lpNdsBuffer->lpSyntaxBuffer,
|
|
lpNdsBuffer->dwSyntaxBufferSize + LengthAdded,
|
|
LPTR );
|
|
|
|
if ( lpTempBuffer )
|
|
{
|
|
lpNdsBuffer->lpSyntaxBuffer = lpTempBuffer;
|
|
}
|
|
else
|
|
{
|
|
lpTempBuffer = (LPBYTE) LocalAlloc( LPTR,
|
|
lpNdsBuffer->dwSyntaxBufferSize +
|
|
LengthAdded );
|
|
|
|
if ( lpTempBuffer )
|
|
{
|
|
RtlCopyMemory( lpTempBuffer,
|
|
lpNdsBuffer->lpSyntaxBuffer,
|
|
lpNdsBuffer->dwSyntaxBufferSize );
|
|
|
|
LocalFree( lpNdsBuffer->lpSyntaxBuffer );
|
|
|
|
lpNdsBuffer->lpSyntaxBuffer = lpTempBuffer;
|
|
}
|
|
else
|
|
{
|
|
LocalFree( lpNdsBuffer->lpSyntaxBuffer );
|
|
|
|
lpNdsBuffer->lpSyntaxBuffer = NULL;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Figure how much we need. We figure how many four kb
|
|
// chunks and then multiply that by four kb to get the number
|
|
// or bytes needed.
|
|
//
|
|
|
|
if (dwLengthNeeded <= 0) {
|
|
LengthAdded = FOUR_KB;
|
|
}
|
|
else {
|
|
LengthAdded = ((dwLengthNeeded + (FOUR_KB) - 1) / FOUR_KB) * FOUR_KB;
|
|
}
|
|
|
|
//
|
|
// Need to allocate a 4K byte buffer.
|
|
//
|
|
lpNdsBuffer->lpSyntaxBuffer = (LPBYTE) LocalAlloc( LPTR,
|
|
LengthAdded );
|
|
lpNdsBuffer->dwSyntaxBufferSize = 0;
|
|
lpNdsBuffer->dwSyntaxAvailableBytes = 0;
|
|
}
|
|
|
|
if ( lpNdsBuffer->lpSyntaxBuffer == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: AllocateOrIncreaseSyntaxBuffer LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
lpNdsBuffer->dwSyntaxBufferSize += LengthAdded;
|
|
lpNdsBuffer->dwSyntaxAvailableBytes += LengthAdded;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
DWORD
|
|
AllocateOrIncreaseRequestBuffer(
|
|
IN LPNDS_BUFFER lpNdsBuffer )
|
|
{
|
|
if ( lpNdsBuffer->lpRequestBuffer )
|
|
{
|
|
LPBYTE lpTempBuffer = NULL;
|
|
|
|
//
|
|
// Need to reallocate buffer to a bigger size.
|
|
//
|
|
lpTempBuffer = (LPBYTE) LocalReAlloc(
|
|
(HLOCAL) lpNdsBuffer->lpRequestBuffer,
|
|
lpNdsBuffer->dwRequestBufferSize + TWO_KB,
|
|
LPTR );
|
|
|
|
if ( lpTempBuffer )
|
|
{
|
|
lpNdsBuffer->lpRequestBuffer = lpTempBuffer;
|
|
}
|
|
else
|
|
{
|
|
lpTempBuffer = (LPBYTE) LocalAlloc( LPTR,
|
|
lpNdsBuffer->dwRequestBufferSize +
|
|
TWO_KB );
|
|
|
|
if ( lpTempBuffer )
|
|
{
|
|
RtlCopyMemory( lpTempBuffer,
|
|
lpNdsBuffer->lpRequestBuffer,
|
|
lpNdsBuffer->dwRequestBufferSize );
|
|
|
|
LocalFree( lpNdsBuffer->lpRequestBuffer );
|
|
|
|
lpNdsBuffer->lpRequestBuffer = lpTempBuffer;
|
|
}
|
|
else
|
|
{
|
|
LocalFree( lpNdsBuffer->lpRequestBuffer );
|
|
|
|
lpNdsBuffer->lpRequestBuffer = NULL;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Need to allocate a 2K byte buffer.
|
|
//
|
|
lpNdsBuffer->lpRequestBuffer = (LPBYTE) LocalAlloc( LPTR,
|
|
TWO_KB );
|
|
lpNdsBuffer->dwRequestBufferSize = 0;
|
|
lpNdsBuffer->dwRequestAvailableBytes = 0;
|
|
}
|
|
|
|
if ( lpNdsBuffer->lpRequestBuffer == NULL )
|
|
{
|
|
#if DBG
|
|
KdPrint(( "NDS32: AllocateOrIncreaseRequestBuffer LocalAlloc Failed 0x%.8X\n", GetLastError() ));
|
|
#endif
|
|
|
|
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
|
|
return (DWORD) UNSUCCESSFUL;
|
|
}
|
|
|
|
lpNdsBuffer->dwRequestBufferSize += TWO_KB;
|
|
lpNdsBuffer->dwRequestAvailableBytes += TWO_KB;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|