diff options
Diffstat (limited to '')
-rw-r--r-- | private/nw/svcdlls/nwwks/client/nwutil.c | 872 |
1 files changed, 872 insertions, 0 deletions
diff --git a/private/nw/svcdlls/nwwks/client/nwutil.c b/private/nw/svcdlls/nwwks/client/nwutil.c new file mode 100644 index 000000000..f39a0de0d --- /dev/null +++ b/private/nw/svcdlls/nwwks/client/nwutil.c @@ -0,0 +1,872 @@ +/*++ + +Copyright (c) 1995 Microsoft Corporation + +Module Name: + + nwutil.c + +Abstract: + + Contains some misc functions used by shell extensions + +Author: + + Yi-Hsin Sung (yihsins) 25-Oct-1995 + +Environment: + + User Mode - Win32 + +Revision History: + +--*/ + +#include <nt.h> +#include <ntrtl.h> +#include <nturtl.h> +#include <ntddnwfs.h> +#include <ndsapi32.h> +#include <nwmisc.h> +#include "nwclient.h" +#include "nwapi.h" +#include "nwutil.h" + +#define EXTRA_BYTES 256 + +BOOL +NwIsNdsSyntax( + IN LPWSTR lpstrUnc +) +{ + HANDLE hTreeConn; + DWORD dwOid; + DWORD status = NO_ERROR; + + if ( lpstrUnc == NULL ) + return FALSE; + + status = NwOpenAndGetTreeInfo( lpstrUnc, &hTreeConn, &dwOid ); + + if ( status != NO_ERROR ) + { + return FALSE; + } + + CloseHandle( hTreeConn ); + + return TRUE; +} + +VOID +NwAbbreviateUserName( + IN LPWSTR pszFullName, + OUT LPWSTR pszUserName +) +{ + if ( pszUserName == NULL ) + return; + + if ( NwIsNdsSyntax( pszFullName )) + { + // + // BUGBUG - This part of the code never gets called due to the + // change in how NwIsNdsSyntax works. Post NT 4.0, get rid of the + // NwIsNdsSyntax test and run this section of code no matter what. + // This bug was not fixed in NT4.0 due to the extremely close time + // to the ship date. + // + LPWSTR pszTemp = pszFullName; + LPWSTR pszLast = pszTemp; + + *pszUserName = 0; + + while ( pszTemp = wcschr( pszTemp, L'=')) + { + WCHAR NextChar; + + NextChar = *(++pszTemp); + + while ( NextChar != 0 && NextChar != L'.' ) + { + *(pszUserName++) = *pszTemp; + NextChar = *(++pszTemp); + } + + if ( NextChar == 0 ) + { + pszLast = NULL; + break; + } + + *(pszUserName++) = *pszTemp; // put back the '.' + pszLast = ++pszTemp; + } + + if ( pszLast != NULL ) + { + while ( *pszLast != 0 ) + *(pszUserName++) = *(pszLast++); + } + + *pszUserName = 0; + } + else + { + wcscpy( pszUserName, pszFullName ); + } +} + +VOID +NwMakePrettyDisplayName( + IN LPWSTR pszName +) +{ + if ( pszName ) + { + CharLower( pszName ); + CharUpperBuff( pszName, 1); + } +} + +VOID +NwExtractTreeName( + IN LPWSTR pszUNCPath, + OUT LPWSTR pszTreeName +) +{ + LPWSTR pszTemp = NULL; + + if ( pszTreeName == NULL ) + return; + + pszTreeName[0] = 0; + + if ( pszUNCPath == NULL ) + return; + + if ( pszUNCPath[0] == L' ') + pszUNCPath++; + + if ( ( pszUNCPath[0] != L'\\') + || ( pszUNCPath[1] != L'\\') + ) + { + return; + } + + wcscpy( pszTreeName, pszUNCPath + 2 ); // get past "\\" + + if ( pszTemp = wcschr( pszTreeName, L'\\' )) + *pszTemp = 0; +} + +VOID +NwExtractServerName( + IN LPWSTR pszUNCPath, + OUT LPWSTR pszServerName +) +{ + LPWSTR pszTemp = NULL; + + if ( pszServerName == NULL ) + return; + + pszServerName[0] = 0; + + if ( ( pszUNCPath == NULL ) + || ( pszUNCPath[0] != L'\\') + || ( pszUNCPath[1] != L'\\') + ) + { + return; + } + + if ( NwIsNdsSyntax( pszUNCPath )) + { + pszTemp = wcschr( pszUNCPath + 2, L'\\' ); // get past "\\" + wcscpy( pszServerName, pszTemp + 1 ); // get past "\" + + if ( pszTemp = wcschr( pszServerName, L'.' )) + *pszTemp = 0; + + } + else + { + wcscpy( pszServerName, pszUNCPath + 2 ); // get past "\\" + + if ( pszTemp = wcschr( pszServerName, L'\\' )) + *pszTemp = 0; + } +} + +VOID +NwExtractShareName( + IN LPWSTR pszUNCPath, + OUT LPWSTR pszShareName +) +{ + LPWSTR pszTemp = NULL; + + if ( pszShareName == NULL ) + return; + + pszShareName[0] = 0; + + if ( ( pszUNCPath == NULL ) + || ( pszUNCPath[0] != L'\\') + || ( pszUNCPath[1] != L'\\') + ) + { + return; + } + + if ( NwIsNdsSyntax( pszUNCPath )) + { + pszTemp = wcschr( pszUNCPath + 2, L'\\' ); // get past "\\" + wcscpy( pszShareName, pszTemp + 1 ); // get past "\" + + if ( pszTemp = wcschr( pszShareName, L'.' )) + *pszTemp = 0; + } + else + { + pszTemp = wcschr( pszUNCPath + 2, L'\\' ); // get past "\\" + wcscpy( pszShareName, pszTemp + 1); // get past "\" + + if ( pszTemp = wcschr( pszShareName, L'\\' )) + *pszTemp = 0; + } +} + +DWORD +NwIsServerInDefaultTree( + IN LPWSTR pszFullServerName, + OUT BOOL *pfInDefaultTree +) +{ + DWORD err = NO_ERROR; + LPWSTR pszCurrentContext = NULL; + DWORD dwPrintOptions; + WCHAR szTreeName[MAX_PATH + 1]; + + *pfInDefaultTree = FALSE; + + if ( !NwIsNdsSyntax( pszFullServerName )) + { + // The full server name does not contain any NDS information + // In this case, assume the server is not in the tree. + // If a server belongs the default tree, we would get the full + // NDS information. + return NO_ERROR; + } + + // Get the current default tree or server name + err = NwQueryInfo( &dwPrintOptions, &pszCurrentContext ); + + if ( (err == NO_ERROR) && ( *pszCurrentContext == TREECHAR)) + { + // Yes, there is a default tree. + // So, get the tree name out of *TREE\CONTEXT + LPWSTR pszTemp = wcschr( pszCurrentContext, L'\\'); + if ( pszTemp ) + *pszTemp = 0; + + // Need to extract the tree name from full UNC path + NwExtractTreeName( pszFullServerName, szTreeName ); + + if ( _wcsicmp( szTreeName, + pszCurrentContext + 1) == 0 ) // get past the tree char + { + *pfInDefaultTree = TRUE; + } + } + + if ( pszCurrentContext != NULL ) + LocalFree( pszCurrentContext ); + + return err; +} + +DWORD +NwIsServerOrTreeAttached( + IN LPWSTR pszName, + OUT BOOL *pfAttached, + OUT BOOL *pfAuthenticated +) +{ + DWORD err = NO_ERROR; + DWORD EntriesRead = 0; + DWORD ResumeKey = 0; + LPBYTE Buffer = NULL; + + err = NwGetConnectionStatus( + pszName, + &ResumeKey, + &Buffer, + &EntriesRead ); + + *pfAttached = FALSE; + *pfAuthenticated = FALSE; + + if (( err == NO_ERROR ) && ( EntriesRead > 0 )) + { + // For trees, we might get more than one entries back. + + PCONN_STATUS pConnStatus = (PCONN_STATUS) Buffer; + + if ( !pConnStatus->fPreferred ) + { + // We only need to return as attached if this is not a preferred + // server implicit connection since we don't want the user to know + // about this connection ( which rdr does not allow user to delete) + + *pfAttached = TRUE; + *pfAuthenticated = (pConnStatus->dwConnType != NW_CONN_NOT_AUTHENTICATED); + } + } + + if ( Buffer != NULL ) + { + LocalFree( Buffer ); + Buffer = NULL; + } + + return err; +} + +DWORD +NwGetConnectionInformation( + IN LPWSTR pszName, + OUT LPBYTE Buffer, + IN DWORD BufferSize +) +{ + NTSTATUS ntstatus = STATUS_SUCCESS; + HANDLE handleRdr = NULL; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + UNICODE_STRING uRdrName; + WCHAR RdrPrefix[] = L"\\Device\\NwRdr\\*"; + + PNWR_REQUEST_PACKET RequestPacket = NULL; + DWORD RequestPacketSize = 0; + DWORD dwNameLen = 0; + + if ( pszName == NULL ) + return ERROR_INVALID_PARAMETER; + + // + // Set up the object attributes. + // + + RtlInitUnicodeString( &uRdrName, RdrPrefix ); + + InitializeObjectAttributes( &ObjectAttributes, + &uRdrName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL ); + + ntstatus = NtOpenFile( &handleRdr, + SYNCHRONIZE | FILE_LIST_DIRECTORY, + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_VALID_FLAGS, + FILE_SYNCHRONOUS_IO_NONALERT ); + + if ( !NT_SUCCESS(ntstatus) ) + goto CleanExit; + + dwNameLen = wcslen(pszName) * sizeof(WCHAR); + + RequestPacketSize = sizeof( NWR_REQUEST_PACKET ) + dwNameLen; + + RequestPacket = (PNWR_REQUEST_PACKET) LocalAlloc( LMEM_ZEROINIT, + RequestPacketSize ); + + if ( RequestPacket == NULL ) + { + ntstatus = STATUS_NO_MEMORY; + goto CleanExit; + } + + // + // Fill out the request packet for FSCTL_NWR_GET_CONN_INFO. + // + + RequestPacket->Version = REQUEST_PACKET_VERSION; + RequestPacket->Parameters.GetConnInfo.ConnectionNameLength = dwNameLen; + + RtlCopyMemory( &(RequestPacket->Parameters.GetConnInfo.ConnectionName[0]), + pszName, + dwNameLen ); + + ntstatus = NtFsControlFile( handleRdr, + NULL, + NULL, + NULL, + &IoStatusBlock, + FSCTL_NWR_GET_CONN_INFO, + (PVOID) RequestPacket, + RequestPacketSize, + (PVOID) Buffer, + BufferSize ); + + if ( NT_SUCCESS( ntstatus )) + ntstatus = IoStatusBlock.Status; + +CleanExit: + + if ( handleRdr != NULL ) + NtClose( handleRdr ); + + if ( RequestPacket != NULL ) + LocalFree( RequestPacket ); + + return RtlNtStatusToDosError( ntstatus ); +} + +DWORD +NWPGetConnectionStatus( + IN LPWSTR pszRemoteName, + IN OUT PDWORD ResumeKey, + OUT LPBYTE Buffer, + IN DWORD BufferSize, + OUT PDWORD BytesNeeded, + OUT PDWORD EntriesRead +) +{ + NTSTATUS ntstatus = STATUS_SUCCESS; + HANDLE handleRdr = NULL; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + UNICODE_STRING uRdrName; + WCHAR RdrPrefix[] = L"\\Device\\NwRdr\\*"; + + PNWR_REQUEST_PACKET RequestPacket = NULL; + DWORD RequestPacketSize = 0; + DWORD dwRemoteNameLen = 0; + + // + // Set up the object attributes. + // + + RtlInitUnicodeString( &uRdrName, RdrPrefix ); + + InitializeObjectAttributes( &ObjectAttributes, + &uRdrName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL ); + + ntstatus = NtOpenFile( &handleRdr, + SYNCHRONIZE | FILE_LIST_DIRECTORY, + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_VALID_FLAGS, + FILE_SYNCHRONOUS_IO_NONALERT ); + + if ( !NT_SUCCESS(ntstatus) ) + goto CleanExit; + + dwRemoteNameLen = pszRemoteName? wcslen(pszRemoteName)*sizeof(WCHAR) : 0; + + RequestPacketSize = sizeof( NWR_REQUEST_PACKET ) + dwRemoteNameLen; + + RequestPacket = (PNWR_REQUEST_PACKET) LocalAlloc( LMEM_ZEROINIT, + RequestPacketSize ); + + if ( RequestPacket == NULL ) + { + ntstatus = STATUS_NO_MEMORY; + goto CleanExit; + } + + // + // Fill out the request packet for FSCTL_NWR_GET_CONN_STATUS. + // + + RequestPacket->Parameters.GetConnStatus.ResumeKey = *ResumeKey; + + RequestPacket->Version = REQUEST_PACKET_VERSION; + RequestPacket->Parameters.GetConnStatus.ConnectionNameLength = dwRemoteNameLen; + + RtlCopyMemory( &(RequestPacket->Parameters.GetConnStatus.ConnectionName[0]), + pszRemoteName, + dwRemoteNameLen ); + + ntstatus = NtFsControlFile( handleRdr, + NULL, + NULL, + NULL, + &IoStatusBlock, + FSCTL_NWR_GET_CONN_STATUS, + (PVOID) RequestPacket, + RequestPacketSize, + (PVOID) Buffer, + BufferSize ); + + if ( NT_SUCCESS( ntstatus )) + ntstatus = IoStatusBlock.Status; + + *EntriesRead = RequestPacket->Parameters.GetConnStatus.EntriesReturned; + *ResumeKey = RequestPacket->Parameters.GetConnStatus.ResumeKey; + *BytesNeeded = RequestPacket->Parameters.GetConnStatus.BytesNeeded; + +CleanExit: + + if ( handleRdr != NULL ) + NtClose( handleRdr ); + + if ( RequestPacket != NULL ) + LocalFree( RequestPacket ); + + return RtlNtStatusToDosError( ntstatus ); +} + + +DWORD +NwGetConnectionStatus( + IN LPWSTR pszRemoteName, + OUT PDWORD ResumeKey, + OUT LPBYTE *Buffer, + OUT PDWORD EntriesRead +) +{ + DWORD err = NO_ERROR; + DWORD dwBytesNeeded = 0; + DWORD dwBufferSize = TWO_KB; + + *Buffer = NULL; + *EntriesRead = 0; + + do { + + *Buffer = (LPBYTE) LocalAlloc( LMEM_ZEROINIT, dwBufferSize ); + + if ( *Buffer == NULL ) + return ERROR_NOT_ENOUGH_MEMORY; + + err = NWPGetConnectionStatus( pszRemoteName, + ResumeKey, + *Buffer, + dwBufferSize, + &dwBytesNeeded, + EntriesRead ); + + if ( err == ERROR_INSUFFICIENT_BUFFER ) + { + dwBufferSize = dwBytesNeeded + EXTRA_BYTES; + LocalFree( *Buffer ); + *Buffer = NULL; + } + + } while ( err == ERROR_INSUFFICIENT_BUFFER ); + + if ( err == ERROR_INVALID_PARAMETER ) // not attached + { + err = NO_ERROR; + *EntriesRead = 0; + } + + return err; +} + +DWORD +NwGetNdsVolumeInfo( + IN LPWSTR pszName, + OUT LPWSTR pszServerBuffer, + IN WORD wServerBufferSize, // in bytes + OUT LPWSTR pszVolumeBuffer, + IN WORD wVolumeBufferSize // in bytes +) +{ + NTSTATUS ntstatus = STATUS_SUCCESS; + HANDLE handleNdsTree; + + LPWSTR pszTree, pszVolume, pszTemp; + UNICODE_STRING uTree, uVolume; + + UNICODE_STRING uHostServer, uHostVolume; + WCHAR HostVolumeBuffer[256]; + + pszTree = pszName + 2; // get past two backslashes + + pszTemp = wcschr( pszTree, L'\\' ); + if ( pszTemp ) + *pszTemp = 0; + else + return ERROR_INVALID_PARAMETER; + + pszVolume = pszTemp + 1; + + RtlInitUnicodeString( &uTree, pszTree ); + RtlInitUnicodeString( &uVolume, pszVolume ); + + // + // Open up a handle to the tree. + // + + ntstatus = NwNdsOpenTreeHandle( &uTree, + &handleNdsTree ); + + if ( !NT_SUCCESS( ntstatus )) + goto CleanExit; + + // + // Set up the reply strings. + // + + uHostServer.Length = 0; + uHostServer.MaximumLength = wServerBufferSize; + uHostServer.Buffer = pszServerBuffer; + + RtlZeroMemory( pszServerBuffer, wServerBufferSize ); + + if ( pszVolumeBuffer != NULL ) + { + uHostVolume.Length = 0; + uHostVolume.MaximumLength = wVolumeBufferSize; + uHostVolume.Buffer = pszVolumeBuffer; + + RtlZeroMemory( pszVolumeBuffer, wVolumeBufferSize ); + } + else + { + uHostVolume.Length = 0; + uHostVolume.MaximumLength = sizeof( HostVolumeBuffer ); + uHostVolume.Buffer = HostVolumeBuffer; + } + + ntstatus = NwNdsGetVolumeInformation( handleNdsTree, + &uVolume, + &uHostServer, + &uHostVolume ); + + CloseHandle( handleNdsTree ); + +CleanExit: + + if ( pszTemp ) + *pszTemp = L'\\'; + + return RtlNtStatusToDosError( ntstatus ); +} + +DWORD +NwOpenAndGetTreeInfo( + LPWSTR pszNdsUNCPath, + HANDLE *phTreeConn, + DWORD *pdwOid +) +{ + NTSTATUS ntstatus = STATUS_SUCCESS; + WCHAR lpServerName[NW_MAX_SERVER_LEN]; + UNICODE_STRING ServerName; + + UNICODE_STRING ObjectName; + + *phTreeConn = NULL; + + ServerName.Length = 0; + ServerName.MaximumLength = sizeof( lpServerName ); + ServerName.Buffer = lpServerName; + + ObjectName.Buffer = NULL; + ObjectName.MaximumLength = ( wcslen( pszNdsUNCPath) + 1 ) * sizeof( WCHAR ); + + ObjectName.Length = NwParseNdsUncPath( (LPWSTR *) &ObjectName.Buffer, + pszNdsUNCPath, + PARSE_NDS_GET_TREE_NAME ); + + if ( ObjectName.Length == 0 || ObjectName.Buffer == NULL ) + { + return ERROR_PATH_NOT_FOUND; + } + + // + // Open a NDS tree connection handle to \\treename + // + ntstatus = NwNdsOpenTreeHandle( &ObjectName, phTreeConn ); + + if ( !NT_SUCCESS( ntstatus )) + { + return RtlNtStatusToDosError( ntstatus ); + } + + // + // Get the path to the container to open. + // + ObjectName.Length = NwParseNdsUncPath( (LPWSTR *) &ObjectName.Buffer, + pszNdsUNCPath, + 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. + // + ntstatus = NwNdsResolveName( *phTreeConn, + &Root, + pdwOid, + &ServerName, + NULL, + 0 ); + + } + else + { + // + // Resolve the path to get a NDS object id. + // + ntstatus = NwNdsResolveName( *phTreeConn, + &ObjectName, + pdwOid, + &ServerName, + NULL, + 0 ); + + } + + if ( ntstatus == STATUS_SUCCESS && ServerName.Length ) + { + DWORD dwHandleType; + + // + // NwNdsResolveName succeeded, but we were referred to + // another server, though pdwOid is still valid. + + if ( *phTreeConn ) + CloseHandle( *phTreeConn ); + + *phTreeConn = NULL; + + // + // Open a NDS generic connection handle to \\ServerName + // + ntstatus = NwNdsOpenGenericHandle( &ServerName, + &dwHandleType, + phTreeConn ); + + if ( ntstatus != STATUS_SUCCESS ) + { + return RtlNtStatusToDosError(ntstatus); + } + + ASSERT( dwHandleType != HANDLE_TYPE_NCP_SERVER ); + } + + if ( !NT_SUCCESS( ntstatus )) + { + + if ( *phTreeConn != NULL ) + { + CloseHandle( *phTreeConn ); + *phTreeConn = NULL; + } + return RtlNtStatusToDosError(ntstatus); + } + + return NO_ERROR; + +} + +DWORD +NwGetConnectedTrees( + IN LPWSTR pszNtUserName, + OUT LPBYTE Buffer, + IN DWORD BufferSize, + OUT LPDWORD lpEntriesRead, + OUT LPDWORD lpUserLUID +) +{ + NTSTATUS ntstatus = STATUS_SUCCESS; + HANDLE handleRdr = NULL; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + WCHAR RdrPrefix[] = L"\\Device\\NwRdr\\*"; + UNICODE_STRING uRdrName; + UNICODE_STRING uNtUserName; + + PNWR_NDS_REQUEST_PACKET Request = NULL; + BYTE RequestBuffer[2048]; + DWORD RequestSize = 0; + + *lpEntriesRead = 0; + + // + // Convert the user name to unicode. + // + + RtlInitUnicodeString( &uNtUserName, pszNtUserName ); + + // + // Set up the object attributes. + // + + RtlInitUnicodeString( &uRdrName, RdrPrefix ); + + InitializeObjectAttributes( &ObjectAttributes, + &uRdrName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL ); + + ntstatus = NtOpenFile( &handleRdr, + SYNCHRONIZE | FILE_LIST_DIRECTORY, + &ObjectAttributes, + &IoStatusBlock, + FILE_SHARE_VALID_FLAGS, + FILE_SYNCHRONOUS_IO_NONALERT ); + + if ( !NT_SUCCESS(ntstatus) ) + goto CleanExit; + + // + // Fill out the request packet for FSCTL_NWR_NDS_LIST_TREES; + // + + Request = ( PNWR_NDS_REQUEST_PACKET ) RequestBuffer; + + Request->Parameters.ListTrees.NtUserNameLength = uNtUserName.Length; + + RtlCopyMemory( &(Request->Parameters.ListTrees.NtUserName[0]), + uNtUserName.Buffer, + uNtUserName.Length ); + + RequestSize = sizeof( Request->Parameters.ListTrees ) + + uNtUserName.Length + + sizeof( DWORD ); + + ntstatus = NtFsControlFile( handleRdr, + NULL, + NULL, + NULL, + &IoStatusBlock, + FSCTL_NWR_NDS_LIST_TREES, + (PVOID) Request, + RequestSize, + (PVOID) Buffer, + BufferSize ); + + if ( NT_SUCCESS( ntstatus )) + { + ntstatus = IoStatusBlock.Status; + *lpEntriesRead = Request->Parameters.ListTrees.TreesReturned; + *lpUserLUID = Request->Parameters.ListTrees.UserLuid.LowPart; + } + +CleanExit: + + if ( handleRdr != NULL ) + NtClose( handleRdr ); + + return RtlNtStatusToDosError( ntstatus ); +} + + |