2025-04-27 07:49:33 -04:00

1437 lines
39 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1989-1996 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 builkt and tested only in UNICODE environment
--*/
// Include files from the NT public directories
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windef.h>
#include <winbase.h>
#include <winsvc.h>
#include <winnetwk.h>
#include <npapi.h>
// include files from the IFS inc directory
#include <ifsmrx.h>
#include <ifsmrxnp.h>
// The debug level for this module
DWORD IfsMRxNpDebugLevel = 7;
// the IFS mini redirector and provider name. The original constants
// are defined in ifsmrx.h
UNICODE_STRING IfsMRxDeviceName = {
DD_IFSMRX_FS_DEVICE_NAME_U_LENGTH,
DD_IFSMRX_FS_DEVICE_NAME_U_LENGTH,
DD_IFSMRX_FS_DEVICE_NAME_U
};
UNICODE_STRING IfsMrxProviderName = {
IFSMRX_PROVIDER_NAME_U_LENGTH,
IFSMRX_PROVIDER_NAME_U_LENGTH,
IFSMRX_PROVIDER_NAME_U
};
DWORD
OpenSharedMemory(
PHANDLE phMutex,
PHANDLE phMemory,
PVOID *pMemory
)
/*++
Routine Description:
This routine opens the shared memory for exclusive manipulation
Arguments:
phMutex - the mutex handle
phMemory - the memory handle
pMemory - a ptr. to the shared memory which is set if successful
Return Value:
WN_SUCCESS -- if successful
--*/
{
DWORD dwStatus;
TRACE_CALL(("OpenSharedMemory\n"));
*phMutex = 0;
*phMemory = 0;
*pMemory = NULL;
*phMutex = OpenMutex(
SYNCHRONIZE,
FALSE,
IFSMRXNP_MUTEX_NAME);
if (*phMutex == NULL) {
dwStatus = GetLastError();
TRACE_ERROR(("OpenSharedMemory: CreateMutex failed\n"));
goto OpenSharedMemoryAbort1;
}
TRACE_INFO(("OpenSharedMemory: Calling WaitForSingleObject\n"));
WaitForSingleObject(*phMutex, INFINITE);
*phMemory = OpenFileMapping(
FILE_MAP_WRITE,
FALSE,
IFSMRXNP_SHARED_MEMORY_NAME);
if (*phMemory == NULL) {
dwStatus = GetLastError();
TRACE_ERROR(("OpenSharedMemory: OpenFileMapping failed\n"));
goto OpenSharedMemoryAbort2;
}
*pMemory = MapViewOfFile(*phMemory, FILE_MAP_WRITE, 0, 0, 0);
if (*pMemory == NULL) {
dwStatus = GetLastError();
TRACE_ERROR(("OpenSharedMemory: MapViewOfFile failed\n"));
goto OpenSharedMemoryAbort3;
}
TRACE_CALL(("OpenSharedMemory: return ERROR_SUCCESS\n"));
return(ERROR_SUCCESS);
OpenSharedMemoryAbort3:
CloseHandle(*phMemory);
OpenSharedMemoryAbort2:
ReleaseMutex(*phMutex);
CloseHandle(*phMutex);
*phMutex = NULL;
OpenSharedMemoryAbort1:
TRACE_ERROR(("OpenSharedMemory: return dwStatus: %d\n", dwStatus));
return(dwStatus);
}
VOID
CloseSharedMemory(
PHANDLE hMutex,
PHANDLE hMemory,
PVOID *pMemory )
/*++
Routine Description:
This routine relinquishes control of the shared memory after exclusive
manipulation
Arguments:
hMutex - the mutex handle
hMemory - the memory handle
pMemory - a ptr. to the shared memory which is set if successful
Return Value:
--*/
{
TRACE_CALL(("CloseSharedMemory\n"));
if (*pMemory) {
UnmapViewOfFile(*pMemory);
*pMemory = NULL;
}
if (*hMemory) {
CloseHandle(*hMemory);
*hMemory = 0;
}
if (*hMutex) {
if (ReleaseMutex(*hMutex) == FALSE) {
TRACE_ERROR(("CloseSharedMemory: ReleaseMutex error: %d\n", GetLastError()));
}
CloseHandle(*hMutex);
*hMutex = 0;
}
TRACE_CALL(("CloseSharedMemory: Return\n"));
}
DWORD APIENTRY
NPGetCaps(
DWORD nIndex )
/*++
Routine Description:
This routine returns the capaboilities of the IFS Mini redirector
network provider implementation
Arguments:
nIndex - category of capabilities desired
Return Value:
the appropriate capabilities
--*/
{
switch (nIndex) {
case WNNC_SPEC_VERSION:
return(WNNC_SPEC_VERSION51);
case WNNC_NET_TYPE:
return(0x00170000);
case WNNC_DRIVER_VERSION:
#define WNNC_DRIVER(major,minor) (major*0x00010000 + minor)
return(WNNC_DRIVER(1, 0));
case WNNC_USER:
return(0);
case WNNC_CONNECTION:
return(WNNC_CON_GETCONNECTIONS |
WNNC_CON_CANCELCONNECTION |
WNNC_CON_ADDCONNECTION |
WNNC_CON_ADDCONNECTION3);
case WNNC_DIALOG:
return(0);
case WNNC_ADMIN:
return(0);
case WNNC_ENUMERATION:
return(WNNC_ENUM_LOCAL);
case WNNC_START:
return(1);
default:
return(0);
}
}
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);
}
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 = 0;
TRACE_CALL(("NPOpenEnum\n"));
*lphEnum = NULL;
switch (dwScope) {
case RESOURCE_CONNECTED:
{
*lphEnum = LocalAlloc(
LMEM_ZEROINIT,
sizeof(IFSMRXNP_ENUMERATION_HANDLE));
if (*lphEnum != NULL) {
Status = WN_SUCCESS;
} else {
Status = WN_OUT_OF_MEMORY;
}
break;
}
break;
case RESOURCE_CONTEXT:
default:
Status = WN_NOT_SUPPORTED;
break;
}
TRACE_ERROR(("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;
PIFSMRXNP_ENUMERATION_HANDLE pEnumHandle;
LPNETRESOURCEW pBufferResource;
DWORD StringOffset;
DWORD AvailableBufferSize;
HANDLE hMutex, hMemory;
PIFSMRXNP_SHARED_MEMORY pSharedMemory;
TRACE_CALL(("NPEnumResource\n"));
TRACE_INFO(("NPEnumResource Count Requested %d\n",*lpcCount));
AvailableBufferSize = *lpBufferSize;
StringOffset = *lpBufferSize;
pBufferResource = (LPNETRESOURCEW)lpBuffer;
pEnumHandle = (PIFSMRXNP_ENUMERATION_HANDLE)hEnum;
*lpcCount = 0;
if (pEnumHandle->LastIndex >= IFSMRXNP_MAX_DEVICES) {
return(WN_NO_MORE_ENTRIES);
}
Status = OpenSharedMemory(
&hMutex,
&hMemory,
(PVOID)&pSharedMemory);
if (Status == WN_SUCCESS) {
INT Index;
PIFSMRXNP_NETRESOURCE pNetResource;
TRACE_INFO(("NPEnumResource: Highest Index %d Number Of resources %d\n",
pSharedMemory->HighestIndexInUse,pSharedMemory->NumberOfResourcesInUse));
for (Index = pEnumHandle->LastIndex; Index <= pSharedMemory->HighestIndexInUse; Index++) {
pNetResource = &pSharedMemory->NetResources[Index];
TRACE_INFO(("NPEnumResource: Examining Index %d\n",Index));
if (pNetResource->InUse) {
DWORD ResourceSize;
ResourceSize = sizeof(NETRESOURCE) +
pNetResource->LocalNameLength + sizeof(WCHAR) +
pNetResource->RemoteNameLength + sizeof(WCHAR) +
IfsMrxProviderName.Length + sizeof(WCHAR);
if (AvailableBufferSize >= ResourceSize) {
*lpcCount = *lpcCount + 1;
AvailableBufferSize -= ResourceSize;
pBufferResource->dwScope = RESOURCE_CONNECTED;
pBufferResource->dwType = pNetResource->dwType;
pBufferResource->dwDisplayType = pNetResource->dwDisplayType;
pBufferResource->dwUsage = pNetResource->dwUsage;
TRACE_INFO(("NPEnumResource: Copying local name Index %d\n",Index));
// set up the strings in the resource
StringOffset -= (pNetResource->LocalNameLength + sizeof(WCHAR));
pBufferResource->lpLocalName = (PWCHAR)((PBYTE)lpBuffer + StringOffset);
RtlCopyMemory(
pBufferResource->lpLocalName,
pNetResource->LocalName,
pNetResource->LocalNameLength);
pBufferResource->lpLocalName[
pNetResource->LocalNameLength/sizeof(WCHAR)] = L'\0';
TRACE_INFO(("NPEnumResource: Copying remote name Index %d\n",Index));
StringOffset -= (pNetResource->RemoteNameLength + sizeof(WCHAR));
pBufferResource->lpRemoteName = (PWCHAR)((PBYTE)lpBuffer + StringOffset);
RtlCopyMemory(
pBufferResource->lpRemoteName,
pNetResource->RemoteName,
pNetResource->RemoteNameLength);
pBufferResource->lpRemoteName[
pNetResource->RemoteNameLength/sizeof(WCHAR)] = L'\0';
TRACE_INFO(("NPEnumResource: Copying provider name Index %d\n",Index));
StringOffset -= (IfsMrxProviderName.Length + sizeof(WCHAR));
pBufferResource->lpProvider = (PWCHAR)((PBYTE)lpBuffer + StringOffset);
RtlCopyMemory(
pBufferResource->lpProvider,
IfsMrxProviderName.Buffer,
IfsMrxProviderName.Length);
pBufferResource->lpProvider[
IfsMrxProviderName.Length/sizeof(WCHAR)] = L'\0';
pBufferResource->lpComment = NULL;
pBufferResource++;
} else {
TRACE_INFO(("NPEnumResource: Buffer Overflow Index %d\n",Index));
Status = WN_MORE_DATA;
break;
}
}
}
pEnumHandle->LastIndex = Index;
if ((Status == WN_SUCCESS) &&
(pEnumHandle->LastIndex > pSharedMemory->HighestIndexInUse) &&
(*lpcCount == 0)) {
Status = WN_NO_MORE_ENTRIES;
}
CloseSharedMemory(
&hMutex,
&hMemory,
(PVOID)&pSharedMemory);
}
TRACE_INFO(("NPEnumResource returning Count %d\n",*lpcCount));
TRACE_CALL(("NPEnumResource returning Status %lx\n",Status));
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
--*/
{
TRACE_CALL(("NPCloseEnum\n"));
LocalFree(hEnum);
return(WN_SUCCESS);
}
DWORD
OpenConnection(
PUNICODE_STRING pConnectionName,
DWORD Disposition,
PFILE_FULL_EA_INFORMATION pEABuffer,
DWORD EABufferLength,
PHANDLE pConnectionHandle )
/*++
Routine Description:
This routine opens the connection. This routine is shared by NpAddConnection
and NPCancelConnection
Arguments:
pConnectionName - the connection name
Disposition - the Open disposition
pEABuffer - the EA buffer associated with the open
EABufferLength - the EA buffer length
pConnectionHandle - the placeholder for the connection handle
Return Value:
WN_SUCCESS if successful, otherwise the appropriate error
Notes:
--*/
{
NTSTATUS Status;
IO_STATUS_BLOCK IoStatusBlock;
OBJECT_ATTRIBUTES ConnectionObjectAttributes;
TRACE_CALL(("OpenConnection: ConnectionName: %S\n", pConnectionName->Buffer));
InitializeObjectAttributes(
&ConnectionObjectAttributes,
pConnectionName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
Status = NtCreateFile(
pConnectionHandle,
SYNCHRONIZE,
&ConnectionObjectAttributes,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
Disposition,
(FILE_CREATE_TREE_CONNECTION | FILE_SYNCHRONOUS_IO_NONALERT),
pEABuffer,
EABufferLength);
if (Status != STATUS_SUCCESS) {
TRACE_ERROR(("OpenConnection: NtCreateFile Failed: NTStatus: %08x\n", Status));
return(WN_BAD_NETNAME);
}
TRACE_CALL(("OpenConnection: return SUCCESS\n"));
return(WN_SUCCESS);
}
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:
--*/
{
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
Notes:
The current sample does not handle explicitly passesd in credentials. Normally
the credential information is passed in as EA parameters to the associated
mini redirector for further manipulation
--*/
{
DWORD Status = 0;
UNICODE_STRING ConnectionName;
OBJECT_ATTRIBUTES ConnectionAttributes;
HANDLE ConnectionHandle = INVALID_HANDLE_VALUE;
IO_STATUS_BLOCK IoStatusBlock;
PWCHAR pLocalName,pRemoteName;
USHORT LocalNameLength,RemoteNameLength;
// The IFS mini supports only DISK type resources. The other resources
// are not supported.
if ((lpNetResource->lpRemoteName == NULL) ||
(lpNetResource->lpRemoteName[0] != L'\\') ||
(lpNetResource->lpRemoteName[1] != L'\\') ||
(lpNetResource->dwType != RESOURCETYPE_DISK)) {
return WN_BAD_NETNAME;
}
//
// The remote name is in the UNC format \\Server\Share. This name
// needs to be translated to an appropriate NT name in order to
// issue the request to the underlying mini redirector to create the
// connection.
//
// The NT style name is of the form
//
// \device\ifsminiredirector\;<DriveLetter>:\Server\Share
//
// The additional ; is required by the new RDR for extensibility.
//
pLocalName = lpNetResource->lpLocalName;
pRemoteName = lpNetResource->lpRemoteName;
// skip past the first back slash since the name to be appended for the
// NT name does not require this.
pRemoteName++;
if (pLocalName != NULL) {
LocalNameLength = wcslen(pLocalName) * sizeof(WCHAR);
} else {
LocalNameLength = 0;
}
RemoteNameLength = (wcslen(pRemoteName) - 1) * sizeof(WCHAR);
ConnectionName.MaximumLength = (USHORT)(IfsMRxDeviceName.Length +
(USHORT)RemoteNameLength +
((pLocalName != NULL)
? (LocalNameLength + sizeof(WCHAR)) //+1 for ';'
: 0) +
sizeof(WCHAR));
ConnectionName.Length = ConnectionName.MaximumLength;
ConnectionName.Buffer = LocalAlloc(
LMEM_ZEROINIT,
ConnectionName.Length);
if (ConnectionName.Buffer == NULL) {
return GetLastError();
}
// Copy the name into the buffer
RtlCopyMemory(
ConnectionName.Buffer,
IfsMRxDeviceName.Buffer,
IfsMRxDeviceName.Length);
wcscat(ConnectionName.Buffer, L"\\");
wcscat(ConnectionName.Buffer, L";");
if (pLocalName != NULL) {
wcscat(ConnectionName.Buffer, pLocalName);
}
wcscat(ConnectionName.Buffer, pRemoteName);
Status = OpenConnection(
&ConnectionName,
FILE_OPEN_IF,
NULL,
0,
&ConnectionHandle);
if ((Status == WN_SUCCESS) &&
(pLocalName != NULL)) {
WCHAR TempBuf[64];
if (!QueryDosDeviceW(
pLocalName,
TempBuf,
64)) {
if (GetLastError() != ERROR_FILE_NOT_FOUND) {
//
// Most likely failure occurred because our output
// buffer is too small. It still means someone already
// has an existing symbolic link for this device.
//
Status = ERROR_ALREADY_ASSIGNED;
} else {
//
// ERROR_FILE_NOT_FOUND (translated from OBJECT_NAME_NOT_FOUND)
// means it does not exist and we can redirect this device.
//
// Create a symbolic link object to the device we are redirecting
//
if (!DefineDosDeviceW(
DDD_RAW_TARGET_PATH |
DDD_NO_BROADCAST_SYSTEM,
pLocalName,
ConnectionName.Buffer)) {
Status = GetLastError();
} else {
Status = WN_SUCCESS;
}
}
} else {
//
// QueryDosDevice successfully an existing symbolic link--
// somebody is already using this device.
//
Status = ERROR_ALREADY_ASSIGNED;
}
} else {
TRACE_ERROR(("OpenConnection returned %lx\n",Status));
Status = RtlNtStatusToDosError(Status);
}
if (Status == WN_SUCCESS) {
INT Index;
HANDLE hMutex, hMemory;
BOOLEAN FreeEntryFound = FALSE;
PIFSMRXNP_SHARED_MEMORY pSharedMemory;
// The connection was established and the local device mapping
// added. Include this in the list of mapped devices.
Status = OpenSharedMemory(
&hMutex,
&hMemory,
(PVOID)&pSharedMemory);
if (Status == WN_SUCCESS) {
TRACE_INFO(("NPAddConnection3: Highest Index %d Number Of resources %d\n",
pSharedMemory->HighestIndexInUse,pSharedMemory->NumberOfResourcesInUse));
Index = 0;
while (Index < pSharedMemory->HighestIndexInUse) {
if (!pSharedMemory->NetResources[Index].InUse) {
FreeEntryFound = TRUE;
break;
}
Index++;
}
if (!FreeEntryFound &&
(pSharedMemory->HighestIndexInUse < IFSMRXNP_MAX_DEVICES)) {
pSharedMemory->HighestIndexInUse += 1;
Index = pSharedMemory->HighestIndexInUse;
FreeEntryFound = TRUE;
}
if (FreeEntryFound) {
PIFSMRXNP_NETRESOURCE pIfsMrxNetResource;
pSharedMemory->NumberOfResourcesInUse += 1;
pIfsMrxNetResource = &pSharedMemory->NetResources[Index];
pIfsMrxNetResource->InUse = TRUE;
pIfsMrxNetResource->dwScope = lpNetResource->dwScope;
pIfsMrxNetResource->dwType = lpNetResource->dwType;
pIfsMrxNetResource->dwDisplayType = lpNetResource->dwDisplayType;
pIfsMrxNetResource->dwUsage = RESOURCEUSAGE_CONNECTABLE;
pIfsMrxNetResource->LocalNameLength = LocalNameLength;
pIfsMrxNetResource->RemoteNameLength = wcslen(lpNetResource->lpRemoteName) * sizeof(WCHAR);
pIfsMrxNetResource->ConnectionNameLength = ConnectionName.Length;
// Copy the local name
RtlCopyMemory(
pIfsMrxNetResource->LocalName,
lpNetResource->lpLocalName,
pIfsMrxNetResource->LocalNameLength);
// Copy the remote name
RtlCopyMemory(
pIfsMrxNetResource->RemoteName,
lpNetResource->lpRemoteName,
pIfsMrxNetResource->RemoteNameLength);
// Copy the connection name
RtlCopyMemory(
pIfsMrxNetResource->ConnectionName,
ConnectionName.Buffer,
pIfsMrxNetResource->ConnectionNameLength);
} else {
Status = WN_NO_MORE_DEVICES;
}
CloseSharedMemory(
&hMutex,
&hMemory,
(PVOID)&pSharedMemory);
} else {
TRACE_ERROR(("NpAddConnection3: OpenSharedMemory returned %lx\n",Status));
}
}
if (ConnectionHandle != INVALID_HANDLE_VALUE) {
NtClose(ConnectionHandle);
}
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:
--*/
{
BOOL bLocalName = TRUE;
DWORD Status = 0;
UNICODE_STRING Name;
HANDLE hMutex, hMemory;
PIFSMRXNP_SHARED_MEMORY pSharedMemory;
if (*lpName == L'\\' && *(lpName + 1) == L'\\') {
bLocalName = FALSE;
}
TRACE_CALL(("NPCancelConnection\n"));
TRACE_INFO(("NPCancelConnection: ConnectionName: %S\n", lpName));
Name.MaximumLength = Name.Length = wcslen(lpName) * sizeof(WCHAR);
Name.Buffer = lpName;
Status = OpenSharedMemory(
&hMutex,
&hMemory,
(PVOID)&pSharedMemory);
if (Status == WN_SUCCESS) {
INT Index;
BOOL EntryFound = FALSE;
PIFSMRXNP_NETRESOURCE pNetResource;
TRACE_INFO(("NPCancelConnection: Highest Index %d Number Of resources %d\n",
pSharedMemory->HighestIndexInUse,pSharedMemory->NumberOfResourcesInUse));
for (Index = 0; Index <= pSharedMemory->HighestIndexInUse; Index++) {
pNetResource = &pSharedMemory->NetResources[Index];
if (pNetResource->InUse) {
UNICODE_STRING EntryName;
if (bLocalName) {
EntryName.MaximumLength = pNetResource->LocalNameLength;
EntryName.Length = EntryName.MaximumLength;
EntryName.Buffer = pNetResource->LocalName;
} else {
EntryName.MaximumLength = pNetResource->RemoteNameLength;
EntryName.Length = EntryName.MaximumLength;
EntryName.Buffer = pNetResource->RemoteName;
}
TRACE_INFO(("NPCancelConnection: Name %S EntryName %S\n",
lpName,EntryName.Buffer));
TRACE_INFO(("NPCancelConnection: Name Length %d Entry Name Length %d\n",
Name.Length,EntryName.Length));
if (Name.Length == EntryName.Length) {
if (RtlEqualUnicodeString(
&Name,
&EntryName,
TRUE)) {
EntryFound = TRUE;
break;
}
}
}
}
if (EntryFound) {
HANDLE ConnectionHandle;
IO_STATUS_BLOCK IoStatusBlock;
UNICODE_STRING ConnectionName;
TRACE_INFO(("NPCancelConnection: Connection Found:\n"));
ConnectionName.Length = pNetResource->ConnectionNameLength;
ConnectionName.MaximumLength = ConnectionName.Length;
ConnectionName.Buffer = pNetResource->ConnectionName;
Status = OpenConnection(
&ConnectionName,
FILE_OPEN,
NULL,
0,
&ConnectionHandle);
if (Status == WN_SUCCESS) {
Status = NtFsControlFile(
ConnectionHandle,
NULL,
NULL,
NULL,
&IoStatusBlock,
FSCTL_IFSMRX_DELETE_CONNECTION,
NULL,
0,
NULL,
0);
NtClose(ConnectionHandle);
TRACE_ERROR(("NPCancelConnection: NtFsControlFile returned Status %lx\n",Status));
if (bLocalName) {
if (DefineDosDevice(
DDD_REMOVE_DEFINITION | DDD_RAW_TARGET_PATH | DDD_EXACT_MATCH_ON_REMOVE,
lpName,
pNetResource->ConnectionName) == FALSE) {
TRACE_ERROR(("RemoveDosDevice: DefineDosDevice error: %d\n", GetLastError()));
Status = GetLastError();
} else {
pNetResource->InUse = FALSE;
if (Index == pSharedMemory->HighestIndexInUse) {
pSharedMemory->HighestIndexInUse -= 1;
pSharedMemory->NumberOfResourcesInUse -= 1;
}
}
} else {
Status = RtlNtStatusToDosError(Status);
}
} else {
TRACE_ERROR(("NPCancelConnection: OpenConnection returned Status %lx\n",Status));
}
} else {
Status = WN_BAD_NETNAME;
}
CloseSharedMemory(
&hMutex,
&hMemory,
(PVOID)&pSharedMemory);
}
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 = 0;
UNICODE_STRING Name;
HANDLE hMutex, hMemory;
PIFSMRXNP_SHARED_MEMORY pSharedMemory;
Name.MaximumLength = Name.Length = wcslen(lpLocalName) * sizeof(WCHAR);
Name.Buffer = lpLocalName;
Status = OpenSharedMemory(
&hMutex,
&hMemory,
(PVOID)&pSharedMemory);
if (Status == WN_SUCCESS) {
INT Index;
BOOL EntryFound = FALSE;
PIFSMRXNP_NETRESOURCE pNetResource;
for (Index = 0; Index <= pSharedMemory->HighestIndexInUse; Index++) {
pNetResource = &pSharedMemory->NetResources[Index];
if (pNetResource->InUse) {
UNICODE_STRING EntryName;
EntryName.MaximumLength = pNetResource->LocalNameLength;
EntryName.Length = EntryName.MaximumLength;
EntryName.Buffer = pNetResource->LocalName;
if (Name.Length == EntryName.Length) {
if (RtlEqualUnicodeString(
&Name,
&EntryName,
TRUE)) {
EntryFound = TRUE;
break;
}
}
}
}
if (EntryFound) {
if (*lpBufferSize < pNetResource->RemoteNameLength) {
*lpBufferSize = pNetResource->RemoteNameLength;
Status = ERROR_BUFFER_OVERFLOW;
} else {
*lpBufferSize = pNetResource->RemoteNameLength;
RtlCopyMemory(
lpRemoteName,
pNetResource->RemoteName,
pNetResource->RemoteNameLength);
Status = WN_SUCCESS;
}
} else {
Status = ERROR_NO_NET_OR_BAD_PATH;
}
CloseSharedMemory(
&hMutex,
&hMemory,
(PVOID)&pSharedMemory);
}
return(Status);
}
DWORD APIENTRY
NPGetResourceParent(
LPNETRESOURCE lpNetResource,
LPVOID lpBuffer,
LPDWORD lpBufferSize )
/*++
Routine Description:
This routine returns the parent of a given resource
Arguments:
lpNetResource - the NETRESOURCE struct
lpBuffer - the buffer for passing back the parent information
lpBufferSize - the buffer size
Return Value:
WN_NOT_SUPPORTED
Notes:
The current sample does not handle this call.
--*/
{
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:
--*/
{
DWORD dwStatus = 0;
LPNETRESOURCE pOutNetResource;
TRACE_CALL(("NPGetResourceInformation\n"));
return(dwStatus);
}
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:
--*/
{
DWORD dwStatus;
DWORD BufferRequired = 0;
DWORD UniversalNameLength = 0;
DWORD RemoteNameLength = 0;
DWORD RemainingPathLength = 0;
LPWSTR pDriveLetter,
pRemainingPath,
SourceStrings[3];
WCHAR RemoteName[MAX_PATH],
LocalPath[MAX_PATH],
UniversalName[MAX_PATH],
ReplacedChar;
TRACE_CALL(("NPGetUniversalName: lpLocalPath: %S InfoLevel: %d\n", lpLocalPath, dwInfoLevel));
if (dwInfoLevel != UNIVERSAL_NAME_INFO_LEVEL &&
dwInfoLevel != REMOTE_NAME_INFO_LEVEL) {
TRACE_ERROR(("NPGetUniversalName: bad dwInfoLevel value: %d\n", dwInfoLevel));
return(WN_BAD_LEVEL);
}
wcscpy(LocalPath, lpLocalPath);
pDriveLetter = LocalPath;
if (pRemainingPath = wcschr(pDriveLetter, L':')) {
ReplacedChar = *(++pRemainingPath);
*pRemainingPath = L'\0';
}
if ((dwStatus = NPGetConnection(pDriveLetter, RemoteName, &RemoteNameLength)) != WN_SUCCESS) {
TRACE_ERROR(("NPGetUniversalName: NPGetConnection return dwStatus: %d\n", dwStatus));
return(dwStatus);
}
if (pRemainingPath) {
*pRemainingPath = ReplacedChar;
}
TRACE_INFO(("NPGetUniversalName: pRemainingPath: %S RemoteName: %S\n", pRemainingPath, RemoteName));
wcscpy(UniversalName, RemoteName);
if (pRemainingPath)
wcscat(UniversalName, pRemainingPath);
TRACE_INFO(("NPGetUniversalName: UniversalName: %S\n", UniversalName));
// Determine if the provided buffer is large enough.
UniversalNameLength = (wcslen(UniversalName) + 1) * sizeof(WCHAR);
BufferRequired = UniversalNameLength;
if (dwInfoLevel == UNIVERSAL_NAME_INFO_LEVEL) {
BufferRequired += sizeof(UNIVERSAL_NAME_INFO);
}
else {
RemoteNameLength = (wcslen(RemoteName) + 1) * sizeof(WCHAR);
BufferRequired += sizeof(REMOTE_NAME_INFO) + RemoteNameLength;
if (pRemainingPath) {
RemainingPathLength = (wcslen(pRemainingPath) + 1) * sizeof(WCHAR);
BufferRequired += RemainingPathLength;
}
}
if (*lpBufferSize < BufferRequired) {
TRACE_ERROR(("NPGetUniversalName: WN_MORE_DATA BufferRequired: %d\n", BufferRequired));
*lpBufferSize = BufferRequired;
return(WN_MORE_DATA);
}
if (dwInfoLevel == UNIVERSAL_NAME_INFO_LEVEL) {
LPUNIVERSAL_NAME_INFOW pUniversalNameInfo;
pUniversalNameInfo = (LPUNIVERSAL_NAME_INFOW)lpBuffer;
pUniversalNameInfo->lpUniversalName = (PWCHAR)((PBYTE)lpBuffer + sizeof(UNIVERSAL_NAME_INFOW));
RtlCopyMemory(
pUniversalNameInfo->lpUniversalName,
UniversalName,
UniversalNameLength);
} else {
LPREMOTE_NAME_INFOW pRemoteNameInfo;
pRemoteNameInfo = (LPREMOTE_NAME_INFOW)lpBuffer;
pRemoteNameInfo->lpUniversalName = (PWCHAR)((PBYTE)lpBuffer + sizeof(REMOTE_NAME_INFOW));
pRemoteNameInfo->lpConnectionName = pRemoteNameInfo->lpUniversalName + UniversalNameLength;
pRemoteNameInfo->lpRemainingPath = pRemoteNameInfo->lpConnectionName + RemoteNameLength;
RtlCopyMemory(
pRemoteNameInfo->lpUniversalName,
UniversalName,
UniversalNameLength);
RtlCopyMemory(
pRemoteNameInfo->lpConnectionName,
RemoteName,
RemoteNameLength);
RtlCopyMemory(
pRemoteNameInfo->lpRemainingPath,
pRemainingPath,
RemainingPathLength);
}
TRACE_CALL(("NPGetUniversalName: WN_SUCCESS\n"));
return(WN_SUCCESS);
}