Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1002 lines
24 KiB

/*++
Copyright (c) 1989-1999 Microsoft Corporation
Module Name:
ifsmrxnp.c
Abstract:
This module implements the routines required for interaction with network
provider router interface in NT
Notes:
This module has been built and tested only in UNICODE environment
--*/
#include <windows.h>
#include <windef.h>
#include <winbase.h>
#include <winsvc.h>
#include <winnetwk.h>
#include <npapi.h>
#include <devioctl.h>
#include "nulmrx.h"
#ifdef DBG
#define DbgP(_x_) WideDbgPrint _x_
#else
#define DbgP(_x_)
#endif
ULONG _cdecl WideDbgPrint( PWCHAR Format, ... );
#define TRACE_TAG L"NULMRXNP: "
#define WNNC_DRIVER( major, minor ) ( major * 0x00010000 + minor )
DWORD APIENTRY
NPGetCaps(
DWORD nIndex )
/*++
Routine Description:
This routine returns the capaboilities of the Null Mini redirector
network provider implementation
Arguments:
nIndex - category of capabilities desired
Return Value:
the appropriate capabilities
--*/
{
DWORD rc = 0;
DbgP(( L"GetNetCaps .....\n" ));
switch ( nIndex )
{
case WNNC_SPEC_VERSION:
rc = WNNC_SPEC_VERSION51;
break;
case WNNC_NET_TYPE:
rc = WNNC_NET_RDR2SAMPLE;
break;
case WNNC_DRIVER_VERSION:
rc = WNNC_DRIVER(1, 0);
break;
case WNNC_CONNECTION:
rc = WNNC_CON_GETCONNECTIONS |
WNNC_CON_CANCELCONNECTION |
WNNC_CON_ADDCONNECTION |
WNNC_CON_ADDCONNECTION3;
break;
case WNNC_ENUMERATION:
rc = WNNC_ENUM_LOCAL;
break;
case WNNC_START:
rc = 1;
break;
case WNNC_USER:
case WNNC_DIALOG:
case WNNC_ADMIN:
default:
rc = 0;
break;
}
return rc;
}
DWORD APIENTRY
NPLogonNotify(
PLUID lpLogonId,
LPCWSTR lpAuthentInfoType,
LPVOID lpAuthentInfo,
LPCWSTR lpPreviousAuthentInfoType,
LPVOID lpPreviousAuthentInfo,
LPWSTR lpStationName,
LPVOID StationHandle,
LPWSTR *lpLogonScript)
/*++
Routine Description:
This routine handles the logon notifications
Arguments:
lpLogonId -- the associated LUID
lpAuthenInfoType - the authentication information type
lpAuthenInfo - the authentication Information
lpPreviousAuthentInfoType - the previous aunthentication information type
lpPreviousAuthentInfo - the previous authentication information
lpStationName - the logon station name
LPVOID - logon station handle
lpLogonScript - the logon script to be executed.
Return Value:
WN_SUCCESS
Notes:
This capability has not been implemented in the sample.
--*/
{
*lpLogonScript = NULL;
return WN_SUCCESS;
}
DWORD APIENTRY
NPPasswordChangeNotify (
LPCWSTR lpAuthentInfoType,
LPVOID lpAuthentInfo,
LPCWSTR lpPreviousAuthentInfoType,
LPVOID lpPreviousAuthentInfo,
LPWSTR lpStationName,
LPVOID StationHandle,
DWORD dwChangeInfo )
/*++
Routine Description:
This routine handles the password change notifications
Arguments:
lpAuthenInfoType - the authentication information type
lpAuthenInfo - the authentication Information
lpPreviousAuthentInfoType - the previous aunthentication information type
lpPreviousAuthentInfo - the previous authentication information
lpStationName - the logon station name
LPVOID - logon station handle
dwChangeInfo - the password change information.
Return Value:
WN_NOT_SUPPORTED
Notes:
This capability has not been implemented in the sample.
--*/
{
SetLastError( WN_NOT_SUPPORTED );
return WN_NOT_SUPPORTED;
}
ULONG
SendToMiniRdr(
IN ULONG IoctlCode,
IN PVOID InputDataBuf,
IN ULONG InputDataLen,
IN PVOID OutputDataBuf,
IN PULONG pOutputDataLen)
/*++
Routine Description:
This routine sends a device ioctl to the Mini Rdr.
Arguments:
IoctlCode - Function code for the Mini Rdr driver
InputDataBuf - Input buffer pointer
InputDataLen - Lenth of the input buffer
OutputDataBuf - Output buffer pointer
pOutputDataLen - Pointer to the length of the output buffer
Return Value:
WN_SUCCESS if successful, otherwise the appropriate error
Notes:
--*/
{
HANDLE DeviceHandle; // The mini rdr device handle
ULONG BytesRet;
BOOL rc;
ULONG Status;
Status = WN_SUCCESS;
// Grab a handle to the redirector device object
DeviceHandle = CreateFile(
DD_NULMRX_USERMODE_DEV_NAME_U,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
(LPSECURITY_ATTRIBUTES)NULL,
OPEN_EXISTING,
0,
(HANDLE) NULL );
if ( INVALID_HANDLE_VALUE != DeviceHandle )
{
rc = DeviceIoControl(
DeviceHandle,
IoctlCode,
InputDataBuf,
InputDataLen,
OutputDataBuf,
*pOutputDataLen,
pOutputDataLen,
NULL );
if ( !rc )
{
DbgP(( L"SendToMiniRdr: returning error from DeviceIoctl\n" ));
Status = GetLastError( );
}
else
{
DbgP(( L"SendToMiniRdr: The DeviceIoctl call succeded\n" ));
}
CloseHandle(DeviceHandle);
}
else
{
Status = GetLastError( );
DbgP(( L"SendToMiniRdr: error %lx opening device \n", Status ));
}
return Status;
}
DWORD APIENTRY
NPAddConnection(
LPNETRESOURCE lpNetResource,
LPWSTR lpPassword,
LPWSTR lpUserName )
/*++
Routine Description:
This routine adds a connection to the list of connections associated
with this network provider
Arguments:
lpNetResource - the NETRESOURCE struct
lpPassword - the password
lpUserName - the user name
Return Value:
WN_SUCCESS if successful, otherwise the appropriate error
Notes:
--*/
{
DbgP(( L"NPAddConnection....\n" ));
return NPAddConnection3( NULL, lpNetResource, lpPassword, lpUserName, 0 );
}
DWORD APIENTRY
NPAddConnection3(
HWND hwndOwner,
LPNETRESOURCE lpNetResource,
LPWSTR lpPassword,
LPWSTR lpUserName,
DWORD dwFlags )
/*++
Routine Description:
This routine adds a connection to the list of connections associated
with this network provider
Arguments:
hwndOwner - the owner handle
lpNetResource - the NETRESOURCE struct
lpPassword - the password
lpUserName - the user name
dwFlags - flags for the connection
Return Value:
WN_SUCCESS if successful, otherwise the appropriate error
--*/
{
DWORD Status;
WCHAR ConnectionName[128];
WCHAR wszScratch[128];
WCHAR LocalName[3];
DWORD CopyBytes = 0;
DbgP(( L"NPAddConnection3....\n" ));
DbgP(( L"Local Name: %s\n", lpNetResource->lpLocalName ));
DbgP(( L"Remote Name: %s\n", lpNetResource->lpRemoteName ));
Status = WN_SUCCESS;
// \device\miniredirector\;<DriveLetter>:\Server\Share
if ( lstrlen( lpNetResource->lpLocalName ) > 1 )
{
if ( lpNetResource->lpLocalName[1] == L':' )
{
// LocalName[0] = (WCHAR) CharUpper( (PWCHAR) MAKELONG( (USHORT) lpNetResource->lpLocalName[0], 0 ) );
LocalName[0] = (WCHAR) toupper(lpNetResource->lpLocalName[0]);
LocalName[1] = L':';
LocalName[2] = L'\0';
lstrcpyn( ConnectionName, DD_NULMRX_FS_DEVICE_NAME_U, 126 );
wcsncat(ConnectionName, L"\\;", 3 );
wcsncat(ConnectionName, LocalName, 128-wcslen(ConnectionName));
}
else
{
Status = WN_BAD_LOCALNAME;
}
}
else
{
Status = WN_BAD_LOCALNAME;
}
if (Status == WN_SUCCESS)
{
if(lpNetResource->lpRemoteName[0] == L'\0')
{
Status = WN_BAD_NETNAME;
}
// format proper server name
else if ( lpNetResource->lpRemoteName[0] == L'\\' && lpNetResource->lpRemoteName[1] == L'\\' )
{
wcsncat( ConnectionName, lpNetResource->lpRemoteName + 1 , 128-wcslen(ConnectionName));
DbgP(( L"Full Connect Name: %s\n", ConnectionName ));
DbgP(( L"Full Connect Name Length: %d\n", ( wcslen( ConnectionName ) + 1 ) * sizeof( WCHAR ) ));
}
else
{
Status = WN_BAD_NETNAME;
}
}
if ( Status == WN_SUCCESS )
{
if ( QueryDosDevice( LocalName, wszScratch, 128 ) )
{
Status = WN_ALREADY_CONNECTED;
}
else if ( GetLastError( ) == ERROR_FILE_NOT_FOUND )
{
HANDLE hFile;
Status = SendToMiniRdr( IOCTL_NULMRX_ADDCONN, ConnectionName,
( lstrlen( ConnectionName ) + 1 ) * sizeof( WCHAR ),
NULL, &CopyBytes );
if ( Status == WN_SUCCESS )
{
if ( !DefineDosDevice( DDD_RAW_TARGET_PATH |
DDD_NO_BROADCAST_SYSTEM,
lpNetResource->lpLocalName,
ConnectionName ) )
{
Status = GetLastError( );
}
}
else
{
Status = WN_BAD_NETNAME;
}
}
else
{
Status = WN_ALREADY_CONNECTED;
}
}
return Status;
}
DWORD APIENTRY
NPCancelConnection(
LPWSTR lpName,
BOOL fForce )
/*++
Routine Description:
This routine cancels ( deletes ) a connection from the list of connections
associated with this network provider
Arguments:
lpName - name of the connection
fForce - forcefully delete the connection
Return Value:
WN_SUCCESS if successful, otherwise the appropriate error
Notes:
--*/
{
WCHAR LocalName[3];
WCHAR RemoteName[128];
WCHAR ConnectionName[128];
ULONG CopyBytes;
DWORD DisconnectResult;
DWORD Status = WN_NOT_CONNECTED;
if(lpName == NULL)
return Status;
if ( lstrlen( lpName ) > 1 )
{
if ( lpName[1] == L':' )
{
// LocalName[0] = (WCHAR) CharUpper( (PWCHAR) MAKELONG( (USHORT) lpName[0], 0 ) );
LocalName[0] = (WCHAR) toupper(lpName[0]);
LocalName[1] = L':';
LocalName[2] = L'\0';
CopyBytes = 128 * sizeof(WCHAR);
Status = SendToMiniRdr( IOCTL_NULMRX_GETCONN, LocalName, 3 * sizeof( WCHAR ),
(PVOID) RemoteName, &CopyBytes );
if ( Status == WN_SUCCESS && CopyBytes > 0 && CopyBytes < 128 * sizeof(WCHAR) )
{
RemoteName[CopyBytes/sizeof(WCHAR)] = L'\0';
lstrcpyn( ConnectionName, DD_NULMRX_FS_DEVICE_NAME_U, 126 );
wcsncat( ConnectionName, L"\\;", 3);
wcsncat( ConnectionName, LocalName, 128-wcslen(ConnectionName) );
wcsncat( ConnectionName, RemoteName, 128-wcslen(ConnectionName) );
ConnectionName[127] = L'\0';
CopyBytes = 0;
Status = SendToMiniRdr( IOCTL_NULMRX_DELCONN, ConnectionName,
( wcslen( ConnectionName ) + 1 ) * sizeof( WCHAR ),
NULL, &CopyBytes );
if ( Status == WN_SUCCESS )
{
if ( !DefineDosDevice( DDD_REMOVE_DEFINITION | DDD_RAW_TARGET_PATH | DDD_EXACT_MATCH_ON_REMOVE,
LocalName,
ConnectionName ) )
{
Status = GetLastError( );
}
}
}
else
{
Status = WN_NOT_CONNECTED;
}
}
}
return Status;
}
DWORD APIENTRY
NPGetConnection(
LPWSTR lpLocalName,
LPWSTR lpRemoteName,
LPDWORD lpBufferSize )
/*++
Routine Description:
This routine returns the information associated with a connection
Arguments:
lpLocalName - local name associated with the connection
lpRemoteName - the remote name associated with the connection
lpBufferSize - the remote name buffer size
Return Value:
WN_SUCCESS if successful, otherwise the appropriate error
Notes:
--*/
{
DWORD Status, len, i;
ULONG CopyBytes;
WCHAR RemoteName[128];
WCHAR LocalName[3];
Status = WN_NOT_CONNECTED;
DbgP(( L"NPGetConnection....\n" ));
if(lpLocalName == NULL)
return Status;
if ( wcslen( lpLocalName ) > 1 )
{
if ( lpLocalName[1] == L':' )
{
CopyBytes = 128*sizeof(WCHAR);
// LocalName[0] = (WCHAR) CharUpper( (PWCHAR) MAKELONG( (USHORT) lpLocalName[0], 0 ) );
LocalName[0] = (WCHAR) toupper(lpLocalName[0]);
LocalName[1] = L':';
LocalName[2] = L'\0';
Status = SendToMiniRdr( IOCTL_NULMRX_GETCONN, LocalName, 3 * sizeof( WCHAR ),
(PVOID) RemoteName, &CopyBytes );
}
}
if ( Status == WN_SUCCESS )
{
len = CopyBytes + sizeof(WCHAR);
if ( *lpBufferSize > len )
{
*lpRemoteName++ = L'\\';
CopyMemory( lpRemoteName, RemoteName, CopyBytes );
lpRemoteName[CopyBytes/sizeof(WCHAR)] = L'\0';
}
else
{
Status = WN_MORE_DATA;
*lpBufferSize = len;
}
}
return Status;
}
DWORD APIENTRY
NPOpenEnum(
DWORD dwScope,
DWORD dwType,
DWORD dwUsage,
LPNETRESOURCE lpNetResource,
LPHANDLE lphEnum )
/*++
Routine Description:
This routine opens a handle for enumeration of resources. The only capability
implemented in the sample is for enumerating connected shares
Arguments:
dwScope - the scope of enumeration
dwType - the type of resources to be enumerated
dwUsage - the usage parameter
lpNetResource - a pointer to the desired NETRESOURCE struct.
lphEnum - aptr. for passing nack the enumeration handle
Return Value:
WN_SUCCESS if successful, otherwise the appropriate error
Notes:
The sample only supports the notion of enumerating connected shares
The handle passed back is merely the index of the last entry returned
--*/
{
DWORD Status;
DbgP((L"NPOpenEnum\n"));
*lphEnum = NULL;
switch ( dwScope )
{
case RESOURCE_CONNECTED:
{
*lphEnum = HeapAlloc( GetProcessHeap( ), HEAP_ZERO_MEMORY, sizeof( ULONG ) );
if (*lphEnum )
{
Status = WN_SUCCESS;
}
else
{
Status = WN_OUT_OF_MEMORY;
}
break;
}
break;
case RESOURCE_CONTEXT:
default:
Status = WN_NOT_SUPPORTED;
break;
}
DbgP((L"NPOpenEnum returning Status %lx\n",Status));
return(Status);
}
DWORD APIENTRY
NPEnumResource(
HANDLE hEnum,
LPDWORD lpcCount,
LPVOID lpBuffer,
LPDWORD lpBufferSize)
/*++
Routine Description:
This routine uses the handle obtained by a call to NPOpenEnum for
enuerating the connected shares
Arguments:
hEnum - the enumeration handle
lpcCount - the number of resources returned
lpBuffer - the buffere for passing back the entries
lpBufferSize - the size of the buffer
Return Value:
WN_SUCCESS if successful, otherwise the appropriate error
WN_NO_MORE_ENTRIES - if the enumeration has exhausted the entries
WN_MORE_DATA - if nmore data is available
Notes:
The sample only supports the notion of enumerating connected shares
The handle passed back is merely the index of the last entry returned
--*/
{
DWORD Status = WN_SUCCESS;
BYTE ConnectionList[26];
ULONG CopyBytes;
ULONG EntriesCopied;
ULONG i;
LPNETRESOURCE pNetResource;
ULONG SpaceNeeded;
ULONG SpaceAvailable;
WCHAR LocalName[3];
WCHAR RemoteName[128];
PWCHAR StringZone;
DbgP((L"NPEnumResource\n"));
DbgP((L"NPEnumResource Count Requested %d\n", *lpcCount));
pNetResource = (LPNETRESOURCE) lpBuffer;
SpaceAvailable = *lpBufferSize;
EntriesCopied = 0;
StringZone = (PWCHAR) ((PBYTE)lpBuffer + *lpBufferSize);
CopyBytes = 26;
Status = SendToMiniRdr( IOCTL_NULMRX_GETLIST, NULL, 0,
(PVOID) ConnectionList, &CopyBytes );
i = *((PULONG)hEnum);
if ( Status == WN_SUCCESS)
{
for ( i = *((PULONG) hEnum); EntriesCopied < *lpcCount && i < 26; i++ )
{
if ( ConnectionList[i] )
{
CopyBytes = 128*sizeof(WCHAR);
LocalName[0] = L'A' + (WCHAR) i;
LocalName[1] = L':';
LocalName[2] = L'\0';
Status = SendToMiniRdr( IOCTL_NULMRX_GETCONN, LocalName, 3 * sizeof(WCHAR),
(PVOID) RemoteName, &CopyBytes );
// if something strange happended then just say there are no more entries
if ( Status != WN_SUCCESS || CopyBytes == 0 )
{
Status = WN_NO_MORE_ENTRIES;
break;
}
// Determine the space needed for this entry...
SpaceNeeded = sizeof( NETRESOURCE ); // resource struct
SpaceNeeded += 3 * sizeof(WCHAR); // local name
SpaceNeeded += 2 * sizeof(WCHAR) + CopyBytes; // remote name
SpaceNeeded += 5 * sizeof(WCHAR); // comment
SpaceNeeded += sizeof(NULMRX_PROVIDER_NAME_U); // provider name
if ( SpaceNeeded > SpaceAvailable )
{
break;
}
else
{
SpaceAvailable -= SpaceNeeded;
pNetResource->dwScope = RESOURCE_CONNECTED;
pNetResource->dwType = RESOURCETYPE_DISK;
pNetResource->dwDisplayType = RESOURCEDISPLAYTYPE_SHARE;
pNetResource->dwUsage = 0;
// setup string area at opposite end of buffer
SpaceNeeded -= sizeof( NETRESOURCE );
StringZone = (PWCHAR)( (PBYTE) StringZone - SpaceNeeded );
// copy local name
pNetResource->lpLocalName = StringZone;
*StringZone++ = L'A' + (WCHAR) i;
*StringZone++ = L':';
*StringZone++ = L'\0';
// copy remote name
pNetResource->lpRemoteName = StringZone;
*StringZone++ = L'\\';
CopyMemory( StringZone, RemoteName, CopyBytes );
StringZone += CopyBytes / sizeof(WCHAR);
*StringZone++ = L'\0';
// copy comment
pNetResource->lpComment = StringZone;
*StringZone++ = L'A';
*StringZone++ = L'_';
*StringZone++ = L'O';
*StringZone++ = L'K';
*StringZone++ = L'\0';
// copy provider name
pNetResource->lpProvider = StringZone;
lstrcpyn( StringZone, NULMRX_PROVIDER_NAME_U, sizeof(NULMRX_PROVIDER_NAME_U)/sizeof(WCHAR) );
EntriesCopied++;
// set new bottom of string zone
StringZone = (PWCHAR)( (PBYTE) StringZone - SpaceNeeded );
}
pNetResource++;
}
}
}
else
{
Status = WN_NO_MORE_ENTRIES;
}
*lpcCount = EntriesCopied;
if ( EntriesCopied == 0 && Status == WN_SUCCESS )
{
if ( i > 25 )
{
Status = WN_NO_MORE_ENTRIES;
}
else
{
DbgP((L"NPEnumResource More Data Needed - %d\n", SpaceNeeded));
Status = WN_MORE_DATA;
*lpBufferSize = SpaceNeeded;
}
}
// update entry index
*(PULONG) hEnum = i;
DbgP((L"NPEnumResource Entries returned - %d\n", EntriesCopied));
return Status;
}
DWORD APIENTRY
NPCloseEnum(
HANDLE hEnum )
/*++
Routine Description:
This routine closes the handle for enumeration of resources.
Arguments:
hEnum - the enumeration handle
Return Value:
WN_SUCCESS if successful, otherwise the appropriate error
Notes:
The sample only supports the notion of enumerating connected shares
--*/
{
DbgP((L"NPCloseEnum\n"));
HeapFree( GetProcessHeap( ), 0, (PVOID) hEnum );
return WN_SUCCESS;
}
DWORD APIENTRY
NPGetResourceParent(
LPNETRESOURCE lpNetResource,
LPVOID lpBuffer,
LPDWORD lpBufferSize )
/*++
Routine Description:
This routine returns the information about net resource parent
Arguments:
lpNetResource - the NETRESOURCE struct
lpBuffer - the buffer for passing back the parent information
lpBufferSize - the buffer size
Return Value:
Notes:
--*/
{
DbgP(( L"NPGetResourceParent: WN_NOT_SUPPORTED\n" ));
return WN_NOT_SUPPORTED;
}
DWORD APIENTRY
NPGetResourceInformation(
LPNETRESOURCE lpNetResource,
LPVOID lpBuffer,
LPDWORD lpBufferSize,
LPWSTR *lplpSystem )
/*++
Routine Description:
This routine returns the information associated net resource
Arguments:
lpNetResource - the NETRESOURCE struct
lpBuffer - the buffer for passing back the parent information
lpBufferSize - the buffer size
lplpSystem -
Return Value:
Notes:
--*/
{
DbgP(( L"NPGetResourceInformation: WN_NOT_SUPPORTED\n" ));
return WN_NOT_SUPPORTED;
}
DWORD APIENTRY
NPGetUniversalName(
LPCWSTR lpLocalPath,
DWORD dwInfoLevel,
LPVOID lpBuffer,
LPDWORD lpBufferSize )
/*++
Routine Description:
This routine returns the information associated net resource
Arguments:
lpLocalPath - the local path name
dwInfoLevel - the desired info level
lpBuffer - the buffer for the univeral name
lpBufferSize - the buffer size
Return Value:
WN_SUCCESS if successful
Notes:
--*/
{
DbgP(( L"NPGetUniversalName: WN_NOT_SUPPORTED\n" ));
return WN_NOT_SUPPORTED;
}
int _cdecl _vsnwprintf( wchar_t *buffer, size_t count, wchar_t *format, va_list arg_ptr);
// Format and write debug information to OutputDebugString
ULONG _cdecl WideDbgPrint( LPTSTR Format, ... )
{
ULONG rc = 0;
TCHAR szbuffer[256];
va_list marker;
va_start( marker, Format );
{
rc = _vsnwprintf( szbuffer, 254, Format, marker );
szbuffer[255] = (TCHAR)0;
OutputDebugString( TRACE_TAG );
OutputDebugString( szbuffer );
}
return rc;
}