sys, dll: NetworkProvider implementation (NPGetConnection)

This commit is contained in:
Bill Zissimopoulos 2016-04-19 14:29:07 -07:00
parent c40ce93fe2
commit 1bcd3cec0a
11 changed files with 546 additions and 0 deletions

View File

@ -24,6 +24,7 @@
<ClInclude Include="..\..\src\dll\library.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\dll\np.c" />
<ClCompile Include="..\..\src\dll\security.c" />
<ClCompile Include="..\..\src\dll\debug.c" />
<ClCompile Include="..\..\src\dll\fsctl.c" />
@ -34,6 +35,7 @@
<ClCompile Include="..\..\src\dll\path.c" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\src\dll\library.def" />
<None Include="..\..\src\dll\ntstatus.i" />
</ItemGroup>
<PropertyGroup Label="Globals">
@ -133,6 +135,7 @@
<GenerateMapFile>true</GenerateMapFile>
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@ -156,6 +159,7 @@
<GenerateMapFile>true</GenerateMapFile>
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@ -182,6 +186,7 @@
<GenerateMapFile>true</GenerateMapFile>
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@ -208,6 +213,7 @@
<GenerateMapFile>true</GenerateMapFile>
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@ -49,10 +49,16 @@
<ClCompile Include="..\..\src\dll\security.c">
<Filter>Source</Filter>
</ClCompile>
<ClCompile Include="..\..\src\dll\np.c">
<Filter>Source</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\..\src\dll\ntstatus.i">
<Filter>Source</Filter>
</None>
<None Include="..\..\src\dll\library.def">
<Filter>Source</Filter>
</None>
</ItemGroup>
</Project>

View File

@ -34,6 +34,8 @@ extern const __declspec(selectany) GUID FspFsvrtDeviceClassGuid =
/* fsctl device codes */
#define FSP_FSCTL_VOLUME_NAME \
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'N', METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSP_FSCTL_VOLUME_LIST \
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'L', METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSP_FSCTL_TRANSACT \
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'T', METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSP_FSCTL_TRANSACT_BATCH \
@ -405,6 +407,8 @@ FSP_API NTSTATUS FspFsctlTransact(HANDLE VolumeHandle,
PVOID RequestBuf, SIZE_T *PRequestBufSize,
BOOLEAN Batch);
FSP_API NTSTATUS FspFsctlStop(HANDLE VolumeHandle);
FSP_API NTSTATUS FspFsctlGetVolumeList(PWSTR DevicePath,
PWCHAR VolumeListBuf, PSIZE_T PVolumeListSize);
#endif
#ifdef __cplusplus

View File

@ -119,3 +119,58 @@ FSP_API NTSTATUS FspFsctlStop(HANDLE VolumeHandle)
return STATUS_SUCCESS;
}
FSP_API NTSTATUS FspFsctlGetVolumeList(PWSTR DevicePath,
PWCHAR VolumeListBuf, PSIZE_T PVolumeListSize)
{
NTSTATUS Result;
PWSTR DeviceRoot;
SIZE_T DeviceRootSize, DevicePathSize;
WCHAR DevicePathBuf[MAX_PATH], *DevicePathPtr;
HANDLE VolumeHandle = INVALID_HANDLE_VALUE;
DWORD Bytes;
/* check lengths; everything must fit within MAX_PATH */
DeviceRoot = L'\\' == DevicePath[0] ? GLOBALROOT : GLOBALROOT "\\Device\\";
DeviceRootSize = lstrlenW(DeviceRoot) * sizeof(WCHAR);
DevicePathSize = lstrlenW(DevicePath) * sizeof(WCHAR);
if (DeviceRootSize + DevicePathSize + sizeof(WCHAR) > sizeof DevicePathBuf)
return STATUS_INVALID_PARAMETER;
/* prepare the device path to be opened */
DevicePathPtr = DevicePathBuf;
memcpy(DevicePathPtr, DeviceRoot, DeviceRootSize);
DevicePathPtr = (PVOID)((PUINT8)DevicePathPtr + DeviceRootSize);
memcpy(DevicePathPtr, DevicePath, DevicePathSize);
DevicePathPtr = (PVOID)((PUINT8)DevicePathPtr + DevicePathSize);
*DevicePathPtr = L'\0';
VolumeHandle = CreateFileW(DevicePathBuf,
0, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
if (INVALID_HANDLE_VALUE == VolumeHandle)
{
Result = FspNtStatusFromWin32(GetLastError());
if (STATUS_OBJECT_PATH_NOT_FOUND == Result ||
STATUS_OBJECT_NAME_NOT_FOUND == Result)
Result = STATUS_NO_SUCH_DEVICE;
goto exit;
}
if (!DeviceIoControl(VolumeHandle, FSP_FSCTL_VOLUME_LIST,
0, 0,
VolumeListBuf, (DWORD)*PVolumeListSize,
&Bytes, 0))
{
Result = FspNtStatusFromWin32(GetLastError());
goto exit;
}
*PVolumeListSize = Bytes;
Result = STATUS_SUCCESS;
exit:
if (INVALID_HANDLE_VALUE != VolumeHandle)
CloseHandle(VolumeHandle);
return Result;
}

View File

@ -6,6 +6,7 @@
#include <dll/library.h>
HINSTANCE DllInstance;
HANDLE ProcessHeap;
BOOL WINAPI DllMain(HINSTANCE Instance, DWORD Reason, PVOID Reserved)
@ -13,6 +14,7 @@ BOOL WINAPI DllMain(HINSTANCE Instance, DWORD Reason, PVOID Reserved)
switch (Reason)
{
case DLL_PROCESS_ATTACH:
DllInstance = Instance;
ProcessHeap = GetProcessHeap();
if (0 == ProcessHeap)
return FALSE;
@ -33,3 +35,21 @@ BOOL WINAPI _DllMainCRTStartup(HINSTANCE Instance, DWORD Reason, PVOID Reserved)
return DllMain(Instance, Reason, Reserved);
}
#endif
HRESULT WINAPI DllRegisterServer(VOID)
{
NTSTATUS Result;
Result = FspNpRegister();
return NT_SUCCESS(Result) ? S_OK : 0x80040201/*SELFREG_E_CLASS*/;
}
HRESULT WINAPI DllUnregisterServer(VOID)
{
NTSTATUS Result;
Result = FspNpUnregister();
return NT_SUCCESS(Result) ? S_OK : 0x80040201/*SELFREG_E_CLASS*/;
}

5
src/dll/library.def Normal file
View File

@ -0,0 +1,5 @@
EXPORTS
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
NPGetCaps PRIVATE
NPGetConnection PRIVATE

View File

@ -95,4 +95,7 @@ BOOLEAN RemoveEntryList(PLIST_ENTRY Entry)
VOID FspFileSystemInitialize(VOID);
VOID FspFileSystemFinalize(VOID);
NTSTATUS FspNpRegister(VOID);
NTSTATUS FspNpUnregister(VOID);
#endif

351
src/dll/np.c Normal file
View File

@ -0,0 +1,351 @@
/**
* @file dll/np.c
*
* @copyright 2015-2016 Bill Zissimopoulos
*/
#include <dll/library.h>
#include <npapi.h>
#define FSP_NP_NAME "WinFsp.Np"
#define FSP_NP_DESC "File System Proxy"
#define FSP_NP_TYPE ' spF' /* pick a value hopefully not in use */
DWORD APIENTRY NPGetCaps(DWORD Index)
{
switch (Index)
{
case WNNC_ADMIN:
/*
* WNNC_ADM_DIRECTORYNOTIFY
* WNNC_ADM_GETDIRECTORYTYPE
*/
return 0;
case WNNC_CONNECTION:
/*
* WNNC_CON_ADDCONECTION
* WNNC_CON_CANCELCONNECTION
* WNNC_CON_GETCONNECTIONS
* WNNC_CON_ADDCONECTION3
* WNNC_CON_GETPERFORMANCE
* WNNC_CON_DEFER
*/
return WNNC_CON_GETCONNECTIONS;
case WNNC_DIALOG:
/*
* WNNC_DLG_DEVICEMODE
* WNNC_DLG_FORMATNETNAME
* WNNC_DLG_GETRESOURCEINFORMATION
* WNNC_DLG_GETRESOURCEPARENT
* WNNC_DLG_PERMISSIONEDITOR
* WNNC_DLG_PROPERTYDIALOG
* WNNC_DLG_SEARCHDIALOG
*/
return 0;
case WNNC_ENUMERATION:
/*
* WNNC_ENUM_GLOBAL
* WNNC_ENUM_LOCAL
* WNNC_ENUM_CONTEXT
*/
return 0;
case WNNC_NET_TYPE:
return FSP_NP_TYPE;
case WNNC_SPEC_VERSION:
return WNNC_SPEC_VERSION51;
case WNNC_START:
return 1;
case WNNC_USER:
/*
* WNNC_USR_GETUSER
*/
return 0;
default:
return 0;
}
}
static NTSTATUS FspNpGetVolumeList(
PWCHAR *PVolumeListBuf, PSIZE_T PVolumeListSize)
{
NTSTATUS Result;
PWCHAR VolumeListBuf;
SIZE_T VolumeListSize;
*PVolumeListBuf = 0;
*PVolumeListSize = 0;
for (VolumeListSize = 1024;; VolumeListSize *= 2)
{
VolumeListBuf = MemAlloc(VolumeListSize);
if (0 == VolumeListBuf)
return STATUS_INSUFFICIENT_RESOURCES;
Result = FspFsctlGetVolumeList(L"" FSP_FSCTL_NET_DEVICE_NAME,
VolumeListBuf, &VolumeListSize);
if (NT_SUCCESS(Result))
{
*PVolumeListBuf = VolumeListBuf;
*PVolumeListSize = VolumeListSize;
return Result;
}
MemFree(VolumeListBuf);
if (STATUS_BUFFER_TOO_SMALL != Result)
return Result;
}
}
DWORD APIENTRY NPGetConnection(LPWSTR lpLocalName, LPWSTR lpRemoteName, LPDWORD lpnBufferLen)
{
DWORD NpResult;
NTSTATUS Result;
WCHAR LocalNameBuf[3];
WCHAR VolumeNameBuf[FSP_FSCTL_VOLUME_NAME_SIZEMAX / sizeof(WCHAR)];
PWCHAR VolumeListBuf = 0, VolumeListBufEnd, VolumeName, P;
SIZE_T VolumeListSize, VolumeNameSize;
ULONG Backslashes;
if (0 == lpLocalName ||
!(
(L'A' <= lpLocalName[0] && lpLocalName[0] <= L'Z') ||
(L'a' <= lpLocalName[0] && lpLocalName[0] <= L'z')
) ||
L':' != lpLocalName[1])
return WN_BAD_LOCALNAME;
LocalNameBuf[0] = lpLocalName[0];
LocalNameBuf[1] = L':';
LocalNameBuf[2] = L'\0';
if (0 == QueryDosDeviceW(LocalNameBuf, VolumeNameBuf, sizeof VolumeNameBuf))
return WN_NOT_CONNECTED;
Result = FspNpGetVolumeList(&VolumeListBuf, &VolumeListSize);
if (!NT_SUCCESS(Result))
return WN_OUT_OF_MEMORY;
NpResult = WN_NOT_CONNECTED;
for (P = VolumeListBuf, VolumeListBufEnd = (PVOID)((PUINT8)P + VolumeListSize), VolumeName = P;
VolumeListBufEnd > P; P++)
{
if (L'\0' == *P)
{
if (0 == lstrcmpW(VolumeNameBuf, VolumeName))
{
/*
* Looks like this is a WinFsp device. Extract the VolumePrefix from the VolumeName.
*
* The VolumeName will have the following syntax:
* \Device\Volume{GUID}\Server\Share
*
* We want to extract the \Server\Share part. We will simply count backslashes and
* stop at the third one. Since we are about to break this loop, it is ok to mess
* with the loop variables.
*/
for (Backslashes = 0; VolumeName < P; VolumeName++)
if (L'\\' == *VolumeName)
if (3 == ++Backslashes)
break;
if (3 == Backslashes)
{
VolumeNameSize = lstrlenW(VolumeName) + 1/* term-0 */;
if (*lpnBufferLen >= 1/* lead-\ */ + VolumeNameSize)
{
*lpRemoteName = L'\\';
memcpy(lpRemoteName + 1, VolumeName, VolumeNameSize * sizeof(WCHAR));
NpResult = WN_SUCCESS;
}
else
{
*lpnBufferLen = (DWORD)(1/* lead-\ */ + VolumeNameSize);
NpResult = WN_MORE_DATA;
}
}
break;
}
else
VolumeName = P + 1;
}
}
MemFree(VolumeListBuf);
return NpResult;
}
NTSTATUS FspNpRegister(VOID)
{
extern HINSTANCE DllInstance;
WCHAR ProviderPath[MAX_PATH];
WCHAR RegBuffer[1024];
PWSTR P, Part;
DWORD RegResult, RegType, RegBufferSize;
HKEY RegKey;
BOOLEAN FoundProvider;
if (0 == GetModuleFileNameW(DllInstance, ProviderPath, MAX_PATH))
return FspNtStatusFromWin32(GetLastError());
RegResult = RegCreateKeyExW(
HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\" FSP_NP_NAME,
0, 0, 0, KEY_ALL_ACCESS, 0, &RegKey, 0);
if (ERROR_SUCCESS != RegResult)
return FspNtStatusFromWin32(RegResult);
RegResult = RegSetValueExW(RegKey,
L"Group", 0, REG_SZ, (PVOID) L"NetworkProvider", sizeof L"NetworkProvider");
if (ERROR_SUCCESS != RegResult)
goto close_and_exit;
RegCloseKey(RegKey);
RegResult = RegCreateKeyExW(
HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\" FSP_NP_NAME "\\NetworkProvider",
0, 0, 0, KEY_ALL_ACCESS, 0, &RegKey, 0);
if (ERROR_SUCCESS != RegResult)
return FspNtStatusFromWin32(RegResult);
RegResult = RegSetValueExW(RegKey,
L"Name", 0, REG_SZ, (PVOID) L"" FSP_NP_DESC, sizeof L"" FSP_NP_DESC);
if (ERROR_SUCCESS != RegResult)
goto close_and_exit;
RegResult = RegSetValueExW(RegKey,
L"ProviderPath", 0, REG_SZ, (PVOID)ProviderPath, (lstrlenW(ProviderPath) + 1) * sizeof(WCHAR));
if (ERROR_SUCCESS != RegResult)
goto close_and_exit;
RegCloseKey(RegKey);
RegResult = RegOpenKeyExW(
HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\NetworkProvider\\Order",
0, KEY_ALL_ACCESS, &RegKey);
if (ERROR_SUCCESS != RegResult)
return FspNtStatusFromWin32(RegResult);
RegBufferSize = sizeof RegBuffer - sizeof L"," FSP_NP_NAME;
RegResult = RegQueryValueExW(RegKey,
L"ProviderOrder", 0, &RegType, (PVOID)RegBuffer, &RegBufferSize);
if (ERROR_SUCCESS != RegResult)
goto close_and_exit;
RegBufferSize /= sizeof(WCHAR);
FoundProvider = FALSE;
RegBuffer[RegBufferSize] = L'\0';
P = RegBuffer, Part = P;
do
{
if (L',' == *P || '\0' == *P)
{
if (CSTR_EQUAL == CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE,
Part, (int)(P - Part),
L"" FSP_NP_NAME, (int)(sizeof L"" FSP_NP_NAME - sizeof(WCHAR)) / sizeof(WCHAR)))
{
FoundProvider = TRUE;
break;
}
else
Part = P + 1;
}
} while (L'\0' != *P++);
if (!FoundProvider)
{
P--;
memcpy(P, L"," FSP_NP_NAME, sizeof L"," FSP_NP_NAME);
RegBufferSize = lstrlenW(RegBuffer);
RegBufferSize++;
RegResult = RegSetValueExW(RegKey,
L"ProviderOrder", 0, REG_SZ, (PVOID)RegBuffer, RegBufferSize * sizeof(WCHAR));
if (ERROR_SUCCESS != RegResult)
goto close_and_exit;
}
RegCloseKey(RegKey);
return STATUS_SUCCESS;
close_and_exit:
RegCloseKey(RegKey);
return FspNtStatusFromWin32(RegResult);
}
NTSTATUS FspNpUnregister(VOID)
{
WCHAR RegBuffer[1024];
PWSTR P, Part;
DWORD RegResult, RegType, RegBufferSize;
HKEY RegKey;
BOOLEAN FoundProvider;
RegResult = RegOpenKeyExW(
HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\NetworkProvider\\Order",
0, KEY_ALL_ACCESS, &RegKey);
if (ERROR_SUCCESS != RegResult)
return FspNtStatusFromWin32(RegResult);
RegBufferSize = sizeof RegBuffer - sizeof L"," FSP_NP_NAME;
RegResult = RegQueryValueExW(RegKey,
L"ProviderOrder", 0, &RegType, (PVOID)RegBuffer, &RegBufferSize);
if (ERROR_SUCCESS != RegResult)
goto close_and_exit;
RegBufferSize /= sizeof(WCHAR);
FoundProvider = FALSE;
RegBuffer[RegBufferSize] = L'\0';
P = RegBuffer, Part = P;
do
{
if (L',' == *P || '\0' == *P)
{
if (CSTR_EQUAL == CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE,
Part, (int)(P - Part),
L"" FSP_NP_NAME, (int)(sizeof L"" FSP_NP_NAME - sizeof(WCHAR)) / sizeof(WCHAR)))
{
FoundProvider = TRUE;
break;
}
else
Part = P + 1;
}
} while (L'\0' != *P++);
if (FoundProvider)
{
if (L',' == *P)
P++;
RtlMoveMemory(Part, P, (lstrlenW(P) + 1) * sizeof(WCHAR));
RegBufferSize = lstrlenW(RegBuffer);
while (0 < RegBufferSize && ',' == RegBuffer[RegBufferSize - 1])
RegBufferSize--;
RegBuffer[RegBufferSize] = L'\0';
RegBufferSize++;
RegResult = RegSetValueExW(RegKey,
L"ProviderOrder", 0, REG_SZ, (PVOID)RegBuffer, RegBufferSize * sizeof(WCHAR));
if (ERROR_SUCCESS != RegResult)
goto close_and_exit;
}
RegCloseKey(RegKey);
RegResult = RegDeleteTreeW(
HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\" FSP_NP_NAME);
if (ERROR_SUCCESS != RegResult && ERROR_FILE_NOT_FOUND != RegResult)
return FspNtStatusFromWin32(RegResult);
return STATUS_SUCCESS;
close_and_exit:
RegCloseKey(RegKey);
return FspNtStatusFromWin32(RegResult);
}

View File

@ -853,6 +853,8 @@ NTSTATUS FspVolumeRedirQueryPathEx(
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
NTSTATUS FspVolumeGetName(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
NTSTATUS FspVolumeGetNameList(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
NTSTATUS FspVolumeTransact(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
NTSTATUS FspVolumeStop(

View File

@ -35,6 +35,9 @@ static NTSTATUS FspFsctlFileSystemControl(
if (0 != IrpSp->FileObject->FsContext2)
Result = FspVolumeGetName(DeviceObject, Irp, IrpSp);
break;
case FSP_FSCTL_VOLUME_LIST:
Result = FspVolumeGetNameList(DeviceObject, Irp, IrpSp);
break;
case FSP_FSCTL_TRANSACT:
case FSP_FSCTL_TRANSACT_BATCH:
if (0 != IrpSp->FileObject->FsContext2)

View File

@ -24,6 +24,10 @@ NTSTATUS FspVolumeRedirQueryPathEx(
PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
NTSTATUS FspVolumeGetName(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
NTSTATUS FspVolumeGetNameList(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
static NTSTATUS FspVolumeGetNameListNoLock(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
NTSTATUS FspVolumeTransact(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
NTSTATUS FspVolumeStop(
@ -42,6 +46,8 @@ NTSTATUS FspVolumeWork(
// ! #pragma alloc_text(PAGE, FspVolumeMountNoLock)
#pragma alloc_text(PAGE, FspVolumeRedirQueryPathEx)
#pragma alloc_text(PAGE, FspVolumeGetName)
#pragma alloc_text(PAGE, FspVolumeGetNameList)
#pragma alloc_text(PAGE, FspVolumeGetNameListNoLock)
#pragma alloc_text(PAGE, FspVolumeTransact)
#pragma alloc_text(PAGE, FspVolumeStop)
#pragma alloc_text(PAGE, FspVolumeWork)
@ -60,6 +66,8 @@ typedef struct
NTSTATUS FspVolumeCreate(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
{
PAGED_CODE();
NTSTATUS Result;
FspDeviceGlobalLock();
Result = FspVolumeCreateNoLock(FsctlDeviceObject, Irp, IrpSp);
@ -259,6 +267,8 @@ static VOID FspVolumeCreateRegisterMup(PVOID Context)
VOID FspVolumeDelete(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
{
// !PAGED_CODE();
FspDeviceGlobalLock();
FspVolumeDeleteNoLock(FsctlDeviceObject, Irp, IrpSp);
FspDeviceGlobalUnlock();
@ -381,6 +391,8 @@ static VOID FspVolumeDeleteDelayed(PVOID Context)
NTSTATUS FspVolumeMount(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
{
// !PAGED_CODE();
NTSTATUS Result;
FspDeviceGlobalLock();
Result = FspVolumeMountNoLock(FsctlDeviceObject, Irp, IrpSp);
@ -532,6 +544,85 @@ NTSTATUS FspVolumeGetName(
return STATUS_SUCCESS;
}
NTSTATUS FspVolumeGetNameList(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
{
PAGED_CODE();
NTSTATUS Result;
FspDeviceGlobalLock();
Result = FspVolumeGetNameListNoLock(FsctlDeviceObject, Irp, IrpSp);
FspDeviceGlobalUnlock();
return Result;
}
static NTSTATUS FspVolumeGetNameListNoLock(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
{
PAGED_CODE();
ASSERT(IRP_MJ_FILE_SYSTEM_CONTROL == IrpSp->MajorFunction);
ASSERT(IRP_MN_USER_FS_REQUEST == IrpSp->MinorFunction);
ASSERT(FSP_FSCTL_VOLUME_LIST == IrpSp->Parameters.FileSystemControl.FsControlCode);
NTSTATUS Result;
ULONG OutputBufferLength = IrpSp->Parameters.FileSystemControl.OutputBufferLength;
PVOID SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
PDEVICE_OBJECT *DeviceObjects = 0;
ULONG DeviceObjectCount = 0;
PDEVICE_OBJECT FsvolDeviceObject;
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension;
UNICODE_STRING VolumeList;
USHORT Length;
if (65535/*USHRT_MAX*/ < OutputBufferLength)
return STATUS_INVALID_PARAMETER;
Result = FspDeviceCopyList(&DeviceObjects, &DeviceObjectCount);
if (!NT_SUCCESS(Result))
return Result;
Result = STATUS_SUCCESS;
RtlInitEmptyUnicodeString(&VolumeList, SystemBuffer, (USHORT)OutputBufferLength);
for (ULONG i = 0; NT_SUCCESS(Result) && DeviceObjectCount > i; i++)
if (FspDeviceReference(DeviceObjects[i]))
{
if (FspFsvolDeviceExtensionKind == FspDeviceExtension(DeviceObjects[i])->Kind)
{
FsvolDeviceObject = DeviceObjects[i];
FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
if (FsvolDeviceExtension->FsctlDeviceObject == FsctlDeviceObject &&
!FspIoqStopped(FsvolDeviceExtension->Ioq))
{
Length =
FsvolDeviceExtension->VolumeName.Length +
FsvolDeviceExtension->VolumePrefix.Length +
sizeof(WCHAR);
if (VolumeList.Length + Length <= VolumeList.MaximumLength)
{
RtlAppendUnicodeStringToString(&VolumeList, &FsvolDeviceExtension->VolumeName);
if (FILE_DEVICE_NETWORK_FILE_SYSTEM == FsctlDeviceObject->DeviceType)
RtlAppendUnicodeStringToString(&VolumeList, &FsvolDeviceExtension->VolumePrefix);
VolumeList.Buffer[VolumeList.Length / sizeof(WCHAR)] = L'\0';
VolumeList.Length += sizeof(WCHAR);
}
else
{
VolumeList.Length = 0;
Result = STATUS_BUFFER_TOO_SMALL;
}
}
}
FspDeviceDereference(DeviceObjects[i]);
}
FspDeviceDeleteList(DeviceObjects, DeviceObjectCount);
Irp->IoStatus.Information = VolumeList.Length;
return Result;
}
NTSTATUS FspVolumeTransact(
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
{