From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/nw/nwscript/nds.c | 1505 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1505 insertions(+) create mode 100644 private/nw/nwscript/nds.c (limited to 'private/nw/nwscript/nds.c') 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 + +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; +} -- cgit v1.2.3