997 lines
21 KiB
C
997 lines
21 KiB
C
/*++
|
||
|
||
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';
|
||
lstrcpy( ConnectionName, DD_NULMRX_FS_DEVICE_NAME_U );
|
||
lstrcat( ConnectionName, L"\\;" );
|
||
lstrcat( ConnectionName, LocalName );
|
||
}
|
||
else
|
||
{
|
||
Status = WN_BAD_LOCALNAME;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Status = WN_BAD_LOCALNAME;
|
||
}
|
||
|
||
// format proper server name
|
||
if ( lpNetResource->lpRemoteName[0] == L'\\' && lpNetResource->lpRemoteName[1] == L'\\' )
|
||
{
|
||
lstrcat( ConnectionName, lpNetResource->lpRemoteName + 1 );
|
||
}
|
||
else
|
||
{
|
||
Status = WN_BAD_NETNAME;
|
||
}
|
||
|
||
DbgP(( L"Full Connect Name: %s\n", ConnectionName ));
|
||
DbgP(( L"Full Connect Name Length: %d\n", ( lstrlen( ConnectionName ) + 1 ) * sizeof( WCHAR ) ));
|
||
|
||
|
||
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 ( 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;
|
||
Status = SendToMiniRdr( IOCTL_NULMRX_GETCONN, LocalName, 3 * sizeof( WCHAR ),
|
||
(PVOID) RemoteName, &CopyBytes );
|
||
if ( Status == WN_SUCCESS && CopyBytes > 0 )
|
||
{
|
||
RemoteName[CopyBytes] = L'\0';
|
||
lstrcpy( ConnectionName, DD_NULMRX_FS_DEVICE_NAME_U );
|
||
lstrcat( ConnectionName, L"\\;" );
|
||
lstrcat( ConnectionName, LocalName );
|
||
lstrcat( ConnectionName, RemoteName );
|
||
CopyBytes = 0;
|
||
Status = SendToMiniRdr( IOCTL_NULMRX_DELCONN, ConnectionName,
|
||
( lstrlen( 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 ( lstrlen( lpLocalName ) > 1 )
|
||
{
|
||
if ( lpLocalName[1] == L':' )
|
||
{
|
||
CopyBytes = 128;
|
||
// 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 )
|
||
{
|
||
if ( CopyBytes > 0 )
|
||
{
|
||
len = CopyBytes + 1;
|
||
if ( *lpBufferSize > len )
|
||
{
|
||
*lpRemoteName++ = L'\\';
|
||
CopyMemory( lpRemoteName, RemoteName, CopyBytes );
|
||
*lpRemoteName++ = L'\0';
|
||
}
|
||
else
|
||
{
|
||
Status = WN_MORE_DATA;
|
||
*lpBufferSize = len;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Status = WN_NOT_CONNECTED;
|
||
}
|
||
}
|
||
|
||
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 );
|
||
|
||
if ( Status == WN_SUCCESS && CopyBytes > 0 )
|
||
{
|
||
for ( i = *((PULONG) hEnum); EntriesCopied < *lpcCount, i < 26; i++ )
|
||
{
|
||
if ( ConnectionList[i] )
|
||
{
|
||
CopyBytes = 128;
|
||
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;
|
||
lstrcpy( StringZone, NULMRX_PROVIDER_NAME_U );
|
||
|
||
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;
|
||
}
|
||
|
||
|
||
// Format and write debug information to OutputDebugString
|
||
ULONG
|
||
_cdecl
|
||
WideDbgPrint(
|
||
PWCHAR Format,
|
||
...
|
||
)
|
||
{
|
||
ULONG rc = 0;
|
||
WCHAR wszbuffer[255];
|
||
|
||
va_list marker;
|
||
va_start( marker, Format );
|
||
{
|
||
rc = wvsprintf( wszbuffer, Format, marker );
|
||
OutputDebugString( TRACE_TAG );
|
||
OutputDebugString( wszbuffer );
|
||
}
|
||
|
||
return rc;
|
||
}
|
||
|
||
|