Last active
April 17, 2020 04:58
-
-
Save billziss-gh/9bc2b3eba7599680ccb7a3e21081c2dd to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/inc/winfsp/launch.h b/inc/winfsp/launch.h | |
index 112ee251..4a029316 100644 | |
--- a/inc/winfsp/launch.h | |
+++ b/inc/winfsp/launch.h | |
@@ -292,7 +292,8 @@ typedef struct _FSP_LAUNCH_REG_RECORD | |
ULONG Credentials; | |
ULONG AuthPackageId; | |
ULONG Recovery; | |
- ULONG Reserved1[4]; | |
+ ULONG VolumePrefixComponentCount; | |
+ ULONG Reserved1[3]; | |
UINT8 Buffer[]; | |
} FSP_LAUNCH_REG_RECORD; | |
#pragma warning(pop) | |
diff --git a/src/dll/launch.c b/src/dll/launch.c | |
index 8912cdd7..9d05edfd 100644 | |
--- a/src/dll/launch.c | |
+++ b/src/dll/launch.c | |
@@ -275,6 +275,7 @@ FSP_API NTSTATUS FspLaunchRegSetRecord( | |
SETFIELDI(Credentials, 0); | |
SETFIELDI(AuthPackageId, 0); | |
SETFIELDI(Recovery, 0); | |
+ SETFIELDI(VolumePrefixComponentCount, 0); | |
} | |
else | |
{ | |
@@ -428,6 +429,7 @@ FSP_API NTSTATUS FspLaunchRegGetRecord( | |
GETFIELDI(Credentials); | |
GETFIELDI(AuthPackageId); | |
GETFIELDI(Recovery); | |
+ GETFIELDI(VolumePrefixComponentCount); | |
if (0 == Record->Executable) | |
{ | |
@@ -461,6 +463,8 @@ FSP_API NTSTATUS FspLaunchRegGetRecord( | |
Record->JobControl = RecordBuf.JobControl; | |
Record->Credentials = RecordBuf.Credentials; | |
Record->AuthPackageId = RecordBuf.AuthPackageId; | |
+ Record->Recovery = RecordBuf.Recovery; | |
+ Record->VolumePrefixComponentCount = RecordBuf.VolumePrefixComponentCount; | |
*PRecord = Record; | |
Result = STATUS_SUCCESS; | |
diff --git a/src/dll/library.def b/src/dll/library.def | |
index 8c61982f..0d812ad5 100644 | |
--- a/src/dll/library.def | |
+++ b/src/dll/library.def | |
@@ -9,3 +9,4 @@ EXPORTS | |
NPOpenEnum PRIVATE | |
NPEnumResource PRIVATE | |
NPCloseEnum PRIVATE | |
+ NPGetResourceInformation PRIVATE | |
diff --git a/src/dll/np.c b/src/dll/np.c | |
index ce04708a..12cb7bfb 100644 | |
--- a/src/dll/np.c | |
+++ b/src/dll/np.c | |
@@ -87,7 +87,8 @@ DWORD APIENTRY NPGetCaps(DWORD Index) | |
* WNNC_DLG_PROPERTYDIALOG | |
* WNNC_DLG_SEARCHDIALOG | |
*/ | |
- return 0; | |
+ return | |
+ WNNC_DLG_GETRESOURCEINFORMATION; | |
case WNNC_ENUMERATION: | |
/* | |
* WNNC_ENUM_GLOBAL | |
@@ -869,6 +870,7 @@ typedef struct | |
DWORD dwScope; | |
PWCHAR VolumeListBuf, VolumeListBufEnd, VolumeName; | |
DWORD LogicalDrives; | |
+ PWSTR RemoteName, *PRemain; | |
} FSP_NP_ENUM; | |
static inline BOOLEAN FspNpValidateEnum(FSP_NP_ENUM *Enum) | |
@@ -885,6 +887,40 @@ static inline BOOLEAN FspNpValidateEnum(FSP_NP_ENUM *Enum) | |
#endif | |
} | |
+static DWORD APIENTRY NPOpenEnumWithVolumePrefix( | |
+ DWORD dwScope, PWSTR VolumePrefix, PWSTR VolumePrefixEnd, LPHANDLE lphEnum) | |
+{ | |
+ static const WCHAR DevicePrefix[] = L"\\Device\\Volume{00000000-0000-0000-0000-000000000000}"; | |
+ FSP_NP_ENUM *Enum = 0; | |
+ SIZE_T VolumeListSize; | |
+ | |
+ Enum = MemAlloc(sizeof *Enum); | |
+ if (0 == Enum) | |
+ return WN_OUT_OF_MEMORY; | |
+ | |
+ VolumeListSize = sizeof DevicePrefix + (VolumePrefixEnd - VolumePrefix) * sizeof(WCHAR); | |
+ Enum->VolumeListBuf = MemAlloc(VolumeListSize); | |
+ if (0 == Enum->VolumeListBuf) | |
+ { | |
+ MemFree(Enum); | |
+ return WN_OUT_OF_MEMORY; | |
+ } | |
+ memcpy(Enum->VolumeListBuf, DevicePrefix, sizeof DevicePrefix); | |
+ memcpy(Enum->VolumeListBuf + sizeof DevicePrefix / sizeof(WCHAR) - 1, | |
+ VolumePrefix, (VolumePrefixEnd - VolumePrefix) * sizeof(WCHAR)); | |
+ Enum->VolumeListBuf[sizeof DevicePrefix / sizeof(WCHAR) - 1 + VolumePrefixEnd - VolumePrefix] = L'\0'; | |
+ | |
+ Enum->Signature = 'munE'; | |
+ Enum->dwScope = dwScope; | |
+ Enum->VolumeListBufEnd = (PVOID)((PUINT8)Enum->VolumeListBuf + VolumeListSize); | |
+ Enum->VolumeName = Enum->VolumeListBuf; | |
+ Enum->LogicalDrives = GetLogicalDrives(); | |
+ | |
+ *lphEnum = Enum; | |
+ | |
+ return WN_SUCCESS; | |
+} | |
+ | |
DWORD APIENTRY NPOpenEnum( | |
DWORD dwScope, DWORD dwType, DWORD dwUsage, LPNETRESOURCEW lpNetResource, LPHANDLE lphEnum) | |
{ | |
@@ -937,7 +973,7 @@ DWORD APIENTRY NPEnumResource( | |
PWCHAR ProviderName = 0; | |
DWORD Count; | |
PWCHAR P, VolumePrefix; | |
- ULONG Backslashes; | |
+ ULONG Backslashes, VolumePrefixLen; | |
WCHAR Drive; | |
if (!FspNpValidateEnum(Enum)) | |
@@ -968,12 +1004,15 @@ DWORD APIENTRY NPEnumResource( | |
if (3 == ++Backslashes) | |
break; | |
- if (3 == Backslashes) | |
+ VolumePrefixLen = lstrlenW(VolumePrefix); | |
+ if (3 == Backslashes && (0 == Enum->RemoteName || | |
+ 0 == invariant_wcsnicmp(Enum->RemoteName, VolumePrefix, VolumePrefixLen))) | |
{ | |
Drive = FspNpGetDriveLetter(&Enum->LogicalDrives, Enum->VolumeName); | |
- Strings -= (Drive ? 3 : 0) + 2/* backslash + term-0 */ + lstrlenW(VolumePrefix) + | |
- (0 == ProviderName ? lstrlenW(L"" FSP_NP_NAME) + 1 : 0); | |
+ Strings -= (Drive ? 3 : 0) + 2/* backslash + term-0 */ + VolumePrefixLen + | |
+ (0 == ProviderName ? lstrlenW(L"" FSP_NP_NAME) + 1 : 0) + | |
+ (0 != Enum->PRemain ? lstrlenW(Enum->RemoteName) - VolumePrefixLen + 1 : 0); | |
if ((PVOID)(Resource + 1) > (PVOID)Strings) | |
{ | |
@@ -993,9 +1032,16 @@ DWORD APIENTRY NPEnumResource( | |
goto exit; | |
} | |
+ if (0 != Enum->PRemain) | |
+ { | |
+ *Enum->PRemain = Strings + (Drive ? 3 : 0) + 2/* backslash + term-0 */ + VolumePrefixLen + | |
+ (0 == ProviderName ? lstrlenW(L"" FSP_NP_NAME) + 1 : 0); | |
+ lstrcpyW(*Enum->PRemain, Enum->RemoteName + VolumePrefixLen); | |
+ } | |
+ | |
if (0 == ProviderName) | |
{ | |
- ProviderName = Strings + (Drive ? 3 : 0) + 2/* backslash + term-0 */ + lstrlenW(VolumePrefix); | |
+ ProviderName = Strings + (Drive ? 3 : 0) + 2/* backslash + term-0 */ + VolumePrefixLen; | |
lstrcpyW(ProviderName, L"" FSP_NP_NAME); | |
} | |
@@ -1056,6 +1102,88 @@ DWORD APIENTRY NPCloseEnum(HANDLE hEnum) | |
return WN_SUCCESS; | |
} | |
+DWORD APIENTRY NPGetResourceInformation( | |
+ LPNETRESOURCEW lpNetResource, LPVOID lpBuffer, LPDWORD lpBufferSize, LPWSTR *lplpSystem) | |
+{ | |
+ DWORD NpResult; | |
+ NTSTATUS Result; | |
+ DWORD dwType = lpNetResource->dwType; | |
+ LPWSTR lpRemoteName = lpNetResource->lpRemoteName; | |
+ PWSTR ClassName, InstanceName, RemoteName; | |
+ ULONG ClassNameLen, InstanceNameLen; | |
+ WCHAR ClassNameBuf[sizeof(((FSP_FSCTL_VOLUME_PARAMS *)0)->Prefix) / sizeof(WCHAR)]; | |
+ HANDLE Enum; | |
+ DWORD EnumCount; | |
+ FSP_LAUNCH_REG_RECORD *Record; | |
+ ULONG RegVolumePrefixComponentCount, VolumePrefixComponentCount; | |
+ PWSTR VolumePrefixEnd; | |
+ | |
+ if (dwType & RESOURCETYPE_PRINT) | |
+ return WN_BAD_VALUE; | |
+ | |
+ if (!FspNpParseRemoteName(lpRemoteName, | |
+ &ClassName, &ClassNameLen, &InstanceName, &InstanceNameLen)) | |
+ return WN_BAD_NETNAME; | |
+ RemoteName = lpRemoteName + 1; | |
+ | |
+ if (ClassNameLen > sizeof ClassNameBuf / sizeof ClassNameBuf[0] - 1) | |
+ ClassNameLen = sizeof ClassNameBuf / sizeof ClassNameBuf[0] - 1; | |
+ memcpy(ClassNameBuf, ClassName, ClassNameLen * sizeof(WCHAR)); | |
+ ClassNameBuf[ClassNameLen] = '\0'; | |
+ | |
+ NpResult = NPOpenEnum( | |
+ RESOURCE_CONNECTED, RESOURCETYPE_DISK, RESOURCEUSAGE_CONNECTABLE, 0, &Enum); | |
+ if (WN_SUCCESS == NpResult) | |
+ { | |
+ ((FSP_NP_ENUM *)Enum)->RemoteName = RemoteName; | |
+ ((FSP_NP_ENUM *)Enum)->PRemain = lplpSystem; | |
+ | |
+ EnumCount = 1; | |
+ NpResult = NPEnumResource(Enum, &EnumCount, lpBuffer, lpBufferSize); | |
+ NPCloseEnum(Enum); | |
+ if (WN_SUCCESS == NpResult) | |
+ return NpResult; | |
+ } | |
+ | |
+ Result = FspLaunchRegGetRecord(ClassNameBuf, L"" FSP_NP_NAME, &Record); | |
+ if (!NT_SUCCESS(Result)) | |
+ return WN_BAD_NETNAME; | |
+ RegVolumePrefixComponentCount = Record->VolumePrefixComponentCount; | |
+ FspLaunchRegFreeRecord(Record); | |
+ | |
+ if (RegVolumePrefixComponentCount < 2) | |
+ RegVolumePrefixComponentCount = 2; | |
+ | |
+ VolumePrefixComponentCount = 0; | |
+ for (VolumePrefixEnd = RemoteName; L'\0' != *VolumePrefixEnd; VolumePrefixEnd++) | |
+ if (L'\\' == *VolumePrefixEnd) | |
+ { | |
+ if (RegVolumePrefixComponentCount == VolumePrefixComponentCount) | |
+ break; | |
+ } | |
+ else if (VolumePrefixEnd > RemoteName && L'\\' == VolumePrefixEnd[-1]) | |
+ VolumePrefixComponentCount++; | |
+ | |
+ if (RegVolumePrefixComponentCount != VolumePrefixComponentCount) | |
+ return WN_BAD_NETNAME; | |
+ | |
+ NpResult = NPOpenEnumWithVolumePrefix( | |
+ RESOURCE_CONTEXT, RemoteName, VolumePrefixEnd, &Enum); | |
+ if (WN_SUCCESS == NpResult) | |
+ { | |
+ ((FSP_NP_ENUM *)Enum)->RemoteName = RemoteName; | |
+ ((FSP_NP_ENUM *)Enum)->PRemain = lplpSystem; | |
+ | |
+ EnumCount = 1; | |
+ NpResult = NPEnumResource(Enum, &EnumCount, lpBuffer, lpBufferSize); | |
+ NPCloseEnum(Enum); | |
+ if (WN_SUCCESS == NpResult) | |
+ return NpResult; | |
+ } | |
+ | |
+ return WN_BAD_NETNAME; | |
+} | |
+ | |
NTSTATUS FspNpRegister(VOID) | |
{ | |
extern HINSTANCE DllInstance; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment