summaryrefslogtreecommitdiffstats
path: root/private/nw/nwscript/nds.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--private/nw/nwscript/nds.c1505
1 files changed, 1505 insertions, 0 deletions
diff --git a/private/nw/nwscript/nds.c b/private/nw/nwscript/nds.c
new file mode 100644
index 000000000..1b73643f5
--- /dev/null
+++ b/private/nw/nwscript/nds.c
@@ -0,0 +1,1505 @@
+/*************************************************************************
+*
+* NDS.C
+*
+* NT NetWare NDS routines
+*
+* Copyright (c) 1995 Microsoft Corporation
+*
+*************************************************************************/
+#include <common.h>
+
+DWORD GUserObjectID;
+HANDLE GhRdr;
+
+
+WCHAR * NDSTREE_w = NULL;
+UNICODE_STRING NDSTREE_u;
+
+/********************************************************************
+
+ ExpandRelativeName
+
+Routine Description:
+
+ If the name is a relative NDS name append the proper context
+ to the end. A relative name has periods on the end. Each
+ period represents one level up the NDS tree.
+
+Arguments:
+
+Return Value:
+
+ *******************************************************************/
+void
+ExpandRelativeName( LPSTR RelativeName, LPSTR AbsoluteName, unsigned int Len,
+ LPSTR Context )
+{
+
+ PBYTE ptr;
+ unsigned int i;
+ unsigned int count = 0;
+
+ strncpy( AbsoluteName, RelativeName, Len );
+
+ if ( ( AbsoluteName[0] == '.' ) &&
+ ( AbsoluteName[ strlen( AbsoluteName ) - 1 ] != '.' ) )
+ return;
+
+ if ( ( strlen( AbsoluteName ) + strlen( Context ) ) > Len )
+ {
+ DisplayMessage( IDR_NOT_ENOUGH_MEMORY );
+ return;
+ }
+
+ if ( AbsoluteName[0] == '\0' )
+ {
+ return;
+ }
+
+ ptr = &AbsoluteName[ strlen( AbsoluteName ) - 1 ];
+
+ // Count the number of periods and back up over them.
+
+ if ( *ptr != '.' )
+ {
+ //
+ // No periods at the end
+ // Assume this is a relative name and append the context
+ //
+ strcat( AbsoluteName, "." );
+ strcat( AbsoluteName + strlen( AbsoluteName ), Context );
+ return;
+ }
+
+ while ( *ptr == '.' )
+ {
+ ptr--;
+ count++;
+ }
+
+ ptr++;
+ *ptr = '\0';
+
+ // ptr now points to where the copy of the rest of the context should start
+ // skip the first "count" entries in the context
+
+ ptr = Context;
+
+ for ( i = 0; i < count; i++ )
+ {
+ ptr = strchr( ptr, '.' );
+ if ( ptr == NULL )
+ {
+ return;
+ }
+ ptr++;
+ }
+ ptr--;
+
+ // Now append
+
+ strcat( AbsoluteName, ptr );
+
+}
+
+
+
+/********************************************************************
+
+ NDSGetNameContext
+
+Routine Description:
+
+ Get the current context
+
+Arguments:
+ none
+
+Return Value:
+ none
+
+ *******************************************************************/
+NTSTATUS
+NDSGetNameContext( LPSTR Context, BOOLEAN flag )
+{
+ //
+ // For NdsResolveName.
+ //
+
+ UNICODE_STRING ReferredServer;
+ WCHAR ServerStr[MAX_NAME_LEN];
+ HANDLE hReferredServer;
+ DWORD dwHandleType;
+
+ NTSTATUS Status;
+
+ OEM_STRING oemStr;
+ UNICODE_STRING defaultcontext;
+ DWORD ThisObjectID;
+ BYTE Buffer[2048];
+ WCHAR NdsStr[1024];
+ PBYTE ptr;
+
+ defaultcontext.Length = 0;
+ defaultcontext.MaximumLength = sizeof( NdsStr );
+ defaultcontext.Buffer = NdsStr;
+
+ Status = NwNdsGetTreeContext( GhRdr, &NDSTREE_u, &defaultcontext );
+
+ if ( !NT_SUCCESS( Status ) ) {
+ return Status;
+ }
+
+ ReferredServer.Buffer = ServerStr;
+ ReferredServer.Length = 0;
+ ReferredServer.MaximumLength = sizeof( ServerStr );
+
+ Status = NwNdsResolveName ( GhRdr,
+ &defaultcontext,
+ &ThisObjectID,
+ &ReferredServer,
+ NULL,
+ 0 );
+
+ if ( !NT_SUCCESS( Status ) ) {
+ return Status;
+ }
+
+ if ( ReferredServer.Length > 0 ) {
+
+ //
+ // We've been referred to another server, so we
+ // should change the global handle.
+ //
+
+ Status = NwNdsOpenGenericHandle( &ReferredServer,
+ &dwHandleType,
+ &hReferredServer );
+
+ if ( !NT_SUCCESS( Status ) ) {
+ DisplayMessage(IDR_NDS_USERNAME_FAILED);
+ return Status;
+ }
+
+ CloseHandle( GhRdr );
+ GhRdr = hReferredServer;
+ }
+
+ Status = NwNdsReadObjectInfo( GhRdr, ThisObjectID, Buffer, 2048 );
+
+ if ( !NT_SUCCESS( Status ) ) {
+ return Status;
+ }
+
+ ptr = Buffer + sizeof( NDS_RESPONSE_GET_OBJECT_INFO );
+ ptr += ROUNDUP4(*(DWORD *)ptr);
+ ptr += sizeof(DWORD);
+ ptr += sizeof(DWORD);
+
+ defaultcontext.Length = wcslen( (WCHAR *)ptr ) * 2;
+ defaultcontext.MaximumLength = defaultcontext.Length;
+ defaultcontext.Buffer = (WCHAR *)ptr;
+
+ oemStr.Length = 0;
+ oemStr.MaximumLength = NDS_NAME_CHARS;
+ oemStr.Buffer = Context;
+
+ RtlUnicodeStringToOemString( &oemStr, &defaultcontext, FALSE );
+
+ return 0;
+}
+
+/********************************************************************
+
+ NDSTypeless
+
+Routine Description:
+
+ Change name to typelese
+
+Arguments:
+ none
+
+Return Value:
+ none
+
+ *******************************************************************/
+unsigned int
+NDSTypeless( LPSTR OrigName , LPSTR TypelessName )
+{
+ int i,j;
+ PBYTE p;
+
+ i = 0;
+ j = 0;
+
+ if ( !_strnicmp( "CN=", OrigName, 3 ) ||
+ !_strnicmp( "OU=", OrigName, 3 ) )
+ {
+ i += 3;
+ }
+ else if ( !_strnicmp( "C=", OrigName, 2 ) ||
+ !_strnicmp( "O=", OrigName, 2 ) )
+ {
+ i += 2;
+ }
+
+ for ( ; (( i < NDS_NAME_CHARS ) && ( OrigName[i] ) ); i++ )
+ {
+ if ( !_strnicmp( ".CN=", &OrigName[i], 4 ) ||
+ !_strnicmp( ".OU=", &OrigName[i], 4 ) )
+ {
+ TypelessName[j++]= '.';
+ i += 3;
+ continue;
+ }
+ if ( !_strnicmp( ".C=", &OrigName[i], 3 ) ||
+ !_strnicmp( ".O=", &OrigName[i], 3 ) )
+ {
+ TypelessName[j++]= '.';
+ i += 2;
+ continue;
+ }
+ /*
+ * Strip out multiple blanks
+ */
+ if ( !_strnicmp( " ", &OrigName[i], 2 ) )
+ {
+ continue;
+ }
+ TypelessName[j++] = OrigName[i];
+ }
+
+ TypelessName[j] = '\0';
+
+ return 0;
+}
+
+/********************************************************************
+
+ NDSAbbreviateName
+
+Routine Description:
+
+ Abbreviate name
+
+Arguments:
+ none
+
+Return Value:
+ none
+
+ *******************************************************************/
+unsigned int
+NDSAbbreviateName( DWORD Flags, LPSTR OrigName , LPSTR AbbrevName )
+{
+ BYTE Buffer[NDS_NAME_CHARS];
+ BYTE CurrentContext[NDS_NAME_CHARS];
+ PBYTE p;
+ PBYTE c;
+ NTSTATUS Status;
+
+ if ( OrigName[0] == '.' )
+ NDSTypeless( OrigName + 1, Buffer );
+ else
+ NDSTypeless( OrigName, Buffer );
+
+ /*
+ * We want a relative name
+ */
+ if ( Flags & FLAGS_LOCAL_CONTEXT )
+ {
+ p = &Buffer[strlen(Buffer)-strlen(REQUESTER_CONTEXT)];
+ if ( !_strcmpi( REQUESTER_CONTEXT, p ) )
+ {
+ // The name is below us
+
+ if ( ( *(p-1) == '.' ) && ( p > Buffer ) )
+ p--;
+ *p = '\0';
+ strcpy( AbbrevName, Buffer );
+ }
+ else
+ {
+ //
+ // Going from back to front for each section of context
+ // in common with AbbrevName
+ // truncate both
+ // Going from back to front for each section of context
+ // left over
+ // concatonate a period to AbbrevName
+ //
+ // Example
+ //
+ // Name: w.x.y.z Context: a.b.z => w.x.y..
+ //
+
+ strcpy( CurrentContext, REQUESTER_CONTEXT );
+ strcpy( AbbrevName, Buffer );
+
+ if ( CurrentContext[0] && AbbrevName[0] )
+ {
+ c = &CurrentContext[ strlen( CurrentContext ) ] - 1;
+ p = &AbbrevName[ strlen( AbbrevName ) ] - 1;
+
+ //
+ // Strip off the matching names from end to front
+ //
+ for ( ;; )
+ {
+ if ( ( c == CurrentContext ) && ( *p == '.' ) )
+ {
+ *c = '\0';
+ *p = '\0';
+ break;
+ }
+
+ if ( *c != *p )
+ break;
+
+ if ( ( *c == '.' ) && ( *p == '.' ) )
+ {
+ *c = '\0';
+ *p = '\0';
+ }
+
+ if ( ( c == CurrentContext ) || ( p == AbbrevName ) )
+ {
+ break;
+ }
+
+ c--; p--;
+ }
+
+ //
+ // Count the remaining sections of the context and
+ // add that number of periods to the end of the buffer.
+ // That is how far we need to back up before getting
+ // to a matching branch of the tree.
+ //
+
+ if ( CurrentContext[0] ) {
+ strcat( AbbrevName, "." );
+ for ( c = CurrentContext; *c; c++ ) {
+ if ( *c == '.' )
+ strcat( AbbrevName, "." );
+ }
+ }
+ }
+
+ }
+ }
+ else
+ strcpy( AbbrevName, Buffer );
+
+ return 0;
+}
+
+
+/********************************************************************
+
+ NDSInitUserProperty
+
+Routine Description:
+
+ none
+
+Arguments:
+ none
+
+Return Value:
+ 0 = no error
+
+ *******************************************************************/
+unsigned int
+NDSInitUserProperty( )
+{
+ NTSTATUS Status;
+ UNICODE_STRING ObjectName;
+ PWCHAR lpT;
+ UNICODE_STRING defaultcontext;
+
+ //
+ // For NdsResolveName.
+ //
+
+ UNICODE_STRING ReferredServer;
+ WCHAR ServerStr[MAX_NAME_LEN];
+ HANDLE hReferredServer;
+ DWORD dwHandleType;
+
+ //
+ // Get a handle to the redirector.
+ //
+
+ Status = NwNdsOpenTreeHandle( &NDSTREE_u, &GhRdr );
+
+ if ( !NT_SUCCESS( Status ) ) {
+ DisplayMessage(IDR_TREE_OPEN_FAILED);
+ return 1;
+ }
+
+ //
+ // Resolve the name that we have to an object id.
+ //
+
+ RtlInitUnicodeString( &ObjectName, TYPED_USER_NAME_w );
+
+ ReferredServer.Buffer = ServerStr;
+ ReferredServer.Length = 0;
+ ReferredServer.MaximumLength = sizeof( ServerStr );
+
+ Status = NwNdsResolveName ( GhRdr,
+ &ObjectName,
+ &GUserObjectID,
+ &ReferredServer,
+ NULL,
+ 0 );
+
+ if ( !NT_SUCCESS( Status ) ) {
+ DisplayMessage(IDR_NDS_USERNAME_FAILED);
+ return 1;
+ }
+
+ if ( ReferredServer.Length > 0 ) {
+
+ //
+ // We've been referred to another server, so we
+ // should change the global handle.
+ //
+
+ Status = NwNdsOpenGenericHandle( &ReferredServer,
+ &dwHandleType,
+ &hReferredServer );
+
+ if ( !NT_SUCCESS( Status ) ) {
+ DisplayMessage(IDR_NDS_USERNAME_FAILED);
+ return 1;
+ }
+
+ CloseHandle( GhRdr );
+ GhRdr = hReferredServer;
+ }
+
+ //
+ // Set the current context to what we think it should be
+ // (At the user's location.)
+ //
+
+ lpT = wcschr( TYPED_USER_NAME_w, L'.' );
+ if ( lpT )
+ {
+ RtlInitUnicodeString( &defaultcontext, lpT+1 );
+ }
+ else
+ {
+ RtlInitUnicodeString( &defaultcontext, L"" );
+ }
+
+ Status = NwNdsSetTreeContext( GhRdr, &NDSTREE_u, &defaultcontext );
+
+ if ( !NT_SUCCESS( Status ) ) {
+ DisplayMessage(IDR_NDS_CONTEXT_INVALID);
+ return 1;
+ }
+
+ return 0;
+
+
+}
+
+/********************************************************************
+
+ NDSCanonicalizeName
+
+Routine Description:
+
+ return a canonicalized version of a name
+
+Arguments:
+ Name - original name
+ CanonName - Canonicalized name
+ Len - length of CanonName
+ fCurrentContext - TRUE => use current contex, FALSE use
+ requester context
+
+Return Value:
+ status error
+
+ *******************************************************************/
+unsigned int
+NDSCanonicalizeName( PBYTE Name, PBYTE CanonName, int Len, int fCurrentContext )
+{
+ NTSTATUS Status;
+ int ccode = -1;
+ DWORD ThisObjectID;
+ OEM_STRING oemStr;
+ UNICODE_STRING ObjectName;
+ BYTE Buffer[2048];
+ BYTE FullName[NDS_NAME_CHARS];
+ PBYTE ptr;
+ UNICODE_STRING ReferredServer;
+ WCHAR ServerStr[MAX_NAME_LEN];
+ DWORD dwHandleType;
+ HANDLE hReferredServer;
+ unsigned char CurrentContext[NDS_NAME_CHARS];
+
+ //
+ // Cope with relative names
+ //
+ if ( fCurrentContext )
+ {
+ Status = NDSGetNameContext( CurrentContext, TRUE );
+ if ( !NT_SUCCESS( Status ) )
+ return Status;
+ ExpandRelativeName( Name, FullName, NDS_NAME_CHARS, CurrentContext );
+ }
+ else
+ ExpandRelativeName( Name, FullName, NDS_NAME_CHARS, REQUESTER_CONTEXT );
+
+ //
+ // Fill it in in case we have an error
+ //
+ strncpy( CanonName, FullName, Len);
+
+ //
+ // Resolve the name that we have to an object id.
+ //
+ // Unfortuneately, the name resolver doesn't understand periods at the
+ // front or end (absolute or relative names)
+ //
+
+ if ( FullName[0] == '.' )
+ {
+ oemStr.Length = strlen( FullName + 1 );
+ oemStr.MaximumLength = oemStr.Length;
+ oemStr.Buffer = FullName + 1;
+ }
+ else
+ {
+ oemStr.Length = strlen( FullName );
+ oemStr.MaximumLength = oemStr.Length;
+ oemStr.Buffer = FullName;
+ }
+
+ ObjectName.Length = 0;
+ ObjectName.MaximumLength = sizeof(Buffer);
+ ObjectName.Buffer = (WCHAR *)Buffer;
+
+ RtlOemStringToUnicodeString( &ObjectName, &oemStr, FALSE );
+
+ ReferredServer.Buffer = ServerStr;
+ ReferredServer.Length = 0;
+ ReferredServer.MaximumLength = sizeof( ServerStr );
+
+ Status = NwNdsResolveName ( GhRdr,
+ &ObjectName,
+ &ThisObjectID,
+ &ReferredServer,
+ NULL,
+ 0 );
+
+ if ( !NT_SUCCESS( Status ) ) {
+ return Status;
+ }
+
+ if ( ReferredServer.Length > 0 ) {
+
+ //
+ // We've been referred to another server, so we
+ // should change the global handle.
+ //
+
+ Status = NwNdsOpenGenericHandle( &ReferredServer,
+ &dwHandleType,
+ &hReferredServer );
+
+ if ( !NT_SUCCESS( Status ) ) {
+ return Status;
+ }
+
+ CloseHandle( GhRdr );
+ GhRdr = hReferredServer;
+ }
+
+ Status = NwNdsReadObjectInfo( GhRdr, ThisObjectID, Buffer, 2048 );
+ if ( !NT_SUCCESS( Status ) ) {
+ return Status;
+ }
+
+ ptr = Buffer + sizeof( NDS_RESPONSE_GET_OBJECT_INFO );
+ ptr += ROUNDUP4(*(DWORD *)ptr);
+ ptr += sizeof(DWORD);
+ ptr += sizeof(DWORD);
+
+ RtlInitUnicodeString( &ObjectName, (PWCHAR)ptr );
+
+ oemStr.Length = 0;
+ oemStr.MaximumLength = Len;
+ oemStr.Buffer = CanonName;
+
+ RtlUnicodeStringToOemString( &oemStr, &ObjectName, FALSE );
+
+ return 0;
+}
+
+/********************************************************************
+
+ NDSGetUserProperty
+
+Routine Description:
+
+ Return the NDS property for the object
+
+Arguments:
+ Property - property name
+ Data - data buffer
+ Size - size of data buffer
+
+Return Value:
+ 0 no error
+
+ *******************************************************************/
+unsigned int
+NDSGetUserProperty( PBYTE Property,
+ PBYTE Data,
+ unsigned int Size,
+ SYNTAX * pSyntaxID,
+ unsigned int * pActualSize )
+{
+ NTSTATUS Status;
+ int ccode = -1;
+
+ OEM_STRING oemStr;
+ UNICODE_STRING PropertyName;
+ WCHAR NdsStr[1024];
+ DWORD iterhandle = INITIAL_ITERATION;
+
+ BYTE Buffer[2048];
+ DWORD BufferSize = 2048;
+ PNDS_RESPONSE_READ_ATTRIBUTE pReadAttribute;
+ PNDS_ATTRIBUTE pAttribute;
+ PBYTE pAttribValue;
+
+ //
+ // Read the User property
+ //
+
+ memset(Buffer, 0, BufferSize);
+
+ oemStr.Length = strlen( Property );
+ oemStr.MaximumLength = oemStr.Length;
+ oemStr.Buffer = Property;
+
+ PropertyName.Length = 0;
+ PropertyName.MaximumLength = sizeof(NdsStr);
+ PropertyName.Buffer = NdsStr;
+
+ RtlOemStringToUnicodeString( &PropertyName, &oemStr, FALSE );
+
+ Status = NwNdsReadAttribute ( GhRdr,
+ GUserObjectID,
+ &iterhandle,
+ &PropertyName,
+ Buffer,
+ BufferSize );
+
+ if ( NT_SUCCESS(Status) )
+ {
+ int i;
+ pReadAttribute = (PNDS_RESPONSE_READ_ATTRIBUTE)Buffer;
+ pAttribute = (PNDS_ATTRIBUTE)(Buffer
+ + sizeof(NDS_RESPONSE_READ_ATTRIBUTE));
+ if ( pSyntaxID )
+ {
+ *pSyntaxID = pAttribute->SyntaxID;
+ }
+
+ pAttribValue = (PBYTE)(pAttribute->AttribName) +
+ ROUNDUP4(pAttribute->AttribNameLength) +
+ sizeof(DWORD);
+
+ if ( pActualSize )
+ {
+ *pActualSize = *(DWORD *)pAttribValue;
+ }
+
+ memcpy( Data, pAttribValue + sizeof(DWORD),
+ min(*(DWORD *)pAttribValue, Size) );
+
+ }
+
+ return Status;
+}
+
+
+/********************************************************************
+
+ NDSGetVar
+
+Routine Description:
+
+ Return value of user property
+
+ Get the syntax type of the property
+ Retrieve the data
+ Do any data conversion
+
+Arguments:
+ Name - of NDS property IN
+ Value - value buffer OUT
+ Size - size of value buffer IN
+
+Return Value:
+ none
+
+ *******************************************************************/
+void
+NDSGetVar ( PBYTE Name, PBYTE Value, unsigned int Size)
+{
+ unsigned int err;
+ SYNTAX Syntax;
+ BYTE Buffer[ATTRBUFSIZE];
+ DWORD ActualSize;
+
+ Value[0] = 0;
+
+ err = NDSGetUserProperty( Name, Buffer, ATTRBUFSIZE, &Syntax, &ActualSize );
+
+ if ( err )
+ {
+ return;
+ }
+
+ switch ( Syntax )
+ {
+ case NDSI_BOOLEAN:
+ if ( *(PBYTE)Buffer )
+ {
+ strcpy( Value, "Y" );
+ }
+ else
+ {
+ strcpy( Value, "N" );
+ }
+ break;
+ case NDSI_DIST_NAME:
+ case NDSI_CE_STRING:
+ case NDSI_CI_STRING:
+ case NDSI_OCTET_STRING:
+ case NDSI_PR_STRING:
+ case NDSI_NU_STRING:
+ case NDSI_TEL_NUMBER:
+ case NDSI_CLASS_NAME:
+ ConvertUnicodeToAscii( Buffer );
+ if ( Syntax == NDSI_DIST_NAME )
+ NDSAbbreviateName(FLAGS_LOCAL_CONTEXT, Buffer, Buffer);
+ strncpy( Value, Buffer, Size );
+ break;
+ case NDSI_CI_LIST:
+ ConvertUnicodeToAscii( Buffer+8 );
+ strncpy( Value, Buffer+8, Size );
+ break;
+ break;
+ case NDSI_INTEGER:
+ case NDSI_COUNTER:
+ case NDSI_TIME:
+ case NDSI_INTERVAL:
+ case NDSI_TIMESTAMP:
+ sprintf( Value, "%d", *(int *)Buffer );
+ break;
+ case NDSI_PO_ADDRESS:
+ {
+ // 6 null terminated lines
+ int line,len;
+ PBYTE ptr = Buffer + 4;
+
+ // Stop if not 6 lines
+ if ( *(int *)Buffer != 6 )
+ break;
+
+ for (line = 0; line <= 5; line++) {
+ len = ROUNDUP4(*(int *)ptr);
+ ptr += 4;
+ if ( !len )
+ break;
+ ConvertUnicodeToAscii( ptr );
+ strcat( Value, ptr );
+ strcat( Value, "\n" );
+ ptr += len;
+ }
+ }
+ break;
+ case NDSI_FAX_NUMBER:
+ if ( *(int *)Buffer == 0 )
+ return;
+ ConvertUnicodeToAscii( Buffer+4 );
+ strncpy( Value, Buffer+4, Size );
+ break;
+ case NDSI_EMAIL_ADDRESS:
+ if ( *(int *)(Buffer+4) == 0 )
+ return;
+ ConvertUnicodeToAscii( Buffer+8 );
+ strncpy( Value, Buffer+8, Size );
+ break;
+ case NDSI_PATH:
+ {
+ int len;
+
+ len = *(int *)(Buffer+4);
+ if ( len == 0 )
+ break;
+ len = ROUNDUP4( len );
+ ConvertUnicodeToAscii( Buffer+8 );
+ strcpy( Value, Buffer+8 );
+ NDSAbbreviateName(FLAGS_LOCAL_CONTEXT, Value, Value);
+ strcat( Value, ":" );
+ if ( *(int *)(Buffer + 8 + len) == 0 )
+ break;
+ ConvertUnicodeToAscii( Buffer+8+len+4 );
+ strcat( Value, Buffer+8+len+4 );
+ break;
+ }
+ case NDSI_NET_ADDRESS:
+ case NDSI_OCTET_LIST:
+ case NDSI_OBJECT_ACL:
+ case NDSI_STREAM:
+ case NDSI_UNKNOWN:
+ case NDSI_REPLICA_POINTER:
+ case NDSI_BACK_LINK:
+ case NDSI_TYPED_NAME:
+ case NDSI_HOLD:
+ case NDSI_TAX_COUNT:
+ default:
+ Value[0] = '\0';
+ Value[1] = '\0';
+ break;
+ }
+
+}
+
+/********************************************************************
+
+ NDSChangeContext
+
+Routine Description:
+
+ Change the current context
+
+Arguments:
+ Context - context string IN
+
+Return Value:
+ error number
+
+ *******************************************************************/
+unsigned int
+NDSChangeContext( PBYTE Context )
+{
+ NTSTATUS Status;
+
+ OEM_STRING oemStr;
+ UNICODE_STRING defaultcontext;
+ WCHAR NdsStr[1024];
+
+ oemStr.Length = strlen( Context );
+ oemStr.MaximumLength = oemStr.Length;
+ oemStr.Buffer = Context;
+
+ defaultcontext.Length = 0;
+ defaultcontext.MaximumLength = sizeof(NdsStr);
+ defaultcontext.Buffer = NdsStr;
+
+ RtlOemStringToUnicodeString( &defaultcontext, &oemStr, FALSE );
+
+ Status = NwNdsSetTreeContext( GhRdr, &NDSTREE_u, &defaultcontext );
+
+ return Status;
+}
+
+/********************************************************************
+
+ NDSGetContext
+
+Routine Description:
+
+ Retrieve the current context
+
+Arguments:
+ Buffer - data buffer for context string OUT
+ len - length of data buffer IN
+
+Return Value:
+ error number
+
+ *******************************************************************/
+unsigned int
+NDSGetContext( PBYTE Buffer,
+ unsigned int len )
+{
+ NTSTATUS Status;
+
+ Status = NDSGetNameContext( Buffer, TRUE );
+ if ( !NT_SUCCESS( Status ) )
+ return Status;
+ NDSAbbreviateName(FLAGS_NO_CONTEXT, Buffer, Buffer);
+ return 0;
+}
+
+/********************************************************************
+
+ NDSfopenStream
+
+Routine Description:
+
+ Open a file handle to an NDS stream property
+
+Arguments:
+ Object - name of object IN
+ Property - name of property IN
+ pStream - pointer to file handle OUT
+ pFileSize - pointer to file size OUT
+
+Return Value:
+ error
+
+ *******************************************************************/
+unsigned int
+NDSfopenStream ( PBYTE Object,
+ PBYTE Property,
+ PHANDLE pStream,
+ unsigned int * pFileSize )
+{
+ //
+ // Status variables.
+ //
+
+ NTSTATUS Status;
+ int ccode = -1;
+
+ //
+ // For NwNdsOpenTreeHandle.
+ //
+
+ HANDLE hRdr;
+ OEM_STRING oemStr;
+ UNICODE_STRING ObjectName;
+ WCHAR NdsStr[1024];
+
+ //
+ // For NwNdsResolveName.
+ //
+
+ DWORD dwOid;
+ UNICODE_STRING ReferredServer;
+ WCHAR ServerStr[MAX_NAME_LEN];
+ DWORD dwHandleType;
+ HANDLE hReferredServer;
+
+ //
+ // Get a handle to the redirector.
+ //
+
+ Status = NwNdsOpenTreeHandle( &NDSTREE_u, &hRdr );
+
+ if ( !NT_SUCCESS( Status ) ) {
+ DisplayMessage(IDR_TREE_OPEN_FAILED);
+ return ccode;
+ }
+
+ //
+ // Resolve the name that we have to an object id.
+ //
+
+ if ( !Object )
+ {
+ return 1;
+ }
+
+ oemStr.Length = strlen( Object );
+ oemStr.MaximumLength = oemStr.Length;
+ oemStr.Buffer = Object;
+
+ ObjectName.Length = 0;
+ ObjectName.MaximumLength = sizeof(NdsStr);
+ ObjectName.Buffer = NdsStr;
+
+ RtlOemStringToUnicodeString( &ObjectName, &oemStr, FALSE );
+
+ ReferredServer.Buffer = ServerStr;
+ ReferredServer.Length = 0;
+ ReferredServer.MaximumLength = sizeof( ServerStr );
+
+ Status = NwNdsResolveName ( hRdr,
+ &ObjectName,
+ &dwOid,
+ &ReferredServer,
+ NULL,
+ 0 );
+
+ if ( !NT_SUCCESS( Status ) ) {
+ return 0xffffffff;
+ }
+
+ if ( ReferredServer.Length > 0 ) {
+
+ //
+ // We've been referred to another server, so we
+ // must jump to that server before continuing.
+ //
+
+ Status = NwNdsOpenGenericHandle( &ReferredServer,
+ &dwHandleType,
+ &hReferredServer );
+
+ if ( !NT_SUCCESS( Status ) ) {
+ return 0xffffffff;
+ }
+
+ CloseHandle( hRdr );
+ hRdr = hReferredServer;
+ }
+
+ //
+ // Open the file stream.
+ //
+
+ oemStr.Length = strlen( Property );
+ oemStr.MaximumLength = oemStr.Length;
+ oemStr.Buffer = Property;
+
+ ObjectName.Length = 0;
+ ObjectName.MaximumLength = sizeof(NdsStr);
+ ObjectName.Buffer = NdsStr;
+
+ RtlOemStringToUnicodeString( &ObjectName, &oemStr, FALSE );
+
+ //
+ // Try to open a file stream for read access.
+ //
+
+ Status = NwNdsOpenStream( hRdr,
+ dwOid,
+ &ObjectName,
+ 1, // Read access.
+ pFileSize );
+
+ if ( !NT_SUCCESS( Status ) ) {
+ return 0xffffffff;
+ }
+
+ *pStream = hRdr;
+
+ return 0;
+}
+
+/*
+ * IsMemberOfNDSGroup
+ * ------------------
+ *
+ * Returns true if currently logged in user object is member of group with given name
+ *
+ */
+unsigned int
+IsMemberOfNDSGroup(
+ PBYTE nwGroup
+ )
+{
+ NTSTATUS Status;
+ UINT nwRet;
+ BYTE szCanonTargetGroupName[NDS_NAME_CHARS+1];
+ UINT syntaxid;
+ UINT actualsize;
+ LPSTR szBuffer;
+ LPSTR pProp;
+ UINT i;
+ DWORD iterhandle = INITIAL_ITERATION;
+ UINT fFoundGroup = FALSE;
+ PNDS_RESPONSE_READ_ATTRIBUTE pReadAttribute;
+ PNDS_ATTRIBUTE pAttribute;
+ PBYTE pAttribValue;
+ UNICODE_STRING PropertyName;
+ UINT numvalues = 0;
+
+
+ szBuffer = (BYTE *)malloc(ATTRBUFSIZE);
+
+ if ( !szBuffer ) {
+ DisplayMessage(IDR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+ memset( szBuffer, 0, ATTRBUFSIZE );
+
+ // Canonicalize name according to current context
+
+ strcpy( szCanonTargetGroupName, nwGroup );
+
+ nwRet = NDSCanonicalizeName( szCanonTargetGroupName,
+ szCanonTargetGroupName,
+ NDS_NAME_CHARS,
+ TRUE );
+ if (nwRet) {
+
+ if ( nwGroup[0] != '.' ) {
+
+ // Try an absolute name
+
+ strcpy( szCanonTargetGroupName, "." );
+ strcat( szCanonTargetGroupName, nwGroup );
+
+ nwRet = NDSCanonicalizeName( szCanonTargetGroupName,
+ szCanonTargetGroupName,
+ NDS_NAME_CHARS,
+ TRUE );
+ }
+
+ if ( nwRet )
+ goto CleanRet;
+ }
+
+ // Should check class name of object
+
+ RtlInitUnicodeString( &PropertyName, L"Group Membership" );
+
+ Status = NwNdsReadAttribute ( GhRdr,
+ GUserObjectID,
+ &iterhandle,
+ &PropertyName,
+ szBuffer,
+ ATTRBUFSIZE );
+
+ if ( !NT_SUCCESS(Status) )
+ {
+ return FALSE;
+ }
+
+ pReadAttribute = (PNDS_RESPONSE_READ_ATTRIBUTE)szBuffer;
+
+ pAttribute = (PNDS_ATTRIBUTE)(szBuffer
+ + sizeof(NDS_RESPONSE_READ_ATTRIBUTE));
+ pAttribute->SyntaxID;
+
+ pAttribValue = (PBYTE)(pAttribute->AttribName) +
+ ROUNDUP4(pAttribute->AttribNameLength) +
+ sizeof(DWORD);
+
+ numvalues = *(PUINT)((PBYTE)(pAttribute->AttribName) +
+ ROUNDUP4(pAttribute->AttribNameLength));
+
+ if ( *(DWORD *)pAttribValue == 0 )
+ {
+ return FALSE;
+ }
+
+ for ( i = 0; i < numvalues; i++ ) {
+ ConvertUnicodeToAscii( pAttribValue+sizeof(DWORD) );
+ if (!_stricmp(pAttribValue+sizeof(DWORD),szCanonTargetGroupName)) {
+ fFoundGroup = TRUE;
+ break;
+ }
+ pAttribValue += ROUNDUP4(*(PUINT)pAttribValue) + sizeof(DWORD);
+ }
+
+
+
+CleanRet:
+ if (szBuffer ) {
+ free (szBuffer);
+ }
+ return fFoundGroup;
+}
+
+/********************************************************************
+
+ NDSGetProperty
+
+Routine Description:
+
+ Return the NDS property for the object
+
+Arguments:
+ Object - name of object IN
+ Property - property name IN
+ Data - data buffer OUT
+ Size - size of data buffer IN
+ pActualSize - real data size OUT
+
+Return Value:
+ error
+
+ *******************************************************************/
+unsigned int
+NDSGetProperty ( PBYTE Object,
+ PBYTE Property,
+ PBYTE Data,
+ unsigned int Size,
+ unsigned int * pActualSize )
+{
+ //
+ // Status variables.
+ //
+
+ NTSTATUS Status;
+ int ccode = -1;
+
+ //
+ // For NwNdsOpenTreeHandle.
+ //
+
+ HANDLE hRdr;
+ OEM_STRING oemStr;
+ UNICODE_STRING ObjectName;
+ WCHAR NdsStr[1024];
+
+ //
+ // For NwNdsResolveName.
+ //
+
+ DWORD dwOid;
+ UNICODE_STRING ReferredServer;
+ WCHAR ServerStr[MAX_NAME_LEN];
+ DWORD dwHandleType;
+ HANDLE hReferredServer;
+
+ //
+ // For NwNdsReadAttribute
+ //
+ BYTE Buffer[2048];
+ DWORD BufferSize = 2048;
+ DWORD iterhandle = INITIAL_ITERATION;
+ PNDS_RESPONSE_READ_ATTRIBUTE pReadAttribute;
+ PNDS_ATTRIBUTE pAttribute;
+ PBYTE pAttribValue;
+
+ //
+ // Get a handle to the redirector.
+ //
+
+ Status = NwNdsOpenTreeHandle( &NDSTREE_u, &hRdr );
+
+ if ( !NT_SUCCESS( Status ) ) {
+ DisplayMessage(IDR_TREE_OPEN_FAILED);
+ return ccode;
+ }
+
+ //
+ // Resolve the name that we have to an object id.
+ //
+
+ if ( !Object )
+ {
+ return 1;
+ }
+
+ oemStr.Length = strlen( Object );
+ oemStr.MaximumLength = oemStr.Length;
+ oemStr.Buffer = Object;
+
+ ObjectName.Length = 0;
+ ObjectName.MaximumLength = sizeof(NdsStr);
+ ObjectName.Buffer = NdsStr;
+
+ RtlOemStringToUnicodeString( &ObjectName, &oemStr, FALSE );
+
+ ReferredServer.Buffer = ServerStr;
+ ReferredServer.Length = 0;
+ ReferredServer.MaximumLength = sizeof( ServerStr );
+
+ Status = NwNdsResolveName ( hRdr,
+ &ObjectName,
+ &dwOid,
+ &ReferredServer,
+ NULL,
+ 0 );
+
+ if ( !NT_SUCCESS( Status ) ) {
+ return 0xffffffff;
+ }
+
+ if ( ReferredServer.Length > 0 ) {
+
+ //
+ // We've been referred to another server, so we
+ // must jump to that server before continuing.
+ //
+
+ Status = NwNdsOpenGenericHandle( &ReferredServer,
+ &dwHandleType,
+ &hReferredServer );
+
+ if ( !NT_SUCCESS( Status ) ) {
+ return 0xffffffff;
+ }
+
+ CloseHandle( hRdr );
+ hRdr = hReferredServer;
+ }
+
+ //
+ // Get the attribute
+ //
+
+ oemStr.Length = strlen( Property );
+ oemStr.MaximumLength = oemStr.Length;
+ oemStr.Buffer = Property;
+
+ ObjectName.Length = 0;
+ ObjectName.MaximumLength = sizeof(NdsStr);
+ ObjectName.Buffer = NdsStr;
+
+ RtlOemStringToUnicodeString( &ObjectName, &oemStr, FALSE );
+
+ Status = NwNdsReadAttribute ( hRdr,
+ dwOid,
+ &iterhandle,
+ &ObjectName,
+ Buffer,
+ BufferSize );
+
+ if ( NT_SUCCESS(Status) )
+ {
+ int i;
+ pReadAttribute = (PNDS_RESPONSE_READ_ATTRIBUTE)Buffer;
+ pAttribute = (PNDS_ATTRIBUTE)(Buffer
+ + sizeof(NDS_RESPONSE_READ_ATTRIBUTE));
+
+ pAttribValue = (PBYTE)(pAttribute->AttribName) +
+ ROUNDUP4(pAttribute->AttribNameLength) +
+ sizeof(DWORD);
+
+ if ( pActualSize )
+ {
+ *pActualSize = *(DWORD *)pAttribValue;
+ }
+
+ memcpy( Data, pAttribValue + sizeof(DWORD),
+ min(*(DWORD *)pAttribValue, Size) );
+
+ }
+
+ NtClose( hRdr );
+
+ return Status;
+}
+
+
+/********************************************************************
+
+ NDSCleanup
+
+Routine Description:
+
+ Does any NDS cleanup
+
+Arguments:
+ none
+
+Return Value:
+ none
+
+ *******************************************************************/
+void
+NDSCleanup ( void )
+{
+ NtClose( GhRdr );
+}
+
+/********************************************************************
+
+ NDSGetClassName
+
+Routine Description:
+
+ return a class name for an object
+
+Arguments:
+ szObjectName
+ ClassName
+
+Return Value:
+ none
+
+ *******************************************************************/
+unsigned int
+NDSGetClassName( LPSTR szObjectName, LPSTR ClassName )
+{
+ NTSTATUS Status;
+ int ccode = -1;
+ DWORD ThisObjectID;
+ OEM_STRING oemStr;
+ UNICODE_STRING ObjectName;
+ BYTE Buffer[2048];
+ BYTE FullName[NDS_NAME_CHARS];
+ PBYTE ptr;
+ UNICODE_STRING ReferredServer;
+ WCHAR ServerStr[MAX_NAME_LEN];
+ DWORD dwHandleType;
+ HANDLE hReferredServer;
+ DWORD Length;
+
+ //
+ // Resolve the name that we have to an object id.
+ //
+
+ oemStr.Length = strlen( szObjectName );
+ oemStr.MaximumLength = oemStr.Length;
+ oemStr.Buffer = szObjectName;
+
+ ObjectName.Length = 0;
+ ObjectName.MaximumLength = sizeof(Buffer);
+ ObjectName.Buffer = (WCHAR *)Buffer;
+
+ RtlOemStringToUnicodeString( &ObjectName, &oemStr, FALSE );
+
+ ReferredServer.Buffer = ServerStr;
+ ReferredServer.Length = 0;
+ ReferredServer.MaximumLength = sizeof( ServerStr );
+
+ Status = NwNdsResolveName ( GhRdr,
+ &ObjectName,
+ &ThisObjectID,
+ &ReferredServer,
+ NULL,
+ 0 );
+
+ if ( !NT_SUCCESS( Status ) ) {
+ return Status;
+ }
+
+ if ( ReferredServer.Length > 0 ) {
+
+ //
+ // We've been referred to another server, so we
+ // should change the global handle.
+ //
+
+ Status = NwNdsOpenGenericHandle( &ReferredServer,
+ &dwHandleType,
+ &hReferredServer );
+
+ if ( !NT_SUCCESS( Status ) ) {
+ return Status;
+ }
+
+ CloseHandle( GhRdr );
+ GhRdr = hReferredServer;
+ }
+
+ Status = NwNdsReadObjectInfo( GhRdr, ThisObjectID, Buffer, 2048 );
+ if ( !NT_SUCCESS( Status ) ) {
+ return Status;
+ }
+
+ ptr = Buffer + sizeof( NDS_RESPONSE_GET_OBJECT_INFO ) + sizeof( DWORD );
+
+ RtlInitUnicodeString( &ObjectName, (PWCHAR)ptr );
+
+ oemStr.Length = 0;
+ oemStr.MaximumLength = NDS_NAME_CHARS;
+ oemStr.Buffer = ClassName;
+
+ RtlUnicodeStringToOemString( &oemStr, &ObjectName, FALSE );
+
+ return 0;
+}