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
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;
|
|
}
|
|
|