mirror of
https://github.com/winfsp/winfsp.git
synced 2025-07-03 01:12:58 -05:00
Compare commits
92 Commits
release/1.
...
v2.0B1
Author | SHA1 | Date | |
---|---|---|---|
f85fb49f49 | |||
9747af22e8 | |||
ef9b7e22c6 | |||
4783902d1d | |||
fd27c470b0 | |||
4cd2b8c612 | |||
dacaff41e4 | |||
c187209159 | |||
a2e92207c5 | |||
be27a82879 | |||
4f5ad93f00 | |||
b9ca46694e | |||
b47c42877a | |||
e50d7adc50 | |||
d1fc5e5d0f | |||
7f73192f8d | |||
c4ecd15c0a | |||
d71049225e | |||
91d7f3b673 | |||
63e23c2039 | |||
4d1594b1cf | |||
0eb6912296 | |||
c237a55951 | |||
c15006cce8 | |||
53b44dcb5c | |||
a3765d6360 | |||
98d68c4007 | |||
6c6dd8abcc | |||
16dd729fc7 | |||
e8cec5dfc1 | |||
a2d49a1ded | |||
9ede097e73 | |||
2c3800077f | |||
84b3f98d38 | |||
16734bf37a | |||
ea189c5b68 | |||
7735506cc7 | |||
ca3170c293 | |||
9a27a3225b | |||
d44cb54bd5 | |||
ba13995d10 | |||
d1f863e9ac | |||
ccdbc9daf9 | |||
1723179430 | |||
8e0f5b457c | |||
2fc2c237d3 | |||
b99fb9a5cb | |||
538fee8e54 | |||
925fa4b6e4 | |||
b179c7a933 | |||
b25e116f08 | |||
422c369b15 | |||
d450683e2e | |||
ad1aa156dc | |||
aa012db099 | |||
b08f60bfbd | |||
a9b3cef253 | |||
b43d1f5502 | |||
de9112f6e6 | |||
329b14d838 | |||
7009324e7f | |||
f4ae097722 | |||
50be07e8ac | |||
2dd054087c | |||
7f6608cf7d | |||
39e9d8156b | |||
90acd19014 | |||
9154ec784d | |||
0b3ce52958 | |||
deee7edded | |||
f41f410546 | |||
a2dc40fe3a | |||
adeed2b79d | |||
5dda5903a8 | |||
a7bc306b2d | |||
7e59c2e5a6 | |||
637e8bb8c2 | |||
9670caa3fe | |||
005d3e4fb0 | |||
62a6bbab66 | |||
40ba537dc2 | |||
ec832b45ff | |||
fc03b485f3 | |||
651e45c3ba | |||
95c2fadce0 | |||
b4453c89cc | |||
5483dcbd73 | |||
f1cfe758ec | |||
e9143a73a6 | |||
264450f627 | |||
a731f0e5d8 | |||
d7450d740e |
56
Changelog.md
56
Changelog.md
@ -1,6 +1,62 @@
|
||||
# Changelog
|
||||
|
||||
|
||||
## v2.0B1 (2023 Beta1)
|
||||
|
||||
This release is a major version change for WinFsp (from 1.x to 2.x). There are no backwards incompatible API changes in this release, but nevertheless enough things change that warrant a version change.
|
||||
|
||||
The major new feature of this release is that it allows uninstallation and reinstallation of WinFsp **without reboot**. Going forward installers named `winfsp-2.x.y.msi` can be uninstalled and reinstalled without reboot. Furthermore a later version `winfsp-2.x.y.msi` installer can be used to upgrade over an earlier version `winfsp-2.x.y.msi` installer. However note that a `winfsp-2.x.y.msi` installer cannot be used to upgrade over a "legacy" `winfsp-1.x.y.msi` installer; you will still need to uninstall the "old" `winfsp-1.x.y.msi` installer, potentially reboot and then install the "new" `winfsp-2.x.y.msi` installer.
|
||||
|
||||
Some changes that may be visible to file system developers are listed below:
|
||||
|
||||
- WinFsp executable files are now installed by default in the directory `C:\Program Files (x86)\WinFsp\SxS\sxs.<InstanceID>\bin`. The previous directory `C:\Program Files (x86)\WinFsp\bin` is now a junction that points to the above directory.
|
||||
|
||||
- The WinFsp driver name is no longer `winfsp`, but rather a name such as `winfsp+<InstanceID>`. This means that managing the driver using the `sc.exe` utility is no longer as easy.
|
||||
|
||||
- The `fsptool` utility has been updated with new commands `lsdrv`, `load`, `unload` and `ver`. The `lsdrv`, `load` and `unload` commands can be used to manage the driver from the command line. This is rarely necessary, but may be useful for troubleshooting purposes.
|
||||
|
||||
- The WinFsp symbols directory has been removed. If you are looking for WinFsp symbols you can find them at https://github.com/winfsp/winfsp.sym
|
||||
|
||||
|
||||
## v1.12 (2022.2)
|
||||
|
||||
- [NEW] WinFsp now supports mounting as directory using the Mount Manager. Use the syntax `\\.\C:\Path\To\Mount\Directory`.
|
||||
|
||||
- [NEW] A new registry setting `MountUseMountmgrFromFSD` has been added. See [WinFsp Registry Settings](https://github.com/winfsp/winfsp/wiki/WinFsp-Registry-Settings) for details.
|
||||
|
||||
- [FIX] A problem with Windows containers has been fixed. (GitHub issue #438.)
|
||||
|
||||
- [FIX] File systems can now be mounted as directories on ARM64. (GitHub issue #448.)
|
||||
|
||||
- [FIX] The passthrough file system now reports correct `IndexNumber`. (GitHub issue #325.)
|
||||
|
||||
- [BUILD] Product configuration for the relative paths to the File System Driver, Network Provider and EventLog is now possible via the file `build.version.props` located in `build\VStudio`.
|
||||
|
||||
|
||||
## v1.12B2 (2022.2 Beta2)
|
||||
|
||||
- [NEW] WinFsp now supports mounting as directory using the Mount Manager. Use the syntax `\\.\C:\Path\To\Mount\Directory`.
|
||||
|
||||
- [NEW] A new registry setting `MountUseMountmgrFromFSD` has been added. See [WinFsp Registry Settings](https://github.com/winfsp/winfsp/wiki/WinFsp-Registry-Settings) for details.
|
||||
|
||||
- [FIX] A problem with Windows containers has been fixed. (GitHub issue #438.)
|
||||
|
||||
- [FIX] File systems can now be mounted as directories on ARM64. (GitHub issue #448.)
|
||||
|
||||
- [FIX] The passthrough file system now reports correct `IndexNumber`. (GitHub issue #325.)
|
||||
|
||||
- [BUILD] Product configuration for the relative paths to the File System Driver, Network Provider and EventLog is now possible via the file `build.version.props` located in `build\VStudio`.
|
||||
|
||||
|
||||
## v1.12B1 (2022.2 Beta1)
|
||||
|
||||
- [NEW] WinFsp now supports mounting as directory using the Mount Manager. Use the syntax `\\.\C:\Path\To\Mount\Directory`.
|
||||
|
||||
- [NEW] A new registry setting `MountUseMountmgrFromFSD` has been added. See [WinFsp Registry Settings](https://github.com/winfsp/winfsp/wiki/WinFsp-Registry-Settings) for details.
|
||||
|
||||
- [BUILD] Product configuration for the relative paths to the File System Driver, Network Provider and EventLog is now possible via the file `build.version.props` located in `build\VStudio`.
|
||||
|
||||
|
||||
## v1.11 (2022+ARM64)
|
||||
|
||||
- [NEW] ARM64 support! For details see [WinFsp on ARM64](https://github.com/winfsp/winfsp/wiki/WinFsp-on-ARM64).
|
||||
|
@ -68,6 +68,7 @@ CONTRIBUTOR LIST
|
||||
|John Tyner |jtyner at gmail.com
|
||||
|Paweł Wegner (Google LLC, https://google.com) |lemourin at google.com
|
||||
|Pedro Frejo (Arpa System, https://arpasystem.com) |pedro.frejo at arpasystem.com
|
||||
|Ronny Chan |ronny at ronnychan.ca
|
||||
|Sam Kelly (DuroSoft Technologies LLC, https://durosoft.com) |sam at durosoft.com
|
||||
|Santiago Ganis |sganis at gmail.com
|
||||
|Tobias Urlaub |saibotu at outlook.de
|
||||
|
10
appveyor.yml
10
appveyor.yml
@ -17,19 +17,25 @@ environment:
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
CONFIGURATION: Debug
|
||||
TESTING: Func
|
||||
DOCKER_TESTING: None
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
CONFIGURATION: Release
|
||||
TESTING: Func
|
||||
DOCKER_TESTING: None
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
CONFIGURATION: Release
|
||||
TESTING: Func
|
||||
DOCKER_TESTING: None
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
CONFIGURATION: Release
|
||||
TESTING: Func
|
||||
DOCKER_TESTING: Func
|
||||
#- CONFIGURATION: Release
|
||||
# TESTING: Avast
|
||||
# DOCKER_TESTING: None
|
||||
#- CONFIGURATION: Release
|
||||
# TESTING: Perf
|
||||
# DOCKER_TESTING: None
|
||||
|
||||
init:
|
||||
- ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
@ -81,6 +87,7 @@ test_script:
|
||||
- if %TESTING%==Func start /wait msiexec /i "Test.Filter.Driver\HCK Filter.Driver Content-x86_en-us.msi" /qn
|
||||
- if %TESTING%==Func tools\nmake-ext-test.bat %CONFIGURATION%
|
||||
#- ps: . "C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\gflags.exe" /k +spp *
|
||||
- if %DOCKER_TESTING%==Func docker run -d --name=Container0 --isolation=process "-vC:\Program Files (x86)\WinFsp:C:\Program Files (x86)\WinFsp:RO" "-vC:\projects:C:\projects:RO" mcr.microsoft.com/windows/servercore:ltsc2019 cmd.exe /c waitfor 7BF47D72F6664550B03248ECFE77C7DD
|
||||
- if %TESTING%==Func tools\run-tests.bat %CONFIGURATION%
|
||||
- if %TESTING%==Func tools\run-tests.bat %CONFIGURATION% ifstest
|
||||
- if %TESTING%==Func tools\run-tests.bat %CONFIGURATION% sample
|
||||
@ -88,6 +95,9 @@ test_script:
|
||||
- if %TESTING%==Avast choco install avastfreeantivirus && fltmc instances -v "C:"
|
||||
- if %TESTING%==Avast tools\run-tests.bat %CONFIGURATION% avast-tests
|
||||
- if %TESTING%==Perf tools\run-perf-tests.bat %CONFIGURATION% baseline > perf-tests.csv && type perf-tests.csv & appveyor PushArtifact perf-tests.csv
|
||||
- if %DOCKER_TESTING%==Func docker exec Container0 cmd.exe /c C:\projects\winfsp\build\VStudio\build\%CONFIGURATION%\winfsp-tests-x64.exe +*
|
||||
#- if %DOCKER_TESTING%==Func docker run -d --name=Container1 --isolation=process "-vC:\Program Files (x86)\WinFsp:C:\Program Files (x86)\WinFsp:RO" "-vC:\projects:C:\projects:RO" mcr.microsoft.com/windows/servercore:ltsc2019 cmd.exe /c waitfor 7BF47D72F6664550B03248ECFE77C7DD
|
||||
#- if %DOCKER_TESTING%==Func docker exec Container1 cmd.exe /c C:\projects\winfsp\build\VStudio\build\%CONFIGURATION%\winfsp-tests-x64.exe +*
|
||||
- choco uninstall winfsp -y
|
||||
|
||||
on_finish:
|
||||
|
@ -3,10 +3,10 @@
|
||||
<Import Project="$(MsbuildThisFileDirectory)\build.version.props" />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>NTDDI_VERSION=0x06010000;_WIN32_WINNT=0x0601;MyProductName=$(MyProductName);MyProductFileName=$(MyProductFileName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas);MyFullVersion=$(MyFullVersion);MyFspFsctlDeviceClassGuid=$(MyFspFsctlDeviceClassGuid);MyFspFsvrtDeviceClassGuid=$(MyFspFsvrtDeviceClassGuid)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>NTDDI_VERSION=0x06010000;_WIN32_WINNT=0x0601;MyProductName=$(MyProductName);MyProductFileName=$(MyProductFileName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas);MyFullVersion=$(MyFullVersion);MyFspFsctlDeviceClassGuid=$(MyFspFsctlDeviceClassGuid);MyFspFsvrtDeviceClassGuid=$(MyFspFsvrtDeviceClassGuid);MyFsctlRegisterPath=$(MyFsctlRegisterPath);MyNpRegisterPath=$(MyNpRegisterPath);MyEventLogRegisterPath=$(MyEventLogRegisterPath)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>MyProductName=$(MyProductName);MyProductFileName=$(MyProductFileName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas);MyFullVersion=$(MyFullVersion);MyFspFsctlDeviceClassGuid=$(MyFspFsctlDeviceClassGuid);MyFspFsvrtDeviceClassGuid=$(MyFspFsvrtDeviceClassGuid)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>MyProductName=$(MyProductName);MyProductFileName=$(MyProductFileName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyProductVersion=$(MyProductVersion);MyProductStage=$(MyProductStage);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas);MyFullVersion=$(MyFullVersion);MyFspFsctlDeviceClassGuid=$(MyFspFsctlDeviceClassGuid);MyFspFsvrtDeviceClassGuid=$(MyFspFsvrtDeviceClassGuid);MyFsctlRegisterPath=$(MyFsctlRegisterPath);MyNpRegisterPath=$(MyNpRegisterPath);MyEventLogRegisterPath=$(MyEventLogRegisterPath)</PreprocessorDefinitions>
|
||||
</ResourceCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(IsKernelModeToolset)'=='true'">
|
||||
|
@ -18,12 +18,12 @@
|
||||
<MyCompanyName>Navimatics LLC</MyCompanyName>
|
||||
<MyCopyright>2015-$([System.DateTime]::Now.ToString(`yyyy`)) Bill Zissimopoulos</MyCopyright>
|
||||
|
||||
<MyCanonicalVersion>1.11</MyCanonicalVersion>
|
||||
<MyCanonicalVersion>2.0</MyCanonicalVersion>
|
||||
|
||||
<MyProductVersion>2022+ARM64</MyProductVersion>
|
||||
<MyProductStage>Gold</MyProductStage>
|
||||
<MyProductVersion>2023 Beta1</MyProductVersion>
|
||||
<MyProductStage>Beta</MyProductStage>
|
||||
|
||||
<MyCrossCert>DigiCert High Assurance EV Root CA.crt</MyCrossCert>
|
||||
<MyCrossCert>DigiCertGlobalG3CodeSigningECCSHA3842021CA1.cer</MyCrossCert>
|
||||
<MyCertIssuer>DigiCert</MyCertIssuer>
|
||||
|
||||
<MyVersion>$(MyCanonicalVersion).$(MyBuildNumber)</MyVersion>
|
||||
@ -40,5 +40,37 @@
|
||||
<!-- When rebranding WinFsp you MUST change the following GUIDs - use VS "Create GUID" tool -->
|
||||
<MyFspFsctlDeviceClassGuid>{ 0x6f9d25fa, 0x6dee, 0x4a9d, { 0x80, 0xf5, 0xe9, 0x8e, 0x14, 0xf3, 0x5e, 0x54 } }</MyFspFsctlDeviceClassGuid>
|
||||
<MyFspFsvrtDeviceClassGuid>{ 0xb48171c3, 0xdd50, 0x4852, { 0x83, 0xa3, 0x34, 0x4c, 0x50, 0xd9, 0x3b, 0x17 } }</MyFspFsvrtDeviceClassGuid>
|
||||
|
||||
<!--
|
||||
Configure paths used for registration via DllRegisterServer:
|
||||
|
||||
- MyFsctlRegisterPath: File System Driver registration path
|
||||
- MyNpRegisterPath: Network Provider registration path
|
||||
- MyEventLogRegisterPath: Event Log registration path
|
||||
|
||||
These paths are assumed to be relative to the location of the WinFsp DLL during
|
||||
registration: during DLLRegisterServer the DLL uses PathCombineW to combine its own
|
||||
location with these paths to produce the final locations to be used for registration.
|
||||
|
||||
For example, if the DLL location is `C:\Program Files (x86)\WinFsp\bin\winfsp-x64.dll`:
|
||||
|
||||
- Combining with the path "." will produce the original DLL location:
|
||||
`C:\Program Files (x86)\WinFsp\bin\winfsp-x64.dll`
|
||||
|
||||
- Combining with the path "..\\NetworkProvider.dll" will produce:
|
||||
`C:\Program Files (x86)\WinFsp\bin\NetworkProvider.dll`
|
||||
|
||||
- For Network Provider registrations only it is allowed to use environment variables
|
||||
in the path. For example combining the above DLL location with the path
|
||||
"..\\NetworkProvider-\x25PROCESSOR_ARCHITECTURE\x25.dll" will produce:
|
||||
`C:\Program Files (x86)\WinFsp\bin\NetworkProvider-%PROCESSOR_ARCHITECTURE%.dll`
|
||||
|
||||
(Note that the \x25 escape sequence must be used otherwise the VS build system will
|
||||
try to interpret the string %PROCESSOR_ARCHITECTURE% as an environment variable during
|
||||
the build.)
|
||||
-->
|
||||
<MyFsctlRegisterPath>"."</MyFsctlRegisterPath>
|
||||
<MyNpRegisterPath>"."</MyNpRegisterPath>
|
||||
<MyEventLogRegisterPath>"."</MyEventLogRegisterPath>
|
||||
</PropertyGroup>
|
||||
</Project>
|
@ -21,10 +21,55 @@
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <shellapi.h>
|
||||
#include <msiquery.h>
|
||||
#include <wcautil.h>
|
||||
#include <strutil.h>
|
||||
|
||||
static HINSTANCE DllInstance;
|
||||
|
||||
UINT __stdcall InstanceID(MSIHANDLE MsiHandle)
|
||||
{
|
||||
#if 0
|
||||
WCHAR MessageBuf[64];
|
||||
wsprintfW(MessageBuf, L"PID=%ld", GetCurrentProcessId());
|
||||
MessageBoxW(0, MessageBuf, L"" __FUNCTION__ " Break", MB_OK);
|
||||
#endif
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
UINT err = ERROR_SUCCESS;
|
||||
SYSTEMTIME SystemTime;
|
||||
WCHAR Result[32+1];
|
||||
|
||||
hr = WcaInitialize(MsiHandle, __FUNCTION__);
|
||||
ExitOnFailure(hr, "Failed to initialize");
|
||||
|
||||
WcaLog(LOGMSG_STANDARD, "Initialized");
|
||||
|
||||
GetSystemTime(&SystemTime);
|
||||
wsprintfW(Result, L"%04u%02u%02uT%02u%02u%02uZ",
|
||||
SystemTime.wYear,
|
||||
SystemTime.wMonth,
|
||||
SystemTime.wDay,
|
||||
SystemTime.wHour,
|
||||
SystemTime.wMinute,
|
||||
SystemTime.wSecond);
|
||||
|
||||
/*
|
||||
* Sleep 1 second to ensure timestamp uniqueness.
|
||||
*
|
||||
* Note that this assumes that time is monotonic and users do not change time.
|
||||
* Disable for now as it is assumed that the installation takes more than 1 second to complete.
|
||||
*/
|
||||
//Sleep(1000);
|
||||
|
||||
WcaSetProperty(L"" __FUNCTION__, Result);
|
||||
|
||||
LExit:
|
||||
err = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
|
||||
return WcaFinalize(err);
|
||||
}
|
||||
|
||||
UINT __stdcall ServiceRunning(MSIHANDLE MsiHandle)
|
||||
{
|
||||
#if 0
|
||||
@ -44,7 +89,7 @@ UINT __stdcall ServiceRunning(MSIHANDLE MsiHandle)
|
||||
hr = WcaInitialize(MsiHandle, __FUNCTION__);
|
||||
ExitOnFailure(hr, "Failed to initialize");
|
||||
|
||||
WcaGetProperty(L"" __FUNCTION__, &ServiceName);
|
||||
hr = WcaGetProperty(L"" __FUNCTION__, &ServiceName);
|
||||
ExitOnFailure(hr, "Failed to get ServiceName");
|
||||
|
||||
WcaLog(LOGMSG_STANDARD, "Initialized: \"%S\"", ServiceName);
|
||||
@ -70,12 +115,390 @@ LExit:
|
||||
return WcaFinalize(err);
|
||||
}
|
||||
|
||||
UINT __stdcall DeferredAction(MSIHANDLE MsiHandle)
|
||||
{
|
||||
#if 0
|
||||
WCHAR MessageBuf[64];
|
||||
wsprintfW(MessageBuf, L"PID=%ld", GetCurrentProcessId());
|
||||
MessageBoxW(0, MessageBuf, L"" __FUNCTION__ " Break", MB_OK);
|
||||
#endif
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
UINT err = ERROR_SUCCESS;
|
||||
PWSTR CommandLine = 0;
|
||||
PWSTR *Argv;
|
||||
int Argc;
|
||||
CHAR ProcName[64];
|
||||
FARPROC Proc;
|
||||
|
||||
hr = WcaInitialize(MsiHandle, __FUNCTION__);
|
||||
ExitOnFailure(hr, "Failed to initialize");
|
||||
|
||||
hr = WcaGetProperty(L"CustomActionData", &CommandLine);
|
||||
ExitOnFailure(hr, "Failed to get CommandLine");
|
||||
|
||||
WcaLog(LOGMSG_STANDARD, "Initialized: \"%S\"", CommandLine);
|
||||
|
||||
Argv = CommandLineToArgvW(CommandLine, &Argc);
|
||||
ExitOnNullWithLastError(Argv, hr, "Failed to CommandLineToArgvW");
|
||||
|
||||
if (0 < Argc)
|
||||
{
|
||||
if (0 == WideCharToMultiByte(CP_UTF8, 0, Argv[0], -1, ProcName, sizeof ProcName, 0, 0))
|
||||
ExitWithLastError(hr, "Failed to WideCharToMultiByte");
|
||||
|
||||
Proc = GetProcAddress(DllInstance, ProcName);
|
||||
ExitOnNullWithLastError(Proc, hr, "Failed to GetProcAddress");
|
||||
|
||||
err = ((HRESULT (*)(int, PWSTR *))Proc)(Argc, Argv);
|
||||
ExitOnWin32Error(err, hr, "Failed to %s", ProcName);
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = E_INVALIDARG;
|
||||
ExitOnFailure(hr, "Failed to get arguments");
|
||||
}
|
||||
|
||||
LExit:
|
||||
LocalFree(Argv);
|
||||
ReleaseStr(CommandLine);
|
||||
|
||||
err = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
|
||||
return WcaFinalize(err);
|
||||
}
|
||||
|
||||
static DWORD MakeSymlink(PWSTR Symlink, PWSTR Target);
|
||||
static DWORD MakeJunction(PWSTR Junction, PWSTR Target);
|
||||
static DWORD CreateJunction(PWSTR Junction, PWSTR Target);
|
||||
static DWORD RemoveFile(PWSTR FileName);
|
||||
|
||||
DWORD InstallSymlinks(int Argc, PWSTR *Argv)
|
||||
{
|
||||
/* usage: InstallSymlinks/InstallJunctions SourceDir TargetDir Name... */
|
||||
|
||||
DWORD Result;
|
||||
BOOL Junctions;
|
||||
PWSTR SourceDir, TargetDir;
|
||||
WCHAR SourcePath[MAX_PATH], TargetPath[MAX_PATH];
|
||||
int SourceDirLen, TargetDirLen, Len;
|
||||
|
||||
if (4 > Argc)
|
||||
{
|
||||
Result = ERROR_INVALID_PARAMETER;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Junctions = 0 == lstrcmpW(L"InstallJunctions", Argv[0]);
|
||||
SourceDir = Argv[1];
|
||||
TargetDir = Argv[2];
|
||||
SourceDirLen = lstrlenW(SourceDir);
|
||||
TargetDirLen = lstrlenW(TargetDir);
|
||||
|
||||
for (int Argi = 3; Argc > Argi; Argi++)
|
||||
{
|
||||
Len = lstrlenW(Argv[Argi]);
|
||||
if (MAX_PATH < SourceDirLen + Len + 1 || MAX_PATH < TargetDirLen + Len + 1)
|
||||
{
|
||||
Result = ERROR_FILENAME_EXCED_RANGE;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
memcpy(SourcePath, SourceDir, SourceDirLen * sizeof(WCHAR));
|
||||
memcpy(SourcePath + SourceDirLen, Argv[Argi], Len * sizeof(WCHAR));
|
||||
SourcePath[SourceDirLen + Len] = L'\0';
|
||||
|
||||
memcpy(TargetPath, TargetDir, TargetDirLen * sizeof(WCHAR));
|
||||
memcpy(TargetPath + TargetDirLen, Argv[Argi], Len * sizeof(WCHAR));
|
||||
TargetPath[TargetDirLen + Len] = L'\0';
|
||||
|
||||
if (!Junctions)
|
||||
Result = MakeSymlink(SourcePath, TargetPath);
|
||||
else
|
||||
Result = MakeJunction(SourcePath, TargetPath);
|
||||
#if 0
|
||||
WCHAR MessageBuf[1024];
|
||||
wsprintfW(MessageBuf, L"MakeSymlink(\"%s\", \"%s\") = %lu", SourcePath, TargetPath, Result);
|
||||
MessageBoxW(0, MessageBuf, L"TRACE", MB_OK);
|
||||
#endif
|
||||
if (ERROR_SUCCESS != Result)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Result = ERROR_SUCCESS;
|
||||
|
||||
exit:
|
||||
return Result;
|
||||
}
|
||||
|
||||
DWORD InstallJunctions(int Argc, PWSTR *Argv)
|
||||
{
|
||||
return InstallSymlinks(Argc, Argv);
|
||||
}
|
||||
|
||||
DWORD RemoveFiles(int Argc, PWSTR *Argv)
|
||||
{
|
||||
/* usage: RemoveFiles Dir Name... */
|
||||
|
||||
DWORD Result;
|
||||
PWSTR Dir;
|
||||
WCHAR Path[MAX_PATH];
|
||||
int DirLen, Len;
|
||||
|
||||
if (3 > Argc)
|
||||
{
|
||||
Result = ERROR_INVALID_PARAMETER;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Dir = Argv[1];
|
||||
DirLen = lstrlenW(Dir);
|
||||
|
||||
for (int Argi = 2; Argc > Argi; Argi++)
|
||||
{
|
||||
Len = lstrlenW(Argv[Argi]);
|
||||
if (MAX_PATH < DirLen + Len + 1)
|
||||
{
|
||||
Result = ERROR_FILENAME_EXCED_RANGE;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
memcpy(Path, Dir, DirLen * sizeof(WCHAR));
|
||||
memcpy(Path + DirLen, Argv[Argi], Len * sizeof(WCHAR));
|
||||
Path[DirLen + Len] = L'\0';
|
||||
|
||||
Result = RemoveFile(Path);
|
||||
#if 0
|
||||
WCHAR MessageBuf[1024];
|
||||
wsprintfW(MessageBuf, L"RemoveFile(\"%s\") = %lu", Path, Result);
|
||||
MessageBoxW(0, MessageBuf, L"TRACE", MB_OK);
|
||||
#endif
|
||||
if (ERROR_SUCCESS != Result)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Result = ERROR_SUCCESS;
|
||||
|
||||
exit:
|
||||
return Result;
|
||||
}
|
||||
|
||||
static DWORD MakeSymlink(PWSTR Symlink, PWSTR Target)
|
||||
{
|
||||
DWORD Result;
|
||||
DWORD FileAttributes, Flags;
|
||||
|
||||
RemoveFile(Symlink);
|
||||
|
||||
FileAttributes = GetFileAttributesW(Target);
|
||||
if (INVALID_FILE_ATTRIBUTES == FileAttributes)
|
||||
{
|
||||
Result = GetLastError();
|
||||
goto exit;
|
||||
}
|
||||
Flags = 0 != (FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0;
|
||||
|
||||
if (!CreateSymbolicLinkW(Symlink, Target, Flags))
|
||||
{
|
||||
Result = GetLastError();
|
||||
RemoveFile(Symlink);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Result = ERROR_SUCCESS;
|
||||
|
||||
exit:
|
||||
return Result;
|
||||
}
|
||||
|
||||
static DWORD MakeJunction(PWSTR Junction, PWSTR Target)
|
||||
{
|
||||
DWORD Result;
|
||||
DWORD FileAttributes;
|
||||
|
||||
RemoveFile(Junction);
|
||||
|
||||
FileAttributes = GetFileAttributesW(Target);
|
||||
if (INVALID_FILE_ATTRIBUTES == FileAttributes)
|
||||
{
|
||||
Result = GetLastError();
|
||||
goto exit;
|
||||
}
|
||||
if (0 == (FileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
||||
{
|
||||
Result = ERROR_DIRECTORY;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Result = CreateJunction(Junction, Target);
|
||||
if (ERROR_SUCCESS != Result)
|
||||
{
|
||||
RemoveFile(Junction);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Result = ERROR_SUCCESS;
|
||||
|
||||
exit:
|
||||
return Result;
|
||||
}
|
||||
|
||||
static DWORD CreateJunction(PWSTR Junction, PWSTR Target)
|
||||
{
|
||||
/*
|
||||
* The REPARSE_DATA_BUFFER definitions appear to be missing from the user mode headers.
|
||||
*/
|
||||
typedef struct _REPARSE_DATA_BUFFER
|
||||
{
|
||||
ULONG ReparseTag;
|
||||
USHORT ReparseDataLength;
|
||||
USHORT Reserved;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
USHORT SubstituteNameOffset;
|
||||
USHORT SubstituteNameLength;
|
||||
USHORT PrintNameOffset;
|
||||
USHORT PrintNameLength;
|
||||
ULONG Flags;
|
||||
WCHAR PathBuffer[1];
|
||||
} SymbolicLinkReparseBuffer;
|
||||
struct
|
||||
{
|
||||
USHORT SubstituteNameOffset;
|
||||
USHORT SubstituteNameLength;
|
||||
USHORT PrintNameOffset;
|
||||
USHORT PrintNameLength;
|
||||
WCHAR PathBuffer[1];
|
||||
} MountPointReparseBuffer;
|
||||
struct
|
||||
{
|
||||
UCHAR DataBuffer[1];
|
||||
} GenericReparseBuffer;
|
||||
} DUMMYUNIONNAME;
|
||||
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
|
||||
const LONG REPARSE_DATA_BUFFER_HEADER_SIZE =
|
||||
FIELD_OFFSET(REPARSE_DATA_BUFFER, GenericReparseBuffer);
|
||||
const DWORD FSCTL_SET_REPARSE_POINT = 0x000900a4;
|
||||
|
||||
DWORD Result;
|
||||
HANDLE Handle = INVALID_HANDLE_VALUE;
|
||||
USHORT TargetLength, ReparseDataLength;
|
||||
PREPARSE_DATA_BUFFER ReparseData = 0;
|
||||
PWSTR PathBuffer;
|
||||
DWORD Bytes;
|
||||
|
||||
if (!(
|
||||
((L'A' <= Target[0] && Target[0] <= L'Z') || (L'a' <= Target[0] && Target[0] <= L'z')) &&
|
||||
L':' == Target[1]
|
||||
))
|
||||
{
|
||||
Result = ERROR_INVALID_NAME;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Handle = CreateFileW(Junction,
|
||||
FILE_WRITE_ATTRIBUTES,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
0,
|
||||
CREATE_NEW,
|
||||
FILE_ATTRIBUTE_DIRECTORY |
|
||||
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS,
|
||||
0);
|
||||
if (INVALID_HANDLE_VALUE == Handle)
|
||||
{
|
||||
Result = GetLastError();
|
||||
goto exit;
|
||||
}
|
||||
|
||||
TargetLength = (USHORT)lstrlenW(Target) * sizeof(WCHAR);
|
||||
ReparseDataLength = (USHORT)(
|
||||
FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer) -
|
||||
FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer)) +
|
||||
4 * sizeof(WCHAR) + 2 * (TargetLength + sizeof(WCHAR));
|
||||
ReparseData = (PREPARSE_DATA_BUFFER)
|
||||
HeapAlloc(GetProcessHeap(), 0, REPARSE_DATA_BUFFER_HEADER_SIZE + ReparseDataLength);
|
||||
if (0 == ReparseData)
|
||||
{
|
||||
Result = ERROR_NO_SYSTEM_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ReparseData->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
|
||||
ReparseData->ReparseDataLength = ReparseDataLength;
|
||||
ReparseData->Reserved = 0;
|
||||
ReparseData->MountPointReparseBuffer.SubstituteNameOffset = 0;
|
||||
ReparseData->MountPointReparseBuffer.SubstituteNameLength =
|
||||
4 * sizeof(WCHAR) + TargetLength;
|
||||
ReparseData->MountPointReparseBuffer.PrintNameOffset =
|
||||
ReparseData->MountPointReparseBuffer.SubstituteNameLength + sizeof(WCHAR);
|
||||
ReparseData->MountPointReparseBuffer.PrintNameLength =
|
||||
TargetLength;
|
||||
|
||||
PathBuffer = ReparseData->MountPointReparseBuffer.PathBuffer;
|
||||
PathBuffer[0] = L'\\';
|
||||
PathBuffer[1] = L'?';
|
||||
PathBuffer[2] = L'?';
|
||||
PathBuffer[3] = L'\\';
|
||||
memcpy(PathBuffer + 4, Target, TargetLength);
|
||||
PathBuffer[4 + TargetLength / sizeof(WCHAR)] = L'\0';
|
||||
|
||||
PathBuffer = ReparseData->MountPointReparseBuffer.PathBuffer +
|
||||
(ReparseData->MountPointReparseBuffer.PrintNameOffset) / sizeof(WCHAR);
|
||||
memcpy(PathBuffer, Target, TargetLength);
|
||||
PathBuffer[TargetLength / sizeof(WCHAR)] = L'\0';
|
||||
|
||||
if (!DeviceIoControl(Handle, FSCTL_SET_REPARSE_POINT,
|
||||
ReparseData, REPARSE_DATA_BUFFER_HEADER_SIZE + ReparseData->ReparseDataLength,
|
||||
0, 0,
|
||||
&Bytes, 0))
|
||||
{
|
||||
Result = GetLastError();
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Result = ERROR_SUCCESS;
|
||||
|
||||
exit:
|
||||
if (INVALID_HANDLE_VALUE != Handle)
|
||||
CloseHandle(Handle);
|
||||
|
||||
if (0 != ReparseData)
|
||||
HeapFree(GetProcessHeap(), 0, ReparseData);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
static DWORD RemoveFile(PWSTR FileName)
|
||||
{
|
||||
DWORD Result;
|
||||
|
||||
if (!RemoveDirectoryW(FileName))
|
||||
{
|
||||
Result = GetLastError();
|
||||
if (ERROR_DIRECTORY != Result)
|
||||
goto exit;
|
||||
|
||||
if (!DeleteFileW(FileName))
|
||||
{
|
||||
Result = GetLastError();
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
Result = ERROR_SUCCESS;
|
||||
|
||||
exit:
|
||||
return Result;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
BOOL WINAPI DllMain(HINSTANCE Instance, DWORD Reason, PVOID Reserved)
|
||||
{
|
||||
switch(Reason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
DllInstance = Instance;
|
||||
WcaGlobalInitialize(Instance);
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
|
@ -1,2 +1,7 @@
|
||||
EXPORTS
|
||||
InstanceID
|
||||
ServiceRunning
|
||||
DeferredAction
|
||||
InstallSymlinks
|
||||
InstallJunctions
|
||||
RemoveFiles
|
||||
|
@ -1,4 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!-- The UpgradeCode of the old WinFsp installer that did not support upgrades. -->
|
||||
<?define OldVersionUpgradeCode="82F812D9-4083-4EF1-8BC8-0F1EDA05B46B"?>
|
||||
|
||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
|
||||
xmlns:dep="http://schemas.microsoft.com/wix/DependencyExtension">
|
||||
<Product
|
||||
@ -7,7 +11,7 @@
|
||||
Manufacturer="$(var.MyCompanyName)"
|
||||
Version="$(var.MyVersion)"
|
||||
Language="1033"
|
||||
UpgradeCode="82F812D9-4083-4EF1-8BC8-0F1EDA05B46B">
|
||||
UpgradeCode="5466A3D8-3AA1-4240-B6A0-3A051940A3EC">
|
||||
|
||||
<Package
|
||||
Description="$(var.MyProductName) - $(var.MyDescription)"
|
||||
@ -15,13 +19,26 @@
|
||||
Compressed="yes"
|
||||
InstallScope="perMachine" />
|
||||
<MajorUpgrade
|
||||
Disallow="yes"
|
||||
Disallow="no"
|
||||
AllowDowngrades="no"
|
||||
AllowSameVersionUpgrades="no"
|
||||
DisallowUpgradeErrorMessage="An older version of $(var.MyProductName) is already installed. You must uninstall it before you can install this version."
|
||||
AllowSameVersionUpgrades="yes"
|
||||
DowngradeErrorMessage="A newer version of $(var.MyProductName) is already installed." />
|
||||
<Media Id="1" Cabinet="$(var.MyProductName).cab" EmbedCab="yes" />
|
||||
|
||||
<!-- Determine if we are on Win7 or above. -->
|
||||
<Condition Message="$(var.MyProductName) requires Windows version 7 or higher in order to be installed.">
|
||||
<![CDATA[Installed OR (VersionNT >= 601)]]>
|
||||
</Condition>
|
||||
|
||||
<!-- Determine if the old WinFsp installer that did not support upgrades is installed. -->
|
||||
<Property Id="OLDVERSIONINSTALLED">
|
||||
<ProductSearch UpgradeCode="$(var.OldVersionUpgradeCode)" Minimum="0.0.0.0" />
|
||||
</Property>
|
||||
<Condition Message="An older version of $(var.MyProductName) that cannot be upgraded is already installed. You must uninstall it before you can install this version.">
|
||||
NOT OLDVERSIONINSTALLED
|
||||
</Condition>
|
||||
|
||||
<!-- Determine OS architecture. -->
|
||||
<Property Id="OSARCH" Secure="yes" Value="AMD64">
|
||||
<RegistrySearch
|
||||
Id="R.OSARCH"
|
||||
@ -31,10 +48,10 @@
|
||||
Type="raw" />
|
||||
</Property>
|
||||
|
||||
<Property Id="P.LauncherName">$(var.MyProductName).Launcher</Property>
|
||||
<Property Id="P.LauncherRegistryKey">Software\$(var.MyProductName)\Services</Property>
|
||||
<!-- Setup INSTALLDIR and SXSDIR from the registry or defaults. -->
|
||||
<Property Id="P.RegistryKey">Software\$(var.MyProductName)</Property>
|
||||
<Property Id="INSTALLDIR">
|
||||
<Property Id="P.LauncherRegistryKey">Software\$(var.MyProductName)\Services</Property>
|
||||
<Property Id="INSTALLDIR" Secure="yes">
|
||||
<RegistrySearch
|
||||
Id="R.INSTALLDIR"
|
||||
Root="HKLM"
|
||||
@ -42,22 +59,40 @@
|
||||
Name="InstallDir"
|
||||
Type="raw" />
|
||||
</Property>
|
||||
<Property Id="SXSDIR" Secure="yes">
|
||||
<RegistrySearch
|
||||
Id="R.SXSDIR"
|
||||
Root="HKLM"
|
||||
Key="[P.RegistryKey]"
|
||||
Name="SxsDir"
|
||||
Type="raw" />
|
||||
</Property>
|
||||
<SetProperty Id="INSTALLDIR" Value="[ProgramFilesFolder]$(var.MyProductName)\" After="CostInitialize">
|
||||
NOT INSTALLDIR
|
||||
</SetProperty>
|
||||
<SetProperty Id="SXSDIR" Value="[INSTALLDIR]SxS\sxs.[InstanceID]\" After="SetINSTALLDIR">
|
||||
((NOT SXSDIR) OR WIX_UPGRADE_DETECTED) AND InstanceID
|
||||
</SetProperty>
|
||||
|
||||
<!-- Setup directory structure. -->
|
||||
<Directory Id="TARGETDIR" Name="SourceDir">
|
||||
<Directory Id="ProgramFilesFolder">
|
||||
<Directory Id="INSTALLDIR" Name="$(var.MyProductName)">
|
||||
<Directory Id="INSTALLDIR" Name="DYNAMIC">
|
||||
<Directory Id="SXSBASEDIR" Name="SxS">
|
||||
<Directory Id="SXSDIR" Name="DYNAMIC">
|
||||
<Directory Id="BINDIR" Name="bin" />
|
||||
</Directory>
|
||||
</Directory>
|
||||
<Directory Id="INCDIR" Name="inc" />
|
||||
<Directory Id="LIBDIR" Name="lib" />
|
||||
<Directory Id="OPTDIR" Name="opt" />
|
||||
<Directory Id="SMPDIR" Name="samples" />
|
||||
<Directory Id="SYMDIR" Name="sym" />
|
||||
</Directory>
|
||||
</Directory>
|
||||
</Directory>
|
||||
|
||||
<DirectoryRef Id="INSTALLDIR">
|
||||
<Component Id="C.INSTALLDIR" Guid="{F876F26E-5016-4AC6-93B3-653C0312A6CE}">
|
||||
<Component Id="C.INSTALLDIR" Guid="C086521F-8552-43D1-AAE2-CDD579F66FDD">
|
||||
<RegistryValue
|
||||
Root="HKLM"
|
||||
Key="[P.RegistryKey]"
|
||||
@ -70,6 +105,17 @@
|
||||
<File Name="License.txt" Source="..\..\..\License.txt" KeyPath="yes" />
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
<DirectoryRef Id="SXSDIR">
|
||||
<Component Id="C.SXSDIR" Guid="0F09CD39-1137-4DB8-A783-27B1F51353D1">
|
||||
<RegistryValue
|
||||
Root="HKLM"
|
||||
Key="[P.RegistryKey]"
|
||||
Name="SxsDir"
|
||||
Type="string"
|
||||
Value="[SXSDIR]"
|
||||
KeyPath="yes" />
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
<DirectoryRef Id="BINDIR" FileSource="..\build\$(var.Configuration)">
|
||||
<Component Id="C.$(var.MyProductFileName)_a64.sys">
|
||||
<File Name="$(var.MyProductFileName)-a64.sys" KeyPath="yes" />
|
||||
@ -82,56 +128,56 @@
|
||||
</Component>
|
||||
|
||||
<!-- On WinArm64 register $(var.MyProductFileName)-a64.dll -->
|
||||
<Component Id="C.$(var.MyProductFileName)_a64.dll.a64" Guid="86FB483B-0910-458E-93B4-3CCB66D27AF0">
|
||||
<Component Id="C.$(var.MyProductFileName)_a64.dll.a64" Guid="2A7E68EB-D05F-4DD8-ABF2-EB8CB09697F0">
|
||||
<File Id="FILE.$(var.MyProductFileName)_a64.dll.a64" Name="$(var.MyProductFileName)-a64.dll" KeyPath="yes" SelfRegCost="1" />
|
||||
<Condition><![CDATA[OSARCH = "ARM64"]]></Condition>
|
||||
</Component>
|
||||
<Component Id="C.$(var.MyProductFileName)_x64.dll.a64" Guid="941FAE3E-A650-4BAC-97F5-F8C6E98DB5D2">
|
||||
<Component Id="C.$(var.MyProductFileName)_x64.dll.a64" Guid="EA5ED4FB-FC72-4D27-9802-88D84DAE61B4">
|
||||
<File Id="FILE.$(var.MyProductFileName)_x64.dll.a64" Name="$(var.MyProductFileName)-x64.dll" KeyPath="yes" />
|
||||
<Condition><![CDATA[OSARCH = "ARM64"]]></Condition>
|
||||
</Component>
|
||||
<Component Id="C.$(var.MyProductFileName)_x86.dll.a64" Guid="C312214D-F9A3-40EB-B2C3-4FAF5BF3F938">
|
||||
<Component Id="C.$(var.MyProductFileName)_x86.dll.a64" Guid="2A9BD712-2F96-4794-8A58-929E39F3F3CC">
|
||||
<File Id="FILE.$(var.MyProductFileName)_x86.dll.a64" Name="$(var.MyProductFileName)-x86.dll" KeyPath="yes" />
|
||||
<Condition><![CDATA[OSARCH = "ARM64"]]></Condition>
|
||||
</Component>
|
||||
|
||||
<!-- On Win64 register $(var.MyProductFileName)-x64.dll -->
|
||||
<Component Id="C.$(var.MyProductFileName)_a64.dll.x64" Guid="4ABB46C2-A8E3-49E8-B051-05DBF2B351AE">
|
||||
<Component Id="C.$(var.MyProductFileName)_a64.dll.x64" Guid="026DA201-43E1-450C-9687-8A684FBF2D2D">
|
||||
<File Id="FILE.$(var.MyProductFileName)_a64.dll.x64" Name="$(var.MyProductFileName)-a64.dll" KeyPath="yes" />
|
||||
<Condition><![CDATA[OSARCH = "AMD64"]]></Condition>
|
||||
</Component>
|
||||
<Component Id="C.$(var.MyProductFileName)_x64.dll.x64" Guid="F0A67746-1A9C-4976-8EC0-882E9407FA6D">
|
||||
<Component Id="C.$(var.MyProductFileName)_x64.dll.x64" Guid="89201BAF-5812-4ECE-91CD-12EDFFF11CB1">
|
||||
<File Id="FILE.$(var.MyProductFileName)_x64.dll.x64" Name="$(var.MyProductFileName)-x64.dll" KeyPath="yes" SelfRegCost="1" />
|
||||
<Condition><![CDATA[OSARCH = "AMD64"]]></Condition>
|
||||
</Component>
|
||||
<Component Id="C.$(var.MyProductFileName)_x86.dll.x64" Guid="950492FB-12F7-4E27-9124-8325A2BC9927">
|
||||
<Component Id="C.$(var.MyProductFileName)_x86.dll.x64" Guid="E6EE48A4-6BC7-4135-9A2F-FBBA30DE80BE">
|
||||
<File Id="FILE.$(var.MyProductFileName)_x86.dll.x64" Name="$(var.MyProductFileName)-x86.dll" KeyPath="yes" />
|
||||
<Condition><![CDATA[OSARCH = "AMD64"]]></Condition>
|
||||
</Component>
|
||||
|
||||
<!-- On Win32 register $(var.MyProductFileName)-x86.dll -->
|
||||
<Component Id="C.$(var.MyProductFileName)_a64.dll.x86" Guid="071C0EB2-A0EB-46A1-B5B0-124F60ECD6B3">
|
||||
<Component Id="C.$(var.MyProductFileName)_a64.dll.x86" Guid="2B264958-DECC-4B32-9BB2-DE32D6B6BE77">
|
||||
<File Id="FILE.$(var.MyProductFileName)_a64.dll.x86" Name="$(var.MyProductFileName)-a64.dll" KeyPath="yes" />
|
||||
<Condition><![CDATA[OSARCH = "x86"]]></Condition>
|
||||
</Component>
|
||||
<Component Id="C.$(var.MyProductFileName)_x64.dll.x86" Guid="4D6E7A8E-0CA6-49BE-B312-1EDADE725756">
|
||||
<Component Id="C.$(var.MyProductFileName)_x64.dll.x86" Guid="29FB908F-1D36-4789-9778-4CE2E9C19CEA">
|
||||
<File Id="FILE.$(var.MyProductFileName)_x64.dll.x86" Name="$(var.MyProductFileName)-x64.dll" KeyPath="yes" />
|
||||
<Condition><![CDATA[OSARCH = "x86"]]></Condition>
|
||||
</Component>
|
||||
<Component Id="C.$(var.MyProductFileName)_x86.dll.x86" Guid="F0DEF7A6-AF55-419F-A58A-DF4018C6FA73">
|
||||
<Component Id="C.$(var.MyProductFileName)_x86.dll.x86" Guid="80E87D91-69A8-4942-ABC1-36652B1CA700">
|
||||
<File Id="FILE.$(var.MyProductFileName)_x86.dll.x86" Name="$(var.MyProductFileName)-x86.dll" KeyPath="yes" SelfRegCost="1" />
|
||||
<Condition><![CDATA[OSARCH = "x86"]]></Condition>
|
||||
</Component>
|
||||
|
||||
<!-- install assembly -->
|
||||
<Component Id="C.$(var.MyProductFileName)_msil.dll" Guid="0D8BA6AE-9F87-402B-AE1A-95B0AE3BE179">
|
||||
<Component Id="C.$(var.MyProductFileName)_msil.dll" Guid="1772CDE5-4B2F-48CF-B2DA-CA43818053A8">
|
||||
<File Id="FILE.$(var.MyProductFileName)_msil.dll" Name="$(var.MyProductFileName)-msil.dll" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.$(var.MyProductFileName)_msil.xml" Guid="1657F707-C112-454C-91AE-0FDEBBF454AB">
|
||||
<Component Id="C.$(var.MyProductFileName)_msil.xml" Guid="C76745D2-51FA-4028-B827-3F2F3F763751">
|
||||
<File Id="FILE.$(var.MyProductFileName)_msil.xml" Name="$(var.MyProductFileName)-msil.xml" KeyPath="yes" />
|
||||
</Component>
|
||||
<!--
|
||||
<Component Id="C.$(var.MyProductFileName)_msil.dll.GAC" Guid="6469467D-8C90-4889-8138-4028F9DA6E85">
|
||||
<Component Id="C.$(var.MyProductFileName)_msil.dll.GAC" Guid="D86F8764-2FCC-43DA-A174-23E0FD6D45B7">
|
||||
<File Id="FILE.$(var.MyProductFileName)_msil.dll.GAC" Name="$(var.MyProductFileName)-msil.dll" KeyPath="yes" Assembly=".net" />
|
||||
</Component>
|
||||
<Component Id="C.policy.$(var.MyProductFileName)_msil.dll.GAC">
|
||||
@ -141,103 +187,103 @@
|
||||
-->
|
||||
|
||||
<!-- On WinArm64 ServiceInstall launcher-a64.exe -->
|
||||
<Component Id="C.launcher_a64.exe.a64" Guid="E37E6D75-C44B-4189-8E86-CE5A3E0B0626">
|
||||
<Component Id="C.launcher_a64.exe.a64" Guid="D8B657EA-7B08-48D1-B5F7-76CFB68E1BD5">
|
||||
<File Id="FILE.launcher_a64.exe.a64" Name="launcher-a64.exe" KeyPath="yes" />
|
||||
<ServiceInstall
|
||||
Id="launcher_a64.exe.a64"
|
||||
Name="[P.LauncherName]"
|
||||
Name="$(var.MyProductName).Launcher"
|
||||
Description="$(var.MyDescription)"
|
||||
Type="ownProcess"
|
||||
Start="auto"
|
||||
ErrorControl="ignore" />
|
||||
<ServiceControl
|
||||
Id="launcher_a64.exe.a64"
|
||||
Name="[P.LauncherName]"
|
||||
Name="$(var.MyProductName).Launcher"
|
||||
Start="install"
|
||||
Stop="both"
|
||||
Remove="uninstall" />
|
||||
<Condition><![CDATA[OSARCH = "ARM64"]]></Condition>
|
||||
</Component>
|
||||
<Component Id="C.launcher_x64.exe.a64" Guid="CF5F3EEE-F739-4F50-9938-13C0D2CD9C7A">
|
||||
<Component Id="C.launcher_x64.exe.a64" Guid="3EFC0561-6EA2-4E7E-B707-C2EA706CFBA0">
|
||||
<File Id="FILE.launcher_x64.exe.a64" Name="launcher-x64.exe" KeyPath="yes" />
|
||||
<Condition><![CDATA[OSARCH = "ARM64"]]></Condition>
|
||||
</Component>
|
||||
<Component Id="C.launcher_x86.exe.a64" Guid="D5E9FF96-9E00-46BA-8719-BC49CF35BBE6">
|
||||
<Component Id="C.launcher_x86.exe.a64" Guid="69F16682-10AE-4FC4-9007-8D80CE0D8388">
|
||||
<File Id="FILE.launcher_x86.exe.a64" Name="launcher-x86.exe" KeyPath="yes" />
|
||||
<Condition><![CDATA[OSARCH = "ARM64"]]></Condition>
|
||||
</Component>
|
||||
|
||||
<!-- On Win64 ServiceInstall launcher-x64.exe -->
|
||||
<Component Id="C.launcher_a64.exe.x64" Guid="10A3F0F9-6555-4071-9C93-EA50E4B3F115">
|
||||
<Component Id="C.launcher_a64.exe.x64" Guid="29760ACE-69CD-4061-8C0C-8A6E72D23A45">
|
||||
<File Id="FILE.launcher_a64.exe.x64" Name="launcher-a64.exe" KeyPath="yes" />
|
||||
<Condition><![CDATA[OSARCH = "AMD64"]]></Condition>
|
||||
</Component>
|
||||
<Component Id="C.launcher_x64.exe.x64" Guid="2AB4E729-F7CB-4B4A-BE81-6C0C3B3194FC">
|
||||
<Component Id="C.launcher_x64.exe.x64" Guid="36ACBA60-1C92-4D2A-B497-CD4FB13A042F">
|
||||
<File Id="FILE.launcher_x64.exe.x64" Name="launcher-x64.exe" KeyPath="yes" />
|
||||
<ServiceInstall
|
||||
Id="launcher_x64.exe.x64"
|
||||
Name="[P.LauncherName]"
|
||||
Name="$(var.MyProductName).Launcher"
|
||||
Description="$(var.MyDescription)"
|
||||
Type="ownProcess"
|
||||
Start="auto"
|
||||
ErrorControl="ignore" />
|
||||
<ServiceControl
|
||||
Id="launcher_x64.exe.x64"
|
||||
Name="[P.LauncherName]"
|
||||
Name="$(var.MyProductName).Launcher"
|
||||
Start="install"
|
||||
Stop="both"
|
||||
Remove="uninstall" />
|
||||
<Condition><![CDATA[OSARCH = "AMD64"]]></Condition>
|
||||
</Component>
|
||||
<Component Id="C.launcher_x86.exe.x64" Guid="C5B6D411-8A6A-4944-8C4F-7D9FB9A72826">
|
||||
<Component Id="C.launcher_x86.exe.x64" Guid="98F17F67-AC1D-4E16-A147-B7AE113E3CB3">
|
||||
<File Id="FILE.launcher_x86.exe.x64" Name="launcher-x86.exe" KeyPath="yes" />
|
||||
<Condition><![CDATA[OSARCH = "AMD64"]]></Condition>
|
||||
</Component>
|
||||
|
||||
<!-- On Win32 ServiceInstall launcher-x86.exe -->
|
||||
<Component Id="C.launcher_a64.exe.x86" Guid="5048AEF5-9DE2-406E-A2EA-F237BAD13286">
|
||||
<Component Id="C.launcher_a64.exe.x86" Guid="9024A9FE-7445-4241-ADA3-82A57C92719A">
|
||||
<File Id="FILE.launcher_a64.exe.x86" Name="launcher-a64.exe" KeyPath="yes" />
|
||||
<Condition><![CDATA[OSARCH = "x86"]]></Condition>
|
||||
</Component>
|
||||
<Component Id="C.launcher_x64.exe.x86" Guid="88CDBE92-8B67-485A-838F-FA4AD37F306F">
|
||||
<Component Id="C.launcher_x64.exe.x86" Guid="A85DA9CD-26AA-460E-950D-CA9692B87465">
|
||||
<File Id="FILE.launcher_x64.exe.x86" Name="launcher-x64.exe" KeyPath="yes" />
|
||||
<Condition><![CDATA[OSARCH = "x86"]]></Condition>
|
||||
</Component>
|
||||
<Component Id="C.launcher_x86.exe.x86" Guid="E995D906-0273-4758-9B26-99A3A8CD143A">
|
||||
<Component Id="C.launcher_x86.exe.x86" Guid="01FCCF6B-9F4B-4F29-8149-489470FFD449">
|
||||
<File Id="FILE.launcher_x86.exe.x86" Name="launcher-x86.exe" KeyPath="yes" />
|
||||
<ServiceInstall
|
||||
Id="launcher_x86.exe.x86"
|
||||
Name="[P.LauncherName]"
|
||||
Name="$(var.MyProductName).Launcher"
|
||||
Description="$(var.MyDescription)"
|
||||
Type="ownProcess"
|
||||
Start="auto"
|
||||
ErrorControl="ignore" />
|
||||
<ServiceControl
|
||||
Id="launcher_x86.exe.x86"
|
||||
Name="[P.LauncherName]"
|
||||
Name="$(var.MyProductName).Launcher"
|
||||
Start="install"
|
||||
Stop="both"
|
||||
Remove="uninstall" />
|
||||
<Condition><![CDATA[OSARCH = "x86"]]></Condition>
|
||||
</Component>
|
||||
|
||||
<Component Id="C.launchctl_a64.exe" Guid="B9B5CF8E-317D-40EE-A208-BC46A2A99BAB">
|
||||
<Component Id="C.launchctl_a64.exe" Guid="A7D830DD-20D2-48BF-85B6-E306BCCAFD2D">
|
||||
<File Name="launchctl-a64.exe" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.launchctl_x64.exe" Guid="2753623B-66F1-4514-B9C7-F879178DFF49">
|
||||
<Component Id="C.launchctl_x64.exe" Guid="CCC8974A-4CD0-443E-840D-1C92535BBD04">
|
||||
<File Name="launchctl-x64.exe" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.launchctl_x86.exe" Guid="EBDEC4FB-07BB-47CA-BFFF-EB854CA2D22D">
|
||||
<Component Id="C.launchctl_x86.exe" Guid="6E382342-10D4-4274-8FA9-F1B44C40C277">
|
||||
<File Name="launchctl-x86.exe" KeyPath="yes" />
|
||||
</Component>
|
||||
|
||||
<Component Id="C.fsptool_a64.exe" Guid="F75A8B14-000C-4933-AD83-EC0D1D3AD3CA">
|
||||
<Component Id="C.fsptool_a64.exe" Guid="8ACEB970-CAD5-491D-8CE8-12675CC0E812">
|
||||
<File Name="fsptool-a64.exe" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.fsptool_x64.exe" Guid="013FE508-097D-4433-9C60-717F5446E7F4">
|
||||
<Component Id="C.fsptool_x64.exe" Guid="35EE49E2-9565-4FA2-A0AC-D51FD94FA380">
|
||||
<File Name="fsptool-x64.exe" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.fsptool_x86.exe" Guid="6C16DC2C-E12F-49FB-A665-3AF0475487AD">
|
||||
<Component Id="C.fsptool_x86.exe" Guid="0E6D5742-D500-4E24-A0FA-E6316DB70D8B">
|
||||
<File Name="fsptool-x86.exe" KeyPath="yes" />
|
||||
</Component>
|
||||
|
||||
@ -409,7 +455,7 @@
|
||||
</Component>
|
||||
|
||||
<!-- On WinArm64 copy fuse-a64.pc -->
|
||||
<Component Id="C.fuse_a64.pc" Guid="74E6E9BD-AF16-4635-AE52-84B33E4E196E">
|
||||
<Component Id="C.fuse_a64.pc" Guid="776C28B5-DA1A-4EB6-96E6-3D22FE1573AC">
|
||||
<File
|
||||
Id="FILE.fuse_a64.pc"
|
||||
Name="fuse.pc"
|
||||
@ -419,7 +465,7 @@
|
||||
</Component>
|
||||
|
||||
<!-- On Win64 copy fuse-x64.pc -->
|
||||
<Component Id="C.fuse_x64.pc" Guid="407395D2-D076-411E-B1D0-D97E21E11A3C">
|
||||
<Component Id="C.fuse_x64.pc" Guid="89D39F6E-2994-4E6F-ACB6-5B544057C051">
|
||||
<File
|
||||
Id="FILE.fuse_x64.pc"
|
||||
Name="fuse.pc"
|
||||
@ -429,7 +475,7 @@
|
||||
</Component>
|
||||
|
||||
<!-- On Win32 copy fuse-x86.pc -->
|
||||
<Component Id="C.fuse_x86.pc" Guid="0568EBCB-782E-4C17-9B64-BAFCC43F64ED">
|
||||
<Component Id="C.fuse_x86.pc" Guid="75637ECD-B3EC-4A19-98B7-9AFAB0722D9A">
|
||||
<File
|
||||
Id="FILE.fuse_x86.pc"
|
||||
Name="fuse.pc"
|
||||
@ -439,7 +485,7 @@
|
||||
</Component>
|
||||
|
||||
<!-- On WinArm64 copy fuse3-x64.pc -->
|
||||
<Component Id="C.fuse3_a64.pc" Guid="2B6444DB-25E5-45B4-BC61-157D3B992F2B">
|
||||
<Component Id="C.fuse3_a64.pc" Guid="5A69B633-11E4-46E4-8D08-BED1BE7BF4F0">
|
||||
<File
|
||||
Id="FILE.fuse3_a64.pc"
|
||||
Name="fuse3.pc"
|
||||
@ -449,7 +495,7 @@
|
||||
</Component>
|
||||
|
||||
<!-- On Win64 copy fuse3-x64.pc -->
|
||||
<Component Id="C.fuse3_x64.pc" Guid="FE59E3BA-E5EA-4822-80B1-19A1DE6B62C7">
|
||||
<Component Id="C.fuse3_x64.pc" Guid="EEAF35B5-5D6C-47D6-BEE3-5E44DD5A294B">
|
||||
<File
|
||||
Id="FILE.fuse3_x64.pc"
|
||||
Name="fuse3.pc"
|
||||
@ -459,7 +505,7 @@
|
||||
</Component>
|
||||
|
||||
<!-- On Win32 copy fuse3-x86.pc -->
|
||||
<Component Id="C.fuse3_x86.pc" Guid="176205D0-07EA-4DFC-947F-18E89ABDAFAB">
|
||||
<Component Id="C.fuse3_x86.pc" Guid="476CF5E5-2B8E-4D75-B1A5-FFA8C3DAECB2">
|
||||
<File
|
||||
Id="FILE.fuse3_x86.pc"
|
||||
Name="fuse3.pc"
|
||||
@ -737,62 +783,6 @@
|
||||
</Component>
|
||||
</Directory>
|
||||
</DirectoryRef>
|
||||
<DirectoryRef Id="SYMDIR">
|
||||
<Component Id="C.$(var.MyProductFileName)_a64.sys.pdb">
|
||||
<File Name="$(var.MyProductFileName)-a64.sys.pdb" Source="..\build\$(var.Configuration)\$(var.MyProductFileName)-a64.sys.public.pdb" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.$(var.MyProductFileName)_x64.sys.pdb">
|
||||
<File Name="$(var.MyProductFileName)-x64.sys.pdb" Source="..\build\$(var.Configuration)\$(var.MyProductFileName)-x64.sys.public.pdb" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.$(var.MyProductFileName)_x86.sys.pdb">
|
||||
<File Name="$(var.MyProductFileName)-x86.sys.pdb" Source="..\build\$(var.Configuration)\$(var.MyProductFileName)-x86.sys.public.pdb" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.$(var.MyProductFileName)_a64.dll.pdb">
|
||||
<File Name="$(var.MyProductFileName)-a64.dll.pdb" Source="..\build\$(var.Configuration)\$(var.MyProductFileName)-a64.dll.public.pdb" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.$(var.MyProductFileName)_x64.dll.pdb">
|
||||
<File Name="$(var.MyProductFileName)-x64.dll.pdb" Source="..\build\$(var.Configuration)\$(var.MyProductFileName)-x64.dll.public.pdb" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.$(var.MyProductFileName)_x86.dll.pdb">
|
||||
<File Name="$(var.MyProductFileName)-x86.dll.pdb" Source="..\build\$(var.Configuration)\$(var.MyProductFileName)-x86.dll.public.pdb" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.launcher_a64.pdb">
|
||||
<File Name="launcher-a64.pdb" Source="..\build\$(var.Configuration)\launcher-a64.public.pdb" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.launcher_x64.pdb">
|
||||
<File Name="launcher-x64.pdb" Source="..\build\$(var.Configuration)\launcher-x64.public.pdb" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.launcher_x86.pdb">
|
||||
<File Name="launcher-x86.pdb" Source="..\build\$(var.Configuration)\launcher-x86.public.pdb" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.launchctl_a64.pdb">
|
||||
<File Name="launchctl-a64.pdb" Source="..\build\$(var.Configuration)\launchctl-a64.public.pdb" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.launchctl_x64.pdb">
|
||||
<File Name="launchctl-x64.pdb" Source="..\build\$(var.Configuration)\launchctl-x64.public.pdb" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.launchctl_x86.pdb">
|
||||
<File Name="launchctl-x86.pdb" Source="..\build\$(var.Configuration)\launchctl-x86.public.pdb" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.fsptool_a64.pdb">
|
||||
<File Name="fsptool-a64.pdb" Source="..\build\$(var.Configuration)\fsptool-a64.public.pdb" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.fsptool_x64.pdb">
|
||||
<File Name="fsptool-x64.pdb" Source="..\build\$(var.Configuration)\fsptool-x64.public.pdb" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.fsptool_x86.pdb">
|
||||
<File Name="fsptool-x86.pdb" Source="..\build\$(var.Configuration)\fsptool-x86.public.pdb" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.memfs_a64.pdb">
|
||||
<File Name="memfs-a64.pdb" Source="..\build\$(var.Configuration)\memfs-a64.public.pdb" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.memfs_x64.pdb">
|
||||
<File Name="memfs-x64.pdb" Source="..\build\$(var.Configuration)\memfs-x64.public.pdb" KeyPath="yes" />
|
||||
</Component>
|
||||
<Component Id="C.memfs_x86.pdb">
|
||||
<File Name="memfs-x86.pdb" Source="..\build\$(var.Configuration)\memfs-x86.public.pdb" KeyPath="yes" />
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
|
||||
<ComponentGroup Id="C.$(var.MyProductName).bin">
|
||||
<ComponentRef Id="C.$(var.MyProductFileName)_a64.sys" />
|
||||
@ -927,26 +917,6 @@
|
||||
<ComponentRef Id="C.notifyfs.vcxproj" />
|
||||
<ComponentRef Id="C.notifyfs.vcxproj.filters" />
|
||||
</ComponentGroup>
|
||||
<ComponentGroup Id="C.$(var.MyProductName).sym">
|
||||
<ComponentRef Id="C.$(var.MyProductFileName)_a64.sys.pdb" />
|
||||
<ComponentRef Id="C.$(var.MyProductFileName)_x64.sys.pdb" />
|
||||
<ComponentRef Id="C.$(var.MyProductFileName)_x86.sys.pdb" />
|
||||
<ComponentRef Id="C.$(var.MyProductFileName)_a64.dll.pdb" />
|
||||
<ComponentRef Id="C.$(var.MyProductFileName)_x64.dll.pdb" />
|
||||
<ComponentRef Id="C.$(var.MyProductFileName)_x86.dll.pdb" />
|
||||
<ComponentRef Id="C.launcher_a64.pdb" />
|
||||
<ComponentRef Id="C.launcher_x64.pdb" />
|
||||
<ComponentRef Id="C.launcher_x86.pdb" />
|
||||
<ComponentRef Id="C.launchctl_a64.pdb" />
|
||||
<ComponentRef Id="C.launchctl_x64.pdb" />
|
||||
<ComponentRef Id="C.launchctl_x86.pdb" />
|
||||
<ComponentRef Id="C.fsptool_a64.pdb" />
|
||||
<ComponentRef Id="C.fsptool_x64.pdb" />
|
||||
<ComponentRef Id="C.fsptool_x86.pdb" />
|
||||
<ComponentRef Id="C.memfs_a64.pdb" />
|
||||
<ComponentRef Id="C.memfs_x64.pdb" />
|
||||
<ComponentRef Id="C.memfs_x86.pdb" />
|
||||
</ComponentGroup>
|
||||
<ComponentGroup Id="C.$(var.MyProductName).net">
|
||||
<ComponentRef Id="C.$(var.MyProductFileName)_msil.dll" />
|
||||
<ComponentRef Id="C.$(var.MyProductFileName)_msil.xml" />
|
||||
@ -978,6 +948,7 @@
|
||||
Absent="disallow">
|
||||
<ComponentRef Id="C.INSTALLDIR" />
|
||||
<ComponentRef Id="C.License.txt" />
|
||||
<ComponentRef Id="C.SXSDIR" />
|
||||
<Feature
|
||||
Id="F.User"
|
||||
Level="1"
|
||||
@ -1013,7 +984,6 @@
|
||||
<ComponentGroupRef Id="C.$(var.MyProductName).lib" />
|
||||
<ComponentGroupRef Id="C.$(var.MyProductName).smp" />
|
||||
<ComponentGroupRef Id="C.$(var.MyProductName).smp.net" />
|
||||
<ComponentGroupRef Id="C.$(var.MyProductName).sym" />
|
||||
</Feature>
|
||||
<Feature
|
||||
Id="F.KernelDeveloper"
|
||||
@ -1056,7 +1026,24 @@
|
||||
Order="10">NOT Installed</Publish>
|
||||
</UI>
|
||||
|
||||
<!-- Custom Actions -->
|
||||
<Binary Id="CustomActions" SourceFile="..\build\$(var.Configuration)\CustomActions.dll" />
|
||||
|
||||
<!-- InstanceID computes a unique per-installer-run ID -->
|
||||
<CustomAction
|
||||
Id="Action.InstanceID"
|
||||
BinaryKey="CustomActions"
|
||||
DllEntry="InstanceID"
|
||||
Execute="firstSequence"
|
||||
Return="check" />
|
||||
<InstallExecuteSequence>
|
||||
<Custom Action="Action.InstanceID" Before="AppSearch" />
|
||||
</InstallExecuteSequence>
|
||||
<InstallUISequence>
|
||||
<Custom Action="Action.InstanceID" Before="AppSearch" />
|
||||
</InstallUISequence>
|
||||
|
||||
<!-- ServiceRunning determines if the old driver (that did not support unload) is running. -->
|
||||
<CustomAction
|
||||
Id="Params.ServiceRunning"
|
||||
Property="ServiceRunning"
|
||||
@ -1069,16 +1056,109 @@
|
||||
Return="ignore" />
|
||||
<CustomAction
|
||||
Id="Action.ServiceRunning.Error"
|
||||
Error="The $(var.MyProductName) service appears to be running. If you just uninstalled $(var.MyProductName) please restart your computer. If you are running a development version of $(var.MyProductName) please remove it before proceeding." />
|
||||
Error="A component from an older version of $(var.MyProductName) that cannot be upgraded appears to be running. If you just uninstalled an older version of $(var.MyProductName) please restart your computer." />
|
||||
<InstallExecuteSequence>
|
||||
<Custom Action="Params.ServiceRunning" Before="Action.ServiceRunning" />
|
||||
<Custom Action="Action.ServiceRunning" Before="LaunchConditions" />
|
||||
<Custom Action="Action.ServiceRunning" After="LaunchConditions">
|
||||
<![CDATA[NOT Installed]]>
|
||||
</Custom>
|
||||
<Custom Action="Action.ServiceRunning.Error" After="Action.ServiceRunning">
|
||||
<![CDATA[NOT Installed AND (0 <> ServiceRunning)]]>
|
||||
</Custom>
|
||||
<ScheduleReboot After="RemoveFiles">
|
||||
<![CDATA[(REMOVE ~= "ALL") AND (0 <> ServiceRunning)]]>
|
||||
</ScheduleReboot>
|
||||
</InstallExecuteSequence>
|
||||
<InstallUISequence>
|
||||
<Custom Action="Params.ServiceRunning" Before="Action.ServiceRunning" />
|
||||
<Custom Action="Action.ServiceRunning" After="LaunchConditions">
|
||||
<![CDATA[NOT Installed]]>
|
||||
</Custom>
|
||||
<Custom Action="Action.ServiceRunning.Error" After="Action.ServiceRunning">
|
||||
<![CDATA[NOT Installed AND (0 <> ServiceRunning)]]>
|
||||
</Custom>
|
||||
</InstallUISequence>
|
||||
|
||||
<!-- InstallSymlinks installs SxS symlinks -->
|
||||
<SetProperty
|
||||
Id="Deferred.InstallSymlinks"
|
||||
Value='InstallJunctions "[INSTALLDIR]\" "[SXSDIR]\" bin'
|
||||
Before="Deferred.InstallSymlinks"
|
||||
Sequence="execute" />
|
||||
<CustomAction
|
||||
Id="Deferred.InstallSymlinks"
|
||||
BinaryKey="CustomActions"
|
||||
DllEntry="DeferredAction"
|
||||
Execute="deferred"
|
||||
Impersonate="no"
|
||||
Return="check" />
|
||||
<SetProperty
|
||||
Id="Rollback.InstallSymlinks"
|
||||
Value='RemoveFiles "[INSTALLDIR]\" bin'
|
||||
Before="Rollback.InstallSymlinks"
|
||||
Sequence="execute" />
|
||||
<CustomAction
|
||||
Id="Rollback.InstallSymlinks"
|
||||
BinaryKey="CustomActions"
|
||||
DllEntry="DeferredAction"
|
||||
Execute="rollback"
|
||||
Impersonate="no"
|
||||
Return="ignore" />
|
||||
<InstallExecuteSequence>
|
||||
<!--
|
||||
deferred: `InstallSymlinks` on install or repair
|
||||
rollback: `RemoveSymlinks` on install only
|
||||
-->
|
||||
<Custom Action="Rollback.InstallSymlinks" After="InstallFiles">
|
||||
NOT Installed
|
||||
</Custom>
|
||||
<Custom Action="Deferred.InstallSymlinks" After="Rollback.InstallSymlinks">
|
||||
(NOT Installed) OR REINSTALL
|
||||
</Custom>
|
||||
</InstallExecuteSequence>
|
||||
|
||||
<!-- RemoveSymlinks removes SxS symlinks -->
|
||||
<SetProperty
|
||||
Id="Deferred.RemoveSymlinks"
|
||||
Value='RemoveFiles "[INSTALLDIR]\" bin'
|
||||
Before="Deferred.RemoveSymlinks"
|
||||
Sequence="execute" />
|
||||
<CustomAction
|
||||
Id="Deferred.RemoveSymlinks"
|
||||
BinaryKey="CustomActions"
|
||||
DllEntry="DeferredAction"
|
||||
Execute="deferred"
|
||||
Impersonate="no"
|
||||
Return="ignore" />
|
||||
<SetProperty
|
||||
Id="Rollback.RemoveSymlinks"
|
||||
Value='InstallJunctions "[INSTALLDIR]\" "[SXSDIR]\" bin'
|
||||
Before="Rollback.RemoveSymlinks"
|
||||
Sequence="execute" />
|
||||
<CustomAction
|
||||
Id="Rollback.RemoveSymlinks"
|
||||
BinaryKey="CustomActions"
|
||||
DllEntry="DeferredAction"
|
||||
Execute="rollback"
|
||||
Impersonate="no"
|
||||
Return="check" />
|
||||
<InstallExecuteSequence>
|
||||
<!--
|
||||
deferred: `RemoveSymlinks` on uninstall
|
||||
rollback: `InstallSymlinks` on uninstall
|
||||
-->
|
||||
<Custom Action="Rollback.RemoveSymlinks" Before="RemoveFiles">
|
||||
REMOVE ~= "ALL"
|
||||
</Custom>
|
||||
<Custom Action="Deferred.RemoveSymlinks" After="Rollback.RemoveSymlinks">
|
||||
REMOVE ~= "ALL"
|
||||
</Custom>
|
||||
</InstallExecuteSequence>
|
||||
|
||||
<!--
|
||||
Specify WIXFAILWHENDEFERRED=1 on the msiexec cmdline for rollback testing.
|
||||
See http://tinyurl.com/yxkaywek
|
||||
-->
|
||||
<!--
|
||||
<Property Id="WIXFAILWHENDEFERRED" Value="0" Secure="yes" />
|
||||
<CustomActionRef Id="WixFailWhenDeferred" />
|
||||
-->
|
||||
</Product>
|
||||
</Wix>
|
||||
|
@ -20,7 +20,7 @@
|
||||
<SuppressAllWarnings>False</SuppressAllWarnings>
|
||||
<Pedantic>True</Pedantic>
|
||||
<SuppressPdbOutput>True</SuppressPdbOutput>
|
||||
<SuppressIces>ICE30</SuppressIces>
|
||||
<SuppressIces>ICE30;ICE61</SuppressIces>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||
<OutputPath>$(SolutionDir)build\$(Configuration)\</OutputPath>
|
||||
@ -29,12 +29,16 @@
|
||||
<SuppressAllWarnings>False</SuppressAllWarnings>
|
||||
<Pedantic>True</Pedantic>
|
||||
<SuppressPdbOutput>True</SuppressPdbOutput>
|
||||
<SuppressIces>ICE30</SuppressIces>
|
||||
<SuppressIces>ICE30;ICE61</SuppressIces>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Product.wxs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<WixExtension Include="WixUtilExtension">
|
||||
<HintPath>$(WixExtDir)\WixUtilExtension.dll</HintPath>
|
||||
<Name>WixUtilExtension</Name>
|
||||
</WixExtension>
|
||||
<WixExtension Include="WixUIExtension">
|
||||
<HintPath>$(WixExtDir)\WixUIExtension.dll</HintPath>
|
||||
<Name>WixUIExtension</Name>
|
||||
|
@ -284,6 +284,7 @@
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\security-test.c" />
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\stream-tests.c" />
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\timeout-test.c" />
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\loadun-test.c" />
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\uuid5-test.c" />
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\version-test.c" />
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\volpath-test.c" />
|
||||
|
@ -112,6 +112,9 @@
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\notify-test.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\..\tst\winfsp-tests\loadun-test.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\..\ext\tlib\testsuite.h">
|
||||
|
@ -73,8 +73,10 @@
|
||||
<ClCompile Include="..\..\src\dll\ntstatus.c" />
|
||||
<ClCompile Include="..\..\src\dll\path.c" />
|
||||
<ClCompile Include="..\..\src\dll\service.c" />
|
||||
<ClCompile Include="..\..\src\dll\sxs.c" />
|
||||
<ClCompile Include="..\..\src\dll\util.c" />
|
||||
<ClCompile Include="..\..\src\dll\wksid.c" />
|
||||
<ClCompile Include="..\..\src\shared\ku\mountmgr.c" />
|
||||
<ClCompile Include="..\..\src\shared\ku\posix.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@ -287,7 +289,7 @@ copy /b $(OutDir)fuse3-$(MyProductFileArch).pc + %(FullPath) $(OutDir)fuse3-$(My
|
||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;credui.lib;secur32.lib;version.lib;netapi32.lib;wldap32.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);credui.lib;netapi32.lib;rpcrt4.lib;secur32.lib;shlwapi.lib;version.lib;wldap32.lib</AdditionalDependencies>
|
||||
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
@ -314,7 +316,7 @@ copy /b $(OutDir)fuse3-$(MyProductFileArch).pc + %(FullPath) $(OutDir)fuse3-$(My
|
||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;credui.lib;secur32.lib;version.lib;netapi32.lib;wldap32.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);credui.lib;netapi32.lib;rpcrt4.lib;secur32.lib;shlwapi.lib;version.lib;wldap32.lib</AdditionalDependencies>
|
||||
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
@ -341,7 +343,7 @@ copy /b $(OutDir)fuse3-$(MyProductFileArch).pc + %(FullPath) $(OutDir)fuse3-$(My
|
||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;credui.lib;secur32.lib;version.lib;netapi32.lib;wldap32.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);credui.lib;netapi32.lib;rpcrt4.lib;secur32.lib;shlwapi.lib;version.lib;wldap32.lib</AdditionalDependencies>
|
||||
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
@ -371,7 +373,7 @@ copy /b $(OutDir)fuse3-$(MyProductFileArch).pc + %(FullPath) $(OutDir)fuse3-$(My
|
||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;credui.lib;secur32.lib;version.lib;netapi32.lib;wldap32.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);credui.lib;netapi32.lib;rpcrt4.lib;secur32.lib;shlwapi.lib;version.lib;wldap32.lib</AdditionalDependencies>
|
||||
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
||||
<AdditionalOptions>/PDBALTPATH:$(TargetFileName).pdb %(AdditionalOptions)</AdditionalOptions>
|
||||
</Link>
|
||||
@ -402,7 +404,7 @@ copy /b $(OutDir)fuse3-$(MyProductFileArch).pc + %(FullPath) $(OutDir)fuse3-$(My
|
||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;credui.lib;secur32.lib;version.lib;netapi32.lib;wldap32.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);credui.lib;netapi32.lib;rpcrt4.lib;secur32.lib;shlwapi.lib;version.lib;wldap32.lib</AdditionalDependencies>
|
||||
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
||||
<AdditionalOptions>/PDBALTPATH:$(TargetFileName).pdb %(AdditionalOptions)</AdditionalOptions>
|
||||
</Link>
|
||||
@ -433,7 +435,7 @@ copy /b $(OutDir)fuse3-$(MyProductFileArch).pc + %(FullPath) $(OutDir)fuse3-$(My
|
||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib;credui.lib;secur32.lib;version.lib;netapi32.lib;wldap32.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);credui.lib;netapi32.lib;rpcrt4.lib;secur32.lib;shlwapi.lib;version.lib;wldap32.lib</AdditionalDependencies>
|
||||
<StripPrivateSymbols>$(OutDir)$(TargetFileName).public.pdb</StripPrivateSymbols>
|
||||
<AdditionalOptions>/PDBALTPATH:$(TargetFileName).pdb %(AdditionalOptions)</AdditionalOptions>
|
||||
</Link>
|
||||
|
@ -175,6 +175,12 @@
|
||||
<ClCompile Include="..\..\src\dll\debug.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\shared\ku\mountmgr.c">
|
||||
<Filter>Source\shared\ku</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\dll\sxs.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\src\dll\library.def">
|
||||
|
@ -228,6 +228,7 @@
|
||||
<FilesToPackage Include="$(TargetPath)" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\shared\ku\mountmgr.c" />
|
||||
<ClCompile Include="..\..\src\shared\ku\posix.c" />
|
||||
<ClCompile Include="..\..\src\shared\ku\uuid5.c" />
|
||||
<ClCompile Include="..\..\src\sys\cleanup.c" />
|
||||
@ -259,6 +260,7 @@
|
||||
<ClCompile Include="..\..\src\sys\shutdown.c" />
|
||||
<ClCompile Include="..\..\src\sys\silo.c" />
|
||||
<ClCompile Include="..\..\src\sys\statistics.c" />
|
||||
<ClCompile Include="..\..\src\sys\sxs.c" />
|
||||
<ClCompile Include="..\..\src\sys\trace.c" />
|
||||
<ClCompile Include="..\..\src\sys\util.c" />
|
||||
<ClCompile Include="..\..\src\sys\volinfo.c" />
|
||||
|
@ -131,6 +131,12 @@
|
||||
<ClCompile Include="..\..\src\sys\devtimer.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\shared\ku\mountmgr.c">
|
||||
<Filter>Source\shared\ku</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\sys\sxs.c">
|
||||
<Filter>Source</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\src\sys\driver.h">
|
||||
|
@ -34,3 +34,4 @@ This document contains a list of known open-source file systems and file system
|
||||
- https://github.com/billziss-gh/fusepy[Python: fusepy] - Simple ctypes bindings for FUSE
|
||||
- https://github.com/pleiszenburg/refuse[Python: refuse] - Simple cross-plattform ctypes bindings for libfuse / FUSE for macOS / WinFsp
|
||||
- https://github.com/Scille/winfspy[Python: winfspy] - WinFSP binding for Python
|
||||
- https://github.com/SnowflakePowered/winfsp-rs[Rust: winfsp-rs] - WinFSP binding for Rust
|
||||
|
@ -71,6 +71,8 @@ Primary registry key used to store WinFsp settings. On a 64-bit system (x64 or A
|
||||
|
||||
* `MountDoNotUseLauncher (REG_DWORD)`: A value of 1 disallows the use of the Launcher for drive mounting. The default value of 0 allows use of the Launcher for drive mounting when necessary. In general the Launcher is not necessary for mounting. However when running a file system in the Windows Service context (session 0) under an account that is not LocalSystem (e.g. `NT AUTHORITY\NETWORK SERVICE`), the Launcher is used to create global drives.
|
||||
|
||||
* `MountUseMountmgrFromFSD (REG_DWORD)`: A value of 1 instructs WinFsp to use the Mount Manager from the FSD (File System Driver) which runs in kernel mode. The default value of 0 instructs WinFsp to use the Mount Manager from the DLL which runs in user mode. Using the Mount Manager from user mode requires Administrator access and this setting allows a file system to circumvent the Administrator access requirement. This setting is not recommended for general use.
|
||||
|
||||
</blockquote>
|
||||
</details>
|
||||
|
||||
|
@ -538,7 +538,8 @@ static NTSTATUS GetFileInfoInternal(HANDLE Handle, FSP_FSCTL_FILE_INFO *FileInfo
|
||||
FileInfo->LastAccessTime = ((PLARGE_INTEGER)&ByHandleFileInfo.ftLastAccessTime)->QuadPart;
|
||||
FileInfo->LastWriteTime = ((PLARGE_INTEGER)&ByHandleFileInfo.ftLastWriteTime)->QuadPart;
|
||||
FileInfo->ChangeTime = FileInfo->LastWriteTime;
|
||||
FileInfo->IndexNumber = 0;
|
||||
FileInfo->IndexNumber =
|
||||
((UINT64)ByHandleFileInfo.nFileIndexHigh << 32) | (UINT64)ByHandleFileInfo.nFileIndexLow;
|
||||
FileInfo->HardLinks = 0;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
|
@ -91,6 +91,8 @@ extern const __declspec(selectany) GUID FspFsvrtDeviceClassGuid =
|
||||
/* fsctl device codes */
|
||||
#define FSP_FSCTL_MOUNTDEV \
|
||||
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'M', METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define FSP_FSCTL_MOUNTMGR \
|
||||
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'm', METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define FSP_FSCTL_VOLUME_NAME \
|
||||
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'N', METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define FSP_FSCTL_VOLUME_LIST \
|
||||
@ -109,6 +111,8 @@ extern const __declspec(selectany) GUID FspFsvrtDeviceClassGuid =
|
||||
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 's', METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define FSP_FSCTL_NOTIFY \
|
||||
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'n', METHOD_NEITHER, FILE_ANY_ACCESS)
|
||||
#define FSP_FSCTL_UNLOAD \
|
||||
CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 0x800 + 'U', METHOD_NEITHER, FILE_ANY_ACCESS)
|
||||
|
||||
/* fsctl internal device codes (usable only in-kernel) */
|
||||
#define FSP_FSCTL_TRANSACT_INTERNAL \
|
||||
@ -226,7 +230,7 @@ enum
|
||||
UINT32 CasePreservedExtendedAttributes:1; /* preserve case of EA (default is UPPERCASE) */\
|
||||
UINT32 WslFeatures:1; /* support features required for WSLinux */\
|
||||
UINT32 DirectoryMarkerAsNextOffset:1; /* directory marker is next offset instead of last name */\
|
||||
UINT32 RejectIrpPriorToTransact0:1; /* reject IRP's prior to FspFsctlTransact with 0 buffers */\
|
||||
UINT32 RejectIrpPriorToTransact0:1; /* DEPRECATED: reject IRP's prior to FspFsctlTransact0 */\
|
||||
UINT32 SupportsPosixUnlinkRename:1; /* file system supports POSIX-style unlink and rename */\
|
||||
UINT32 PostDispositionWhenNecessaryOnly:1; /* post Disposition for dirs or READONLY attr check */\
|
||||
UINT32 KmReservedFlags:1;\
|
||||
@ -679,6 +683,8 @@ FSP_API NTSTATUS FspFsctlCreateVolume(PWSTR DevicePath,
|
||||
PHANDLE PVolumeHandle);
|
||||
FSP_API NTSTATUS FspFsctlMakeMountdev(HANDLE VolumeHandle,
|
||||
BOOLEAN Persistent, GUID *UniqueId);
|
||||
FSP_API NTSTATUS FspFsctlUseMountmgr(HANDLE VolumeHandle,
|
||||
PWSTR MountPoint);
|
||||
FSP_API NTSTATUS FspFsctlTransact(HANDLE VolumeHandle,
|
||||
PVOID ResponseBuf, SIZE_T ResponseBufSize,
|
||||
PVOID RequestBuf, SIZE_T *PRequestBufSize,
|
||||
@ -690,6 +696,11 @@ FSP_API NTSTATUS FspFsctlNotify(HANDLE VolumeHandle,
|
||||
FSP_API NTSTATUS FspFsctlGetVolumeList(PWSTR DevicePath,
|
||||
PWCHAR VolumeListBuf, PSIZE_T PVolumeListSize);
|
||||
FSP_API NTSTATUS FspFsctlPreflight(PWSTR DevicePath);
|
||||
FSP_API NTSTATUS FspFsctlStartService(VOID);
|
||||
FSP_API NTSTATUS FspFsctlStopService(VOID);
|
||||
FSP_API NTSTATUS FspFsctlEnumServices(
|
||||
VOID (*EnumFn)(PVOID Context, PWSTR ServiceName, BOOLEAN Running),
|
||||
PVOID Context);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -1047,11 +1047,14 @@ typedef struct _FSP_FILE_SYSTEM_INTERFACE
|
||||
|
||||
NTSTATUS (*Obsolete0)(VOID);
|
||||
|
||||
VOID (*DispatcherStopped)(FSP_FILE_SYSTEM *FileSystem,
|
||||
BOOLEAN Normally);
|
||||
|
||||
/*
|
||||
* This ensures that this interface will always contain 64 function pointers.
|
||||
* Please update when changing the interface as it is important for future compatibility.
|
||||
*/
|
||||
NTSTATUS (*Reserved[32])();
|
||||
NTSTATUS (*Reserved[31])();
|
||||
} FSP_FILE_SYSTEM_INTERFACE;
|
||||
FSP_FSCTL_STATIC_ASSERT(sizeof(FSP_FILE_SYSTEM_INTERFACE) == 64 * sizeof(NTSTATUS (*)()),
|
||||
"FSP_FILE_SYSTEM_INTERFACE must have 64 entries.");
|
||||
@ -1074,7 +1077,8 @@ typedef struct _FSP_FILE_SYSTEM
|
||||
SRWLOCK OpGuardLock;
|
||||
BOOLEAN UmFileContextIsUserContext2, UmFileContextIsFullContext;
|
||||
UINT16 UmNoReparsePointsDirCheck:1;
|
||||
UINT16 UmReservedFlags:15;
|
||||
UINT16 UmReservedFlags:14;
|
||||
UINT16 DispatcherStopping:1;
|
||||
} FSP_FILE_SYSTEM;
|
||||
FSP_FSCTL_STATIC_ASSERT(
|
||||
(4 == sizeof(PVOID) && 660 == sizeof(FSP_FILE_SYSTEM)) ||
|
||||
@ -2120,6 +2124,7 @@ FSP_API NTSTATUS FspCallNamedPipeSecurelyEx(PWSTR PipeName,
|
||||
PULONG PBytesTransferred, ULONG Timeout, BOOLEAN AllowImpersonation,
|
||||
PSID Sid);
|
||||
FSP_API NTSTATUS FspVersion(PUINT32 PVersion);
|
||||
FSP_API PWSTR FspSxsIdent(VOID);
|
||||
|
||||
/*
|
||||
* Delay load
|
||||
|
@ -100,9 +100,11 @@ NTSTATUS FspEventLogRegister(VOID)
|
||||
WCHAR Path[MAX_PATH];
|
||||
DWORD RegResult, DwordValue;
|
||||
HKEY RegKey;
|
||||
NTSTATUS Result;
|
||||
|
||||
if (0 == GetModuleFileNameW(DllInstance, Path, MAX_PATH))
|
||||
return FspNtStatusFromWin32(GetLastError());
|
||||
Result = FspGetModuleFileName(DllInstance, Path, MAX_PATH, L"" MyEventLogRegisterPath);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return Result;
|
||||
|
||||
RegResult = RegCreateKeyExW(
|
||||
HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\" FSP_EVENTLOG_NAME,
|
||||
|
27
src/dll/fs.c
27
src/dll/fs.c
@ -358,6 +358,21 @@ exit:
|
||||
CloseHandle(DispatcherThread);
|
||||
}
|
||||
|
||||
if (GetCurrentThreadId() == GetThreadId(FileSystem->DispatcherThread))
|
||||
{
|
||||
if (0 != FileSystem->Interface->DispatcherStopped)
|
||||
{
|
||||
/* Normally = !!FileSystem->DispatcherStopping */
|
||||
BOOLEAN Normally = !!(
|
||||
_InterlockedOr16(
|
||||
(PVOID)((PUINT8)&FileSystem->UmFileContextIsFullContext +
|
||||
sizeof(FileSystem->UmFileContextIsFullContext)),
|
||||
0) &
|
||||
0x8000);
|
||||
FileSystem->Interface->DispatcherStopped(FileSystem, Normally);
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
@ -399,6 +414,12 @@ FSP_API VOID FspFileSystemStopDispatcher(FSP_FILE_SYSTEM *FileSystem)
|
||||
if (0 == FileSystem->DispatcherThread)
|
||||
return;
|
||||
|
||||
/* FileSystem->DispatcherStopping = 1 */
|
||||
_InterlockedOr16(
|
||||
(PVOID)((PUINT8)&FileSystem->UmFileContextIsFullContext +
|
||||
sizeof(FileSystem->UmFileContextIsFullContext)),
|
||||
0x8000);
|
||||
|
||||
FspFsctlStop0(FileSystem->VolumeHandle);
|
||||
|
||||
WaitForSingleObject(FileSystem->DispatcherThread, INFINITE);
|
||||
@ -406,6 +427,12 @@ FSP_API VOID FspFileSystemStopDispatcher(FSP_FILE_SYSTEM *FileSystem)
|
||||
FileSystem->DispatcherThread = 0;
|
||||
|
||||
FspFsctlStop(FileSystem->VolumeHandle);
|
||||
|
||||
/* FileSystem->DispatcherStopping = 0 */
|
||||
_InterlockedAnd16(
|
||||
(PVOID)((PUINT8)&FileSystem->UmFileContextIsFullContext +
|
||||
sizeof(FileSystem->UmFileContextIsFullContext)),
|
||||
0x7fff);
|
||||
}
|
||||
|
||||
FSP_API VOID FspFileSystemSendResponse(FSP_FILE_SYSTEM *FileSystem,
|
||||
|
413
src/dll/fsctl.c
413
src/dll/fsctl.c
@ -32,19 +32,21 @@ static DWORD FspFsctlTransactCode = FSP_FSCTL_TRANSACT;
|
||||
static DWORD FspFsctlTransactBatchCode = FSP_FSCTL_TRANSACT_BATCH;
|
||||
|
||||
static VOID FspFsctlServiceVersion(PUINT32 PVersion);
|
||||
static NTSTATUS FspFsctlStartService(VOID);
|
||||
|
||||
FSP_API NTSTATUS FspFsctlCreateVolume(PWSTR DevicePath,
|
||||
const FSP_FSCTL_VOLUME_PARAMS *VolumeParams,
|
||||
PWCHAR VolumeNameBuf, SIZE_T VolumeNameSize,
|
||||
PHANDLE PVolumeHandle)
|
||||
{
|
||||
NTSTATUS Result;
|
||||
WCHAR SxsDevicePathBuf[MAX_PATH];
|
||||
PWSTR DeviceRoot;
|
||||
SIZE_T DeviceRootSize, DevicePathSize, VolumeParamsSize;
|
||||
WCHAR DevicePathBuf[MAX_PATH + sizeof *VolumeParams], *DevicePathPtr, *DevicePathEnd;
|
||||
HANDLE VolumeHandle = INVALID_HANDLE_VALUE;
|
||||
DWORD Bytes;
|
||||
NTSTATUS Result;
|
||||
|
||||
DevicePath = FspSxsAppendSuffix(SxsDevicePathBuf, sizeof SxsDevicePathBuf, DevicePath);
|
||||
|
||||
if (sizeof(WCHAR) <= VolumeNameSize)
|
||||
VolumeNameBuf[0] = L'\0';
|
||||
@ -130,6 +132,22 @@ FSP_API NTSTATUS FspFsctlMakeMountdev(HANDLE VolumeHandle,
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspFsctlUseMountmgr(HANDLE VolumeHandle,
|
||||
PWSTR MountPoint)
|
||||
{
|
||||
DWORD Bytes;
|
||||
|
||||
Bytes = 0 != MountPoint ? lstrlenW(MountPoint) * sizeof(WCHAR) : 0;
|
||||
|
||||
if (!DeviceIoControl(VolumeHandle,
|
||||
FSP_FSCTL_MOUNTMGR,
|
||||
MountPoint, Bytes, 0, 0,
|
||||
&Bytes, 0))
|
||||
return FspNtStatusFromWin32(GetLastError());
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspFsctlTransact(HANDLE VolumeHandle,
|
||||
PVOID ResponseBuf, SIZE_T ResponseBufSize,
|
||||
PVOID RequestBuf, SIZE_T *PRequestBufSize,
|
||||
@ -213,12 +231,15 @@ exit:
|
||||
FSP_API NTSTATUS FspFsctlGetVolumeList(PWSTR DevicePath,
|
||||
PWCHAR VolumeListBuf, PSIZE_T PVolumeListSize)
|
||||
{
|
||||
NTSTATUS Result;
|
||||
WCHAR SxsDevicePathBuf[MAX_PATH];
|
||||
PWSTR DeviceRoot;
|
||||
SIZE_T DeviceRootSize, DevicePathSize;
|
||||
WCHAR DevicePathBuf[MAX_PATH], *DevicePathPtr;
|
||||
HANDLE VolumeHandle = INVALID_HANDLE_VALUE;
|
||||
DWORD Bytes;
|
||||
NTSTATUS Result;
|
||||
|
||||
DevicePath = FspSxsAppendSuffix(SxsDevicePathBuf, sizeof SxsDevicePathBuf, DevicePath);
|
||||
|
||||
/* check lengths; everything must fit within MAX_PATH */
|
||||
DeviceRoot = L'\\' == DevicePath[0] ? GLOBALROOT : GLOBALROOT "\\Device\\";
|
||||
@ -282,16 +303,71 @@ FSP_API NTSTATUS FspFsctlPreflight(PWSTR DevicePath)
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS FspFsctlUnload(PWSTR DevicePath)
|
||||
{
|
||||
WCHAR SxsDevicePathBuf[MAX_PATH];
|
||||
PWSTR DeviceRoot;
|
||||
SIZE_T DeviceRootSize, DevicePathSize;
|
||||
WCHAR DevicePathBuf[MAX_PATH], *DevicePathPtr;
|
||||
HANDLE VolumeHandle = INVALID_HANDLE_VALUE;
|
||||
DWORD Bytes;
|
||||
NTSTATUS Result;
|
||||
|
||||
DevicePath = FspSxsAppendSuffix(SxsDevicePathBuf, sizeof SxsDevicePathBuf, DevicePath);
|
||||
|
||||
/* 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_UNLOAD, 0, 0, 0, 0, &Bytes, 0))
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
if (INVALID_HANDLE_VALUE != VolumeHandle)
|
||||
CloseHandle(VolumeHandle);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
static BOOL WINAPI FspFsctlServiceVersionInitialize(
|
||||
PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
|
||||
{
|
||||
PWSTR DriverName = L"" FSP_FSCTL_DRIVER_NAME;
|
||||
WCHAR DriverName[256];
|
||||
PWSTR ModuleFileName;
|
||||
SC_HANDLE ScmHandle = 0;
|
||||
SC_HANDLE SvcHandle = 0;
|
||||
QUERY_SERVICE_CONFIGW *ServiceConfig = 0;
|
||||
DWORD Size;
|
||||
|
||||
FspSxsAppendSuffix(DriverName, sizeof DriverName, L"" FSP_FSCTL_DRIVER_NAME);
|
||||
|
||||
ScmHandle = OpenSCManagerW(0, 0, 0);
|
||||
if (0 == ScmHandle)
|
||||
goto exit;
|
||||
@ -355,29 +431,33 @@ static VOID FspFsctlServiceVersion(PUINT32 PVersion)
|
||||
*PVersion = FspFsctlServiceVersionValue;
|
||||
}
|
||||
|
||||
static NTSTATUS FspFsctlStartService(VOID)
|
||||
static SRWLOCK FspFsctlStartStopServiceLock = SRWLOCK_INIT;
|
||||
|
||||
static BOOLEAN FspFsctlRunningInContainer(VOID)
|
||||
{
|
||||
/* Determine if we are running inside container.
|
||||
*
|
||||
* See https://github.com/microsoft/perfview/blob/V1.9.65/src/TraceEvent/TraceEventSession.cs#L525
|
||||
* See https://stackoverflow.com/a/50748300
|
||||
*/
|
||||
return ERROR_SUCCESS == RegGetValueW(
|
||||
HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control",
|
||||
L"ContainerType",
|
||||
RRF_RT_REG_DWORD, 0,
|
||||
0, 0);
|
||||
}
|
||||
|
||||
static NTSTATUS FspFsctlStartServiceByName(PWSTR DriverName)
|
||||
{
|
||||
static SRWLOCK Lock = SRWLOCK_INIT;
|
||||
PWSTR DriverName = L"" FSP_FSCTL_DRIVER_NAME;
|
||||
SC_HANDLE ScmHandle = 0;
|
||||
SC_HANDLE SvcHandle = 0;
|
||||
SERVICE_STATUS ServiceStatus;
|
||||
DWORD LastError;
|
||||
NTSTATUS Result;
|
||||
|
||||
AcquireSRWLockExclusive(&Lock);
|
||||
AcquireSRWLockExclusive(&FspFsctlStartStopServiceLock);
|
||||
|
||||
/* Determine if we are running inside container.
|
||||
*
|
||||
* See https://github.com/microsoft/perfview/blob/V1.9.65/src/TraceEvent/TraceEventSession.cs#L525
|
||||
* See https://stackoverflow.com/a/50748300
|
||||
*/
|
||||
LastError = RegGetValueW(
|
||||
HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control",
|
||||
L"ContainerType",
|
||||
RRF_RT_REG_DWORD, 0,
|
||||
0, 0);
|
||||
if (ERROR_SUCCESS == LastError)
|
||||
if (FspFsctlRunningInContainer())
|
||||
{
|
||||
Result = STATUS_SUCCESS;
|
||||
goto exit;
|
||||
@ -437,7 +517,218 @@ exit:
|
||||
if (0 != ScmHandle)
|
||||
CloseServiceHandle(ScmHandle);
|
||||
|
||||
ReleaseSRWLockExclusive(&Lock);
|
||||
ReleaseSRWLockExclusive(&FspFsctlStartStopServiceLock);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
static VOID FspFsctlStartService_EnumFn(PVOID Context, PWSTR ServiceName, BOOLEAN Running)
|
||||
{
|
||||
PWSTR DriverName = Context;
|
||||
if (0 > invariant_wcscmp(DriverName, ServiceName))
|
||||
lstrcpyW(DriverName, ServiceName);
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspFsctlStartService(VOID)
|
||||
{
|
||||
/*
|
||||
* With the introduction of side-by-side (SxS) FSD installations,
|
||||
* we revisit how the FSD is started:
|
||||
*
|
||||
* - If the DLL is started in non-SxS mode, we first try to start
|
||||
* the non-SxS FSD. If that fails we then enumerate all SxS FSD's
|
||||
* and make a best guess on which one to start.
|
||||
*
|
||||
* - If the DLL is started in SxS mode, we only attempt to start
|
||||
* the associated SxS FSD.
|
||||
*/
|
||||
|
||||
if (L'\0' == FspSxsIdent()[0])
|
||||
{
|
||||
/* non-SxS mode */
|
||||
|
||||
NTSTATUS Result;
|
||||
WCHAR DriverName[256];
|
||||
|
||||
Result = FspFsctlStartServiceByName(L"" FSP_FSCTL_DRIVER_NAME);
|
||||
if (NT_SUCCESS(Result) || STATUS_NO_SUCH_DEVICE != Result)
|
||||
return Result;
|
||||
|
||||
/* DO NOT CLOBBER Result. We will return it if our best effort below fails. */
|
||||
|
||||
DriverName[0] = L'\0';
|
||||
FspFsctlEnumServices(FspFsctlStartService_EnumFn, DriverName);
|
||||
|
||||
if (L'\0' == DriverName[0] || !NT_SUCCESS(FspFsctlStartServiceByName(DriverName)))
|
||||
return Result;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* SxS mode */
|
||||
|
||||
WCHAR DriverName[256];
|
||||
FspSxsAppendSuffix(DriverName, sizeof DriverName, L"" FSP_FSCTL_DRIVER_NAME);
|
||||
return FspFsctlStartServiceByName(DriverName);
|
||||
}
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspFsctlStopService(VOID)
|
||||
{
|
||||
WCHAR DriverName[256];
|
||||
HANDLE ThreadToken = 0, ProcessToken = 0;
|
||||
BOOL DidSetThreadToken = FALSE, DidAdjustTokenPrivileges = FALSE;
|
||||
TOKEN_PRIVILEGES Privileges, PreviousPrivileges;
|
||||
PRIVILEGE_SET RequiredPrivileges;
|
||||
DWORD PreviousPrivilegesLength;
|
||||
BOOL PrivilegeCheckResult;
|
||||
NTSTATUS Result;
|
||||
|
||||
FspSxsAppendSuffix(DriverName, sizeof DriverName, L"" FSP_FSCTL_DRIVER_NAME);
|
||||
|
||||
AcquireSRWLockExclusive(&FspFsctlStartStopServiceLock);
|
||||
|
||||
if (FspFsctlRunningInContainer())
|
||||
{
|
||||
Result = STATUS_SUCCESS;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* enable and check SeLoadDriverPrivilege required for FSP_FSCTL_UNLOAD */
|
||||
if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, TRUE, &ThreadToken))
|
||||
{
|
||||
if (!OpenProcessToken(GetCurrentProcess(), MAXIMUM_ALLOWED, &ProcessToken) ||
|
||||
!DuplicateToken(ProcessToken, SecurityDelegation, &ThreadToken) ||
|
||||
!SetThreadToken(0, ThreadToken))
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
}
|
||||
DidSetThreadToken = TRUE;
|
||||
CloseHandle(ThreadToken);
|
||||
ThreadToken = 0;
|
||||
if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, TRUE, &ThreadToken))
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
if (!LookupPrivilegeValueW(0, SE_LOAD_DRIVER_NAME, &Privileges.Privileges[0].Luid))
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
}
|
||||
Privileges.PrivilegeCount = 1;
|
||||
Privileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||
if (!AdjustTokenPrivileges(ThreadToken, FALSE,
|
||||
&Privileges, sizeof PreviousPrivileges, &PreviousPrivileges, &PreviousPrivilegesLength))
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
}
|
||||
DidAdjustTokenPrivileges = 0 == GetLastError();
|
||||
RequiredPrivileges.PrivilegeCount = 1;
|
||||
RequiredPrivileges.Control = PRIVILEGE_SET_ALL_NECESSARY;
|
||||
RequiredPrivileges.Privilege[0].Attributes = 0;
|
||||
RequiredPrivileges.Privilege[0].Luid = Privileges.Privileges[0].Luid;
|
||||
if (!PrivilegeCheck(ThreadToken, &RequiredPrivileges, &PrivilegeCheckResult))
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
}
|
||||
if (!PrivilegeCheckResult)
|
||||
{
|
||||
Result = STATUS_PRIVILEGE_NOT_HELD;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Result = FspFsctlUnload(L"" FSP_FSCTL_DISK_DEVICE_NAME);
|
||||
if (!NT_SUCCESS(Result) && STATUS_NO_SUCH_DEVICE != Result)
|
||||
goto exit;
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
if (DidAdjustTokenPrivileges)
|
||||
AdjustTokenPrivileges(ThreadToken, FALSE, &PreviousPrivileges, 0, 0, 0);
|
||||
if (DidSetThreadToken)
|
||||
SetThreadToken(0, 0);
|
||||
if (0 != ThreadToken)
|
||||
CloseHandle(ThreadToken);
|
||||
if (0 != ProcessToken)
|
||||
CloseHandle(ProcessToken);
|
||||
|
||||
ReleaseSRWLockExclusive(&FspFsctlStartStopServiceLock);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspFsctlEnumServices(
|
||||
VOID (*EnumFn)(PVOID Context, PWSTR ServiceName, BOOLEAN Running),
|
||||
PVOID Context)
|
||||
{
|
||||
SC_HANDLE ScmHandle = 0;
|
||||
LPENUM_SERVICE_STATUSW Services = 0;
|
||||
DWORD Size, ServiceCount;
|
||||
DWORD LastError;
|
||||
NTSTATUS Result;
|
||||
|
||||
ScmHandle = OpenSCManagerW(0, 0, SC_MANAGER_ENUMERATE_SERVICE);
|
||||
if (0 == ScmHandle)
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!EnumServicesStatusW(ScmHandle,
|
||||
SERVICE_FILE_SYSTEM_DRIVER, SERVICE_STATE_ALL, 0, 0, &Size, &ServiceCount, 0))
|
||||
{
|
||||
LastError = GetLastError();
|
||||
if (ERROR_MORE_DATA != LastError)
|
||||
{
|
||||
Result = FspNtStatusFromWin32(LastError);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
if (0 == Size)
|
||||
{
|
||||
Result = STATUS_SUCCESS;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Services = MemAlloc(Size);
|
||||
if (0 == Services)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!EnumServicesStatusW(ScmHandle,
|
||||
SERVICE_FILE_SYSTEM_DRIVER, SERVICE_STATE_ALL, Services, Size, &Size, &ServiceCount, 0))
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
}
|
||||
|
||||
for (DWORD I = 0; ServiceCount > I; I++)
|
||||
{
|
||||
if (0 != invariant_wcsicmp(Services[I].lpServiceName, L"" FSP_FSCTL_DRIVER_NAME) &&
|
||||
0 != invariant_wcsnicmp(Services[I].lpServiceName,
|
||||
L"" FSP_FSCTL_DRIVER_NAME FSP_SXS_SEPARATOR_STRING,
|
||||
sizeof(FSP_FSCTL_DRIVER_NAME FSP_SXS_SEPARATOR_STRING) - 1))
|
||||
continue;
|
||||
EnumFn(Context,
|
||||
Services[I].lpServiceName,
|
||||
SERVICE_STOPPED != Services[I].ServiceStatus.dwCurrentState);
|
||||
}
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
MemFree(Services);
|
||||
if (0 != ScmHandle)
|
||||
CloseServiceHandle(ScmHandle);
|
||||
|
||||
return Result;
|
||||
}
|
||||
@ -445,14 +736,15 @@ exit:
|
||||
static NTSTATUS FspFsctlFixServiceSecurity(HANDLE SvcHandle)
|
||||
{
|
||||
/*
|
||||
* This function adds an ACE that allows Everyone to start a service.
|
||||
* This function adds two ACE's:
|
||||
* - An ACE that allows Everyone to start a service.
|
||||
* - An ACE that denies Everyone (including Administrators) to stop a service.
|
||||
*/
|
||||
|
||||
PSID WorldSid;
|
||||
PSECURITY_DESCRIPTOR SecurityDescriptor = 0;
|
||||
PSECURITY_DESCRIPTOR NewSecurityDescriptor = 0;
|
||||
EXPLICIT_ACCESSW AccessEntry;
|
||||
ACCESS_MASK AccessRights;
|
||||
EXPLICIT_ACCESSW AccessEntries[2];
|
||||
PACL Dacl;
|
||||
BOOL DaclPresent, DaclDefaulted;
|
||||
DWORD Size;
|
||||
@ -497,41 +789,28 @@ static NTSTATUS FspFsctlFixServiceSecurity(HANDLE SvcHandle)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* prepare an EXPLICIT_ACCESS for the SERVICE_QUERY_STATUS | SERVICE_START right for Everyone */
|
||||
AccessEntry.grfAccessPermissions = SERVICE_QUERY_STATUS | SERVICE_START;
|
||||
AccessEntry.grfAccessMode = GRANT_ACCESS;
|
||||
AccessEntry.grfInheritance = NO_INHERITANCE;
|
||||
AccessEntry.Trustee.pMultipleTrustee = 0;
|
||||
AccessEntry.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
|
||||
AccessEntry.Trustee.TrusteeForm = TRUSTEE_IS_SID;
|
||||
AccessEntry.Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
|
||||
AccessEntry.Trustee.ptstrName = WorldSid;
|
||||
/* prepare an EXPLICIT_ACCESS for the SERVICE_QUERY_STATUS | SERVICE_START rights for Everyone */
|
||||
AccessEntries[0].grfAccessPermissions = SERVICE_QUERY_STATUS | SERVICE_START;
|
||||
AccessEntries[0].grfAccessMode = GRANT_ACCESS;
|
||||
AccessEntries[0].grfInheritance = NO_INHERITANCE;
|
||||
AccessEntries[0].Trustee.pMultipleTrustee = 0;
|
||||
AccessEntries[0].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
|
||||
AccessEntries[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
|
||||
AccessEntries[0].Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
|
||||
AccessEntries[0].Trustee.ptstrName = WorldSid;
|
||||
|
||||
/* get the effective rights for Everyone */
|
||||
AccessRights = 0;
|
||||
if (DaclPresent && 0 != Dacl)
|
||||
{
|
||||
LastError = GetEffectiveRightsFromAclW(Dacl, &AccessEntry.Trustee, &AccessRights);
|
||||
if (0 != LastError)
|
||||
/*
|
||||
* Apparently GetEffectiveRightsFromAclW can fail with ERROR_CIRCULAR_DEPENDENCY
|
||||
* in some rare circumstances. Calling GetEffectiveRightsFromAclW is not essential
|
||||
* in this instance. It is only done to check whether the "Everyone/World" SID
|
||||
* already has the access required to start the FSD; if it does not have those
|
||||
* rights already they are added. It is probably safe to just assume that the
|
||||
* required rights are not there if GetEffectiveRightsFromAclW fails; the worst
|
||||
* that can happen is that the rights get added twice (which is benign).
|
||||
*
|
||||
* See https://github.com/winfsp/winfsp/issues/62
|
||||
*/
|
||||
AccessRights = 0;
|
||||
}
|
||||
/* prepare an EXPLICIT_ACCESS to deny the SERVICE_STOP right to Everyone */
|
||||
AccessEntries[1].grfAccessPermissions = SERVICE_STOP;
|
||||
AccessEntries[1].grfAccessMode = DENY_ACCESS;
|
||||
AccessEntries[1].grfInheritance = NO_INHERITANCE;
|
||||
AccessEntries[1].Trustee.pMultipleTrustee = 0;
|
||||
AccessEntries[1].Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
|
||||
AccessEntries[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
|
||||
AccessEntries[1].Trustee.TrusteeType = TRUSTEE_IS_UNKNOWN;
|
||||
AccessEntries[1].Trustee.ptstrName = WorldSid;
|
||||
|
||||
/* do we have the required access rights? */
|
||||
if (AccessEntry.grfAccessPermissions != (AccessRights & AccessEntry.grfAccessPermissions))
|
||||
{
|
||||
/* create a new security descriptor with the new access */
|
||||
LastError = BuildSecurityDescriptorW(0, 0, 1, &AccessEntry, 0, 0, SecurityDescriptor,
|
||||
LastError = BuildSecurityDescriptorW(0, 0, 2, AccessEntries, 0, 0, SecurityDescriptor,
|
||||
&Size, &NewSecurityDescriptor);
|
||||
if (0 != LastError)
|
||||
{
|
||||
@ -545,7 +824,6 @@ static NTSTATUS FspFsctlFixServiceSecurity(HANDLE SvcHandle)
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
@ -559,7 +837,7 @@ exit:
|
||||
NTSTATUS FspFsctlRegister(VOID)
|
||||
{
|
||||
extern HINSTANCE DllInstance;
|
||||
PWSTR DriverName = L"" FSP_FSCTL_DRIVER_NAME;
|
||||
WCHAR DriverName[256];
|
||||
WCHAR DriverPath[MAX_PATH];
|
||||
DWORD Size;
|
||||
SC_HANDLE ScmHandle = 0;
|
||||
@ -568,8 +846,11 @@ NTSTATUS FspFsctlRegister(VOID)
|
||||
SERVICE_DESCRIPTION ServiceDescription;
|
||||
NTSTATUS Result;
|
||||
|
||||
if (0 == GetModuleFileNameW(DllInstance, DriverPath, MAX_PATH))
|
||||
return FspNtStatusFromWin32(GetLastError());
|
||||
FspSxsAppendSuffix(DriverName, sizeof DriverName, L"" FSP_FSCTL_DRIVER_NAME);
|
||||
|
||||
Result = FspGetModuleFileName(DllInstance, DriverPath, MAX_PATH, L"" MyFsctlRegisterPath);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return Result;
|
||||
|
||||
Size = lstrlenW(DriverPath);
|
||||
if (4 < Size &&
|
||||
@ -583,6 +864,14 @@ NTSTATUS FspFsctlRegister(VOID)
|
||||
DriverPath[Size - 2] = L'y';
|
||||
DriverPath[Size - 1] = L's';
|
||||
}
|
||||
else if (4 < Size &&
|
||||
(L'.' == DriverPath[Size - 4]) &&
|
||||
(L'S' == DriverPath[Size - 3] || L's' == DriverPath[Size - 3]) &&
|
||||
(L'Y' == DriverPath[Size - 2] || L'y' == DriverPath[Size - 2]) &&
|
||||
(L'S' == DriverPath[Size - 1] || L's' == DriverPath[Size - 1]) &&
|
||||
(L'\0' == DriverPath[Size]))
|
||||
{
|
||||
}
|
||||
else
|
||||
/* should not happen! */
|
||||
return STATUS_NO_SUCH_DEVICE;
|
||||
@ -649,12 +938,16 @@ exit:
|
||||
|
||||
NTSTATUS FspFsctlUnregister(VOID)
|
||||
{
|
||||
PWSTR DriverName = L"" FSP_FSCTL_DRIVER_NAME;
|
||||
WCHAR DriverName[256];
|
||||
SC_HANDLE ScmHandle = 0;
|
||||
SC_HANDLE SvcHandle = 0;
|
||||
DWORD LastError;
|
||||
NTSTATUS Result;
|
||||
|
||||
FspSxsAppendSuffix(DriverName, sizeof DriverName, L"" FSP_FSCTL_DRIVER_NAME);
|
||||
|
||||
FspFsctlStopService();
|
||||
|
||||
ScmHandle = OpenSCManagerW(0, 0, SC_MANAGER_CREATE_SERVICE);
|
||||
/*
|
||||
* The SC_MANAGER_CREATE_SERVICE access right is not strictly needed here,
|
||||
|
@ -180,7 +180,7 @@ FSP_FUSE_API struct fuse_chan *fsp_fuse_mount(struct fsp_fuse_env *env,
|
||||
const char *mountpoint, struct fuse_args *args)
|
||||
{
|
||||
struct fuse_chan *ch = 0;
|
||||
WCHAR TempMountPointBuf[MAX_PATH], MountPointBuf[MAX_PATH];
|
||||
WCHAR TempMountPointBuf[MAX_PATH], MountPointBuf[MAX_PATH + 4];
|
||||
int Size;
|
||||
|
||||
if (0 == mountpoint || '\0' == mountpoint[0] ||
|
||||
@ -212,6 +212,33 @@ FSP_FUSE_API struct fuse_chan *fsp_fuse_mount(struct fsp_fuse_env *env,
|
||||
MountPointBuf[6] = '\0';
|
||||
Size = 7 * sizeof(WCHAR);
|
||||
}
|
||||
else if (
|
||||
(
|
||||
'\\' == mountpoint[0] &&
|
||||
'\\' == mountpoint[1] &&
|
||||
('?' == mountpoint[2] || '.' == mountpoint[2]) &&
|
||||
'\\' == mountpoint[3]
|
||||
) &&
|
||||
(
|
||||
('A' <= mountpoint[4] && mountpoint[4] <= 'Z') ||
|
||||
('a' <= mountpoint[4] && mountpoint[4] <= 'z')
|
||||
) &&
|
||||
':' == mountpoint[5] && '\\' == mountpoint[6])
|
||||
{
|
||||
MountPointBuf[0] = '\\';
|
||||
MountPointBuf[1] = '\\';
|
||||
MountPointBuf[2] = mountpoint[2];
|
||||
MountPointBuf[3] = '\\';
|
||||
|
||||
Size = 0;
|
||||
if (0 != MultiByteToWideChar(CP_UTF8, 0, mountpoint + 4, -1, TempMountPointBuf, MAX_PATH))
|
||||
Size = GetFullPathNameW(TempMountPointBuf, MAX_PATH, MountPointBuf + 4, 0);
|
||||
|
||||
if (0 == Size || MAX_PATH <= Size)
|
||||
goto fail;
|
||||
|
||||
Size = (Size + 4 + 1) * sizeof(WCHAR);
|
||||
}
|
||||
else if (
|
||||
(
|
||||
('A' <= mountpoint[0] && mountpoint[0] <= 'Z') ||
|
||||
|
@ -70,9 +70,21 @@ NTSTATUS FspNpUnregister(VOID);
|
||||
NTSTATUS FspEventLogRegister(VOID);
|
||||
NTSTATUS FspEventLogUnregister(VOID);
|
||||
|
||||
PWSTR FspSxsSuffix(VOID);
|
||||
PWSTR FspSxsAppendSuffix(PWCHAR Buffer, SIZE_T Size, PWSTR Ident);
|
||||
|
||||
PSID FspWksidNew(WELL_KNOWN_SID_TYPE WellKnownSidType, PNTSTATUS PResult);
|
||||
PSID FspWksidGet(WELL_KNOWN_SID_TYPE WellKnownSidType);
|
||||
|
||||
NTSTATUS FspMountmgrCreateDrive(
|
||||
PUNICODE_STRING VolumeName, GUID *UniqueId, PUNICODE_STRING MountPoint);
|
||||
NTSTATUS FspMountmgrDeleteDrive(
|
||||
PUNICODE_STRING MountPoint);
|
||||
NTSTATUS FspMountmgrNotifyCreateDirectory(
|
||||
PUNICODE_STRING VolumeName, GUID *UniqueId, PUNICODE_STRING MountPoint);
|
||||
NTSTATUS FspMountmgrNotifyDeleteDirectory(
|
||||
PUNICODE_STRING VolumeName, PUNICODE_STRING MountPoint);
|
||||
|
||||
ULONG FspLdapConnect(PWSTR HostName, PVOID *PLdap);
|
||||
VOID FspLdapClose(PVOID Ldap);
|
||||
ULONG FspLdapGetValue(PVOID Ldap, PWSTR Base, ULONG Scope, PWSTR Filter, PWSTR Attribute,
|
||||
@ -81,7 +93,18 @@ ULONG FspLdapGetDefaultNamingContext(PVOID Ldap, PWSTR *PValue);
|
||||
ULONG FspLdapGetTrustPosixOffset(PVOID Ldap, PWSTR Context, PWSTR Domain, PWSTR *PValue);
|
||||
|
||||
PWSTR FspDiagIdent(VOID);
|
||||
HANDLE FspCreateDirectoryFileW(
|
||||
PWSTR FileName,
|
||||
DWORD DesiredAccess,
|
||||
DWORD ShareAccess,
|
||||
PSECURITY_ATTRIBUTES SecurityAttributes,
|
||||
DWORD FlagsAndAttributes);
|
||||
NTSTATUS FspGetModuleVersion(PWSTR ModuleFileName, PUINT32 PVersion);
|
||||
NTSTATUS FspGetModuleFileName(
|
||||
HMODULE Module,
|
||||
PWSTR FileName,
|
||||
ULONG Size,
|
||||
PWSTR RelativePath);
|
||||
|
||||
#define FspFileSystemDirectoryBufferEntryInvalid ((ULONG)-1)
|
||||
VOID FspFileSystemPeekInDirectoryBuffer(PVOID *PDirBuffer,
|
||||
@ -126,6 +149,12 @@ static inline BOOLEAN FspPathIsMountmgrMountPoint(PWSTR FileName)
|
||||
) &&
|
||||
L':' == FileName[5];
|
||||
}
|
||||
static inline BOOLEAN FspPathIsMountmgrDrive(PWSTR FileName)
|
||||
{
|
||||
return
|
||||
FspPathIsMountmgrMountPoint(FileName) &&
|
||||
L'\0' == FileName[6];
|
||||
}
|
||||
|
||||
#define FSP_NEXT_EA(Ea, EaEnd) \
|
||||
(0 != (Ea)->NextEntryOffset ? (PVOID)((PUINT8)(Ea) + (Ea)->NextEntryOffset) : (EaEnd))
|
||||
|
366
src/dll/mount.c
366
src/dll/mount.c
@ -31,6 +31,7 @@ static NTSTATUS (NTAPI *FspNtClose)(
|
||||
HANDLE Handle);
|
||||
static BOOLEAN FspMountDoNotUseLauncherValue;
|
||||
static BOOLEAN FspMountBroadcastDriveChangeValue;
|
||||
static BOOLEAN FspMountUseMountmgrFromFSDValue;
|
||||
|
||||
static VOID FspMountInitializeFromRegistry(VOID)
|
||||
{
|
||||
@ -53,6 +54,14 @@ static VOID FspMountInitializeFromRegistry(VOID)
|
||||
RRF_RT_REG_DWORD, 0, &Value, &Size);
|
||||
if (ERROR_SUCCESS == Result)
|
||||
FspMountBroadcastDriveChangeValue = !!Value;
|
||||
|
||||
Value = 0;
|
||||
Size = sizeof Value;
|
||||
Result = RegGetValueW(HKEY_LOCAL_MACHINE, L"" FSP_FSCTL_PRODUCT_FULL_REGKEY,
|
||||
L"MountUseMountmgrFromFSD",
|
||||
RRF_RT_REG_DWORD, 0, &Value, &Size);
|
||||
if (ERROR_SUCCESS == Result)
|
||||
FspMountUseMountmgrFromFSDValue = !!Value;
|
||||
}
|
||||
|
||||
static BOOL WINAPI FspMountInitialize(
|
||||
@ -80,93 +89,17 @@ static BOOL WINAPI FspMountInitialize(
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static NTSTATUS FspMountmgrControl(ULONG IoControlCode,
|
||||
PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, PULONG POutputBufferLength)
|
||||
static NTSTATUS FspMountSet_Directory(PWSTR VolumeName, PWSTR MountPoint,
|
||||
PSECURITY_DESCRIPTOR SecurityDescriptor, PHANDLE PMountHandle);
|
||||
static NTSTATUS FspMountRemove_Directory(HANDLE MountHandle);
|
||||
|
||||
static NTSTATUS FspMountSet_MountmgrDrive(HANDLE VolumeHandle, PWSTR VolumeName, PWSTR MountPoint)
|
||||
{
|
||||
HANDLE MgrHandle = INVALID_HANDLE_VALUE;
|
||||
DWORD Bytes = 0;
|
||||
NTSTATUS Result;
|
||||
|
||||
if (0 == POutputBufferLength)
|
||||
POutputBufferLength = &Bytes;
|
||||
|
||||
MgrHandle = CreateFileW(L"\\\\.\\MountPointManager",
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
0,
|
||||
OPEN_EXISTING,
|
||||
0,
|
||||
0);
|
||||
if (INVALID_HANDLE_VALUE == MgrHandle)
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!DeviceIoControl(MgrHandle,
|
||||
IoControlCode,
|
||||
InputBuffer, InputBufferLength, OutputBuffer, *POutputBufferLength,
|
||||
&Bytes, 0))
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
}
|
||||
|
||||
*POutputBufferLength = Bytes;
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
if (INVALID_HANDLE_VALUE != MgrHandle)
|
||||
CloseHandle(MgrHandle);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
static NTSTATUS FspMountSet_Mountmgr(HANDLE VolumeHandle, PWSTR VolumeName, PWSTR MountPoint)
|
||||
{
|
||||
/* only support drives for now! (format: \\.\X:) */
|
||||
if (L'\0' != MountPoint[6])
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
/* mountmgr.h */
|
||||
typedef enum
|
||||
{
|
||||
Disabled = 0,
|
||||
Enabled,
|
||||
} MOUNTMGR_AUTO_MOUNT_STATE;
|
||||
typedef struct
|
||||
{
|
||||
MOUNTMGR_AUTO_MOUNT_STATE CurrentState;
|
||||
} MOUNTMGR_QUERY_AUTO_MOUNT;
|
||||
typedef struct
|
||||
{
|
||||
MOUNTMGR_AUTO_MOUNT_STATE NewState;
|
||||
} MOUNTMGR_SET_AUTO_MOUNT;
|
||||
typedef struct
|
||||
{
|
||||
USHORT DeviceNameLength;
|
||||
WCHAR DeviceName[1];
|
||||
} MOUNTMGR_TARGET_NAME;
|
||||
typedef struct
|
||||
{
|
||||
USHORT SymbolicLinkNameOffset;
|
||||
USHORT SymbolicLinkNameLength;
|
||||
USHORT DeviceNameOffset;
|
||||
USHORT DeviceNameLength;
|
||||
} MOUNTMGR_CREATE_POINT_INPUT;
|
||||
if (FspMountUseMountmgrFromFSDValue)
|
||||
/* use MountManager from FSD and exit */
|
||||
return FspFsctlUseMountmgr(VolumeHandle, MountPoint + 4);
|
||||
|
||||
GUID UniqueId;
|
||||
MOUNTMGR_QUERY_AUTO_MOUNT QueryAutoMount;
|
||||
MOUNTMGR_SET_AUTO_MOUNT SetAutoMount;
|
||||
MOUNTMGR_TARGET_NAME *TargetName = 0;
|
||||
MOUNTMGR_CREATE_POINT_INPUT *CreatePointInput = 0;
|
||||
ULONG VolumeNameSize, QueryAutoMountSize, TargetNameSize, CreatePointInputSize;
|
||||
HKEY RegKey;
|
||||
LONG RegResult;
|
||||
WCHAR RegValueName[MAX_PATH];
|
||||
UINT8 RegValueData[sizeof UniqueId];
|
||||
DWORD RegValueNameSize, RegValueDataSize;
|
||||
DWORD RegType;
|
||||
NTSTATUS Result;
|
||||
|
||||
/* transform our volume into one that can be used by the MountManager */
|
||||
@ -174,190 +107,115 @@ static NTSTATUS FspMountSet_Mountmgr(HANDLE VolumeHandle, PWSTR VolumeName, PWST
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
VolumeNameSize = lstrlenW(VolumeName) * sizeof(WCHAR);
|
||||
QueryAutoMountSize = sizeof QueryAutoMount;
|
||||
TargetNameSize = FIELD_OFFSET(MOUNTMGR_TARGET_NAME, DeviceName) + VolumeNameSize;
|
||||
CreatePointInputSize = sizeof *CreatePointInput +
|
||||
sizeof L"\\DosDevices\\X:" - sizeof(WCHAR) + VolumeNameSize;
|
||||
|
||||
TargetName = MemAlloc(TargetNameSize);
|
||||
if (0 == TargetName)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
CreatePointInput = MemAlloc(CreatePointInputSize);
|
||||
if (0 == CreatePointInput)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* query the current AutoMount value and save it */
|
||||
Result = FspMountmgrControl(
|
||||
CTL_CODE('m', 15, METHOD_BUFFERED, FILE_ANY_ACCESS),
|
||||
/* IOCTL_MOUNTMGR_QUERY_AUTO_MOUNT */
|
||||
0, 0, &QueryAutoMount, &QueryAutoMountSize);
|
||||
/* use the MountManager to create the drive */
|
||||
UNICODE_STRING UVolumeName, UMountPoint;
|
||||
UVolumeName.Length = UVolumeName.MaximumLength = (USHORT)(lstrlenW(VolumeName) * sizeof(WCHAR));
|
||||
UVolumeName.Buffer = VolumeName;
|
||||
UMountPoint.Length = UMountPoint.MaximumLength = (USHORT)((lstrlenW(MountPoint) - 4) * sizeof(WCHAR));
|
||||
UMountPoint.Buffer = MountPoint + 4;
|
||||
Result = FspMountmgrCreateDrive(&UVolumeName, &UniqueId, &UMountPoint);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
/* disable AutoMount */
|
||||
SetAutoMount.NewState = 0;
|
||||
Result = FspMountmgrControl(
|
||||
CTL_CODE('m', 16, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
||||
/* IOCTL_MOUNTMGR_SET_AUTO_MOUNT */
|
||||
&SetAutoMount, sizeof SetAutoMount, 0, 0);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
/* announce volume arrival */
|
||||
memset(TargetName, 0, sizeof *TargetName);
|
||||
TargetName->DeviceNameLength = (USHORT)VolumeNameSize;
|
||||
memcpy(TargetName->DeviceName,
|
||||
VolumeName, TargetName->DeviceNameLength);
|
||||
Result = FspMountmgrControl(
|
||||
CTL_CODE('m', 11, METHOD_BUFFERED, FILE_READ_ACCESS),
|
||||
/* IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION */
|
||||
TargetName, TargetNameSize, 0, 0);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
/* reset the AutoMount value to the saved one */
|
||||
SetAutoMount.NewState = QueryAutoMount.CurrentState;
|
||||
FspMountmgrControl(
|
||||
CTL_CODE('m', 16, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
||||
/* IOCTL_MOUNTMGR_SET_AUTO_MOUNT */
|
||||
&SetAutoMount, sizeof SetAutoMount, 0, 0);
|
||||
#if 0
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
#endif
|
||||
|
||||
/* create mount point */
|
||||
memset(CreatePointInput, 0, sizeof *CreatePointInput);
|
||||
CreatePointInput->SymbolicLinkNameOffset = sizeof *CreatePointInput;
|
||||
CreatePointInput->SymbolicLinkNameLength = sizeof L"\\DosDevices\\X:" - sizeof(WCHAR);
|
||||
CreatePointInput->DeviceNameOffset =
|
||||
CreatePointInput->SymbolicLinkNameOffset + CreatePointInput->SymbolicLinkNameLength;
|
||||
CreatePointInput->DeviceNameLength = (USHORT)VolumeNameSize;
|
||||
memcpy((PUINT8)CreatePointInput + CreatePointInput->SymbolicLinkNameOffset,
|
||||
L"\\DosDevices\\X:", CreatePointInput->SymbolicLinkNameLength);
|
||||
((PWCHAR)((PUINT8)CreatePointInput + CreatePointInput->SymbolicLinkNameOffset))[12] =
|
||||
MountPoint[4] & ~0x20;
|
||||
/* convert to uppercase */
|
||||
memcpy((PUINT8)CreatePointInput + CreatePointInput->DeviceNameOffset,
|
||||
VolumeName, CreatePointInput->DeviceNameLength);
|
||||
Result = FspMountmgrControl(
|
||||
CTL_CODE('m', 0, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
||||
/* IOCTL_MOUNTMGR_CREATE_POINT */
|
||||
CreatePointInput, CreatePointInputSize, 0, 0);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
/* HACK: delete the MountManager registry entries */
|
||||
RegResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"System\\MountedDevices",
|
||||
0, KEY_READ | KEY_WRITE, &RegKey);
|
||||
if (ERROR_SUCCESS == RegResult)
|
||||
{
|
||||
for (DWORD I = 0;; I++)
|
||||
{
|
||||
RegValueNameSize = MAX_PATH;
|
||||
RegValueDataSize = sizeof RegValueData;
|
||||
RegResult = RegEnumValueW(RegKey,
|
||||
I, RegValueName, &RegValueNameSize, 0, &RegType, RegValueData, &RegValueDataSize);
|
||||
if (ERROR_NO_MORE_ITEMS == RegResult)
|
||||
break;
|
||||
else if (ERROR_SUCCESS != RegResult)
|
||||
continue;
|
||||
|
||||
if (REG_BINARY == RegType &&
|
||||
sizeof RegValueData == RegValueDataSize &&
|
||||
InlineIsEqualGUID((GUID *)&RegValueData, &UniqueId))
|
||||
{
|
||||
RegResult = RegDeleteValueW(RegKey, RegValueName);
|
||||
if (ERROR_SUCCESS == RegResult)
|
||||
/* reset index after modifying key; only safe way to use RegEnumValueW with modifications */
|
||||
I = -1;
|
||||
}
|
||||
}
|
||||
|
||||
RegCloseKey(RegKey);
|
||||
}
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
MemFree(CreatePointInput);
|
||||
MemFree(TargetName);
|
||||
return Result;
|
||||
}
|
||||
|
||||
static NTSTATUS FspMountSet_MountmgrDirectory(HANDLE VolumeHandle, PWSTR VolumeName, PWSTR MountPoint,
|
||||
PSECURITY_DESCRIPTOR SecurityDescriptor, PHANDLE PMountHandle)
|
||||
{
|
||||
GUID UniqueId;
|
||||
HANDLE MountHandle = INVALID_HANDLE_VALUE;
|
||||
NTSTATUS Result;
|
||||
|
||||
*PMountHandle = 0;
|
||||
|
||||
/* create the directory mount point */
|
||||
Result = FspMountSet_Directory(VolumeName, MountPoint + 4, SecurityDescriptor, &MountHandle);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
if (FspMountUseMountmgrFromFSDValue)
|
||||
{
|
||||
/* use MountManager from FSD and exit */
|
||||
Result = FspFsctlUseMountmgr(VolumeHandle, MountPoint + 4);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
*PMountHandle = MountHandle;
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* transform our volume into one that can be used by the MountManager */
|
||||
Result = FspFsctlMakeMountdev(VolumeHandle, FALSE, &UniqueId);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
/* notify the MountManager about the created directory mount point */
|
||||
UNICODE_STRING UVolumeName, UMountPoint;
|
||||
UVolumeName.Length = UVolumeName.MaximumLength = (USHORT)(lstrlenW(VolumeName) * sizeof(WCHAR));
|
||||
UVolumeName.Buffer = VolumeName;
|
||||
UMountPoint.Length = UMountPoint.MaximumLength = (USHORT)((lstrlenW(MountPoint) - 4) * sizeof(WCHAR));
|
||||
UMountPoint.Buffer = MountPoint + 4;
|
||||
Result = FspMountmgrNotifyCreateDirectory(&UVolumeName, &UniqueId, &UMountPoint);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
*PMountHandle = MountHandle;
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
if (!NT_SUCCESS(Result) && INVALID_HANDLE_VALUE != MountHandle)
|
||||
FspMountRemove_Directory(MountHandle);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
static NTSTATUS FspMountRemove_Mountmgr(PWSTR MountPoint)
|
||||
static NTSTATUS FspMountRemove_MountmgrDrive(HANDLE VolumeHandle, PWSTR MountPoint)
|
||||
{
|
||||
/* mountmgr.h */
|
||||
typedef struct
|
||||
{
|
||||
ULONG SymbolicLinkNameOffset;
|
||||
USHORT SymbolicLinkNameLength;
|
||||
USHORT Reserved1;
|
||||
ULONG UniqueIdOffset;
|
||||
USHORT UniqueIdLength;
|
||||
USHORT Reserved2;
|
||||
ULONG DeviceNameOffset;
|
||||
USHORT DeviceNameLength;
|
||||
USHORT Reserved3;
|
||||
} MOUNTMGR_MOUNT_POINT;
|
||||
typedef struct
|
||||
{
|
||||
ULONG Size;
|
||||
ULONG NumberOfMountPoints;
|
||||
MOUNTMGR_MOUNT_POINT MountPoints[1];
|
||||
} MOUNTMGR_MOUNT_POINTS;
|
||||
if (FspMountUseMountmgrFromFSDValue)
|
||||
/* use MountManager from FSD and exit */
|
||||
return FspFsctlUseMountmgr(VolumeHandle, 0);
|
||||
|
||||
MOUNTMGR_MOUNT_POINT *Input = 0;
|
||||
MOUNTMGR_MOUNT_POINTS *Output = 0;
|
||||
ULONG InputSize, OutputSize;
|
||||
/* use the MountManager to delete the drive */
|
||||
UNICODE_STRING UMountPoint;
|
||||
UMountPoint.Length = UMountPoint.MaximumLength = (USHORT)((lstrlenW(MountPoint) - 4) * sizeof(WCHAR));
|
||||
UMountPoint.Buffer = MountPoint + 4;
|
||||
return FspMountmgrDeleteDrive(&UMountPoint);
|
||||
}
|
||||
|
||||
static NTSTATUS FspMountRemove_MountmgrDirectory(HANDLE VolumeHandle, PWSTR VolumeName, PWSTR MountPoint,
|
||||
HANDLE MountHandle)
|
||||
{
|
||||
NTSTATUS Result;
|
||||
|
||||
InputSize = sizeof *Input + sizeof L"\\DosDevices\\X:" - sizeof(WCHAR);
|
||||
OutputSize = 4096;
|
||||
|
||||
Input = MemAlloc(InputSize);
|
||||
if (0 == Input)
|
||||
if (FspMountUseMountmgrFromFSDValue)
|
||||
/* use MountManager from FSD, but do not exit; additional processing is required below */
|
||||
FspFsctlUseMountmgr(VolumeHandle, 0);
|
||||
else
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
/* notify the MountManager about the deleted directory mount point */
|
||||
UNICODE_STRING UVolumeName, UMountPoint;
|
||||
UVolumeName.Length = UVolumeName.MaximumLength = (USHORT)(lstrlenW(VolumeName) * sizeof(WCHAR));
|
||||
UVolumeName.Buffer = VolumeName;
|
||||
UMountPoint.Length = UMountPoint.MaximumLength = (USHORT)((lstrlenW(MountPoint) - 4) * sizeof(WCHAR));
|
||||
UMountPoint.Buffer = MountPoint + 4;
|
||||
FspMountmgrNotifyDeleteDirectory(&UVolumeName, &UMountPoint);
|
||||
}
|
||||
|
||||
Output = MemAlloc(OutputSize);
|
||||
if (0 == Output)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
memset(Input, 0, sizeof *Input);
|
||||
Input->SymbolicLinkNameOffset = sizeof *Input;
|
||||
Input->SymbolicLinkNameLength = sizeof L"\\DosDevices\\X:" - sizeof(WCHAR);
|
||||
memcpy((PUINT8)Input + Input->SymbolicLinkNameOffset,
|
||||
L"\\DosDevices\\X:", Input->SymbolicLinkNameLength);
|
||||
((PWCHAR)((PUINT8)Input + Input->SymbolicLinkNameOffset))[12] = MountPoint[4] & ~0x20;
|
||||
/* convert to uppercase */
|
||||
Result = FspMountmgrControl(
|
||||
CTL_CODE('m', 1, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
||||
/* IOCTL_MOUNTMGR_DELETE_POINTS */
|
||||
Input, InputSize, Output, &OutputSize);
|
||||
/* delete the directory mount point */
|
||||
Result = FspMountRemove_Directory(MountHandle);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
MemFree(Output);
|
||||
MemFree(Input);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
@ -630,14 +488,12 @@ static NTSTATUS FspMountSet_Directory(PWSTR VolumeName, PWSTR MountPoint,
|
||||
SecurityAttributes.nLength = sizeof SecurityAttributes;
|
||||
SecurityAttributes.lpSecurityDescriptor = SecurityDescriptor;
|
||||
|
||||
MountHandle = CreateFileW(MountPoint,
|
||||
MountHandle = FspCreateDirectoryFileW(MountPoint,
|
||||
FILE_WRITE_ATTRIBUTES,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
&SecurityAttributes,
|
||||
CREATE_NEW,
|
||||
FILE_ATTRIBUTE_DIRECTORY |
|
||||
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS | FILE_FLAG_DELETE_ON_CLOSE,
|
||||
0);
|
||||
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS | FILE_FLAG_DELETE_ON_CLOSE);
|
||||
if (INVALID_HANDLE_VALUE == MountHandle)
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
@ -740,8 +596,11 @@ FSP_API NTSTATUS FspMountSet(FSP_MOUNT_DESC *Desc)
|
||||
Desc->MountPoint[0] = L'*';
|
||||
return STATUS_NO_SUCH_DEVICE;
|
||||
}
|
||||
else if (FspPathIsMountmgrDrive(Desc->MountPoint))
|
||||
return FspMountSet_MountmgrDrive(Desc->VolumeHandle, Desc->VolumeName, Desc->MountPoint);
|
||||
else if (FspPathIsMountmgrMountPoint(Desc->MountPoint))
|
||||
return FspMountSet_Mountmgr(Desc->VolumeHandle, Desc->VolumeName, Desc->MountPoint);
|
||||
return FspMountSet_MountmgrDirectory(Desc->VolumeHandle, Desc->VolumeName, Desc->MountPoint,
|
||||
Desc->Security, &Desc->MountHandle);
|
||||
else if (FspPathIsDrive(Desc->MountPoint))
|
||||
return FspMountSet_Drive(Desc->VolumeName, Desc->MountPoint,
|
||||
&Desc->MountHandle);
|
||||
@ -754,8 +613,11 @@ FSP_API NTSTATUS FspMountRemove(FSP_MOUNT_DESC *Desc)
|
||||
{
|
||||
InitOnceExecuteOnce(&FspMountInitOnce, FspMountInitialize, 0, 0);
|
||||
|
||||
if (FspPathIsMountmgrMountPoint(Desc->MountPoint))
|
||||
return FspMountRemove_Mountmgr(Desc->MountPoint);
|
||||
if (FspPathIsMountmgrDrive(Desc->MountPoint))
|
||||
return FspMountRemove_MountmgrDrive(Desc->VolumeHandle, Desc->MountPoint);
|
||||
else if (FspPathIsMountmgrMountPoint(Desc->MountPoint))
|
||||
return FspMountRemove_MountmgrDirectory(Desc->VolumeHandle, Desc->VolumeName, Desc->MountPoint,
|
||||
Desc->MountHandle);
|
||||
else if (FspPathIsDrive(Desc->MountPoint))
|
||||
return FspMountRemove_Drive(Desc->VolumeName, Desc->MountPoint, Desc->MountHandle);
|
||||
else
|
||||
|
30
src/dll/np.c
30
src/dll/np.c
@ -1152,15 +1152,34 @@ DWORD APIENTRY NPCloseEnum(HANDLE hEnum)
|
||||
NTSTATUS FspNpRegister(VOID)
|
||||
{
|
||||
extern HINSTANCE DllInstance;
|
||||
WCHAR ProviderPath[MAX_PATH];
|
||||
WCHAR DllPath[MAX_PATH], ProviderPath[MAX_PATH];
|
||||
PWSTR VersionInfoPath;
|
||||
BOOLEAN HasPercent;
|
||||
WCHAR RegBuffer[1024];
|
||||
PWSTR P, Part;
|
||||
DWORD RegResult, RegType, RegBufferSize, RegBufferOffset;
|
||||
HKEY RegKey;
|
||||
BOOLEAN FoundProvider;
|
||||
NTSTATUS Result;
|
||||
|
||||
if (0 == GetModuleFileNameW(DllInstance, ProviderPath, MAX_PATH))
|
||||
VersionInfoPath = ProviderPath;
|
||||
HasPercent = FALSE;
|
||||
for (P = L"" MyNpRegisterPath; *P; P++)
|
||||
if ('%' == *P)
|
||||
{
|
||||
HasPercent = TRUE;
|
||||
break;
|
||||
}
|
||||
if (HasPercent)
|
||||
{
|
||||
VersionInfoPath = DllPath;
|
||||
if (0 == GetModuleFileNameW(DllInstance, DllPath, MAX_PATH))
|
||||
return FspNtStatusFromWin32(GetLastError());
|
||||
}
|
||||
|
||||
Result = FspGetModuleFileName(DllInstance, ProviderPath, MAX_PATH, L"" MyNpRegisterPath);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return Result;
|
||||
|
||||
RegResult = RegCreateKeyExW(
|
||||
HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\" FSP_NP_NAME,
|
||||
@ -1187,12 +1206,12 @@ NTSTATUS FspNpRegister(VOID)
|
||||
DWORD Size;
|
||||
PWSTR Description;
|
||||
|
||||
Size = GetFileVersionInfoSizeW(ProviderPath, &Size/*dummy*/);
|
||||
Size = GetFileVersionInfoSizeW(VersionInfoPath, &Size/*dummy*/);
|
||||
if (0 < Size)
|
||||
{
|
||||
VersionInfo = MemAlloc(Size);
|
||||
if (0 != VersionInfo &&
|
||||
GetFileVersionInfoW(ProviderPath, 0, Size, VersionInfo) &&
|
||||
GetFileVersionInfoW(VersionInfoPath, 0, Size, VersionInfo) &&
|
||||
VerQueryValueW(VersionInfo, L"\\StringFileInfo\\040904b0\\FileDescription",
|
||||
&Description, &Size))
|
||||
{
|
||||
@ -1208,7 +1227,8 @@ NTSTATUS FspNpRegister(VOID)
|
||||
goto close_and_exit;
|
||||
|
||||
RegResult = RegSetValueExW(RegKey,
|
||||
L"ProviderPath", 0, REG_SZ, (PVOID)ProviderPath, (lstrlenW(ProviderPath) + 1) * sizeof(WCHAR));
|
||||
L"ProviderPath", 0, HasPercent ? REG_EXPAND_SZ : REG_SZ,
|
||||
(PVOID)ProviderPath, (lstrlenW(ProviderPath) + 1) * sizeof(WCHAR));
|
||||
if (ERROR_SUCCESS != RegResult)
|
||||
goto close_and_exit;
|
||||
|
||||
|
214
src/dll/sxs.c
Normal file
214
src/dll/sxs.c
Normal file
@ -0,0 +1,214 @@
|
||||
/**
|
||||
* @file dll/sxs.c
|
||||
*
|
||||
* @copyright 2015-2022 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
*
|
||||
* You can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License version 3 as published by the Free Software
|
||||
* Foundation.
|
||||
*
|
||||
* Licensees holding a valid commercial license may use this software
|
||||
* in accordance with the commercial license agreement provided in
|
||||
* conjunction with the software. The terms and conditions of any such
|
||||
* commercial license agreement shall govern, supersede, and render
|
||||
* ineffective any application of the GPLv3 license to this software,
|
||||
* notwithstanding of any reference thereto in the software or
|
||||
* associated repository.
|
||||
*/
|
||||
|
||||
#include <dll/library.h>
|
||||
|
||||
static INIT_ONCE FspSxsIdentInitOnce = INIT_ONCE_STATIC_INIT;
|
||||
static WCHAR FspSxsIdentBuf[32 + 2] = L"";
|
||||
|
||||
static BOOLEAN FspSxsIdentInitializeFromFile(VOID)
|
||||
{
|
||||
extern HINSTANCE DllInstance;
|
||||
WCHAR Path[MAX_PATH];
|
||||
DWORD Size;
|
||||
HANDLE Handle = INVALID_HANDLE_VALUE;
|
||||
CHAR Buffer[ARRAYSIZE(FspSxsIdentBuf) - 2];
|
||||
WCHAR WBuffer[ARRAYSIZE(FspSxsIdentBuf) - 2];
|
||||
BOOLEAN Result = FALSE;
|
||||
|
||||
if (0 == GetModuleFileNameW(DllInstance, Path, MAX_PATH))
|
||||
goto exit;
|
||||
|
||||
Size = lstrlenW(Path);
|
||||
if (4 < Size &&
|
||||
(L'.' == Path[Size - 4]) &&
|
||||
(L'D' == Path[Size - 3] || L'd' == Path[Size - 3]) &&
|
||||
(L'L' == Path[Size - 2] || L'l' == Path[Size - 2]) &&
|
||||
(L'L' == Path[Size - 1] || L'l' == Path[Size - 1]) &&
|
||||
(L'\0' == Path[Size]))
|
||||
;
|
||||
else
|
||||
goto exit;
|
||||
|
||||
Size -= 4;
|
||||
for (PWCHAR P = Path + Size - 1; Path <= P; P--)
|
||||
{
|
||||
if (L'\\' == *P)
|
||||
break;
|
||||
if (L'-' == *P)
|
||||
{
|
||||
/* arch */
|
||||
Size = (DWORD)(P - Path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Path[Size + 0] = L'.';
|
||||
Path[Size + 1] = L's';
|
||||
Path[Size + 2] = L'x';
|
||||
Path[Size + 3] = L's';
|
||||
Path[Size + 4] = L'\0';
|
||||
|
||||
Handle = CreateFileW(
|
||||
Path,
|
||||
FILE_READ_DATA,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
0,
|
||||
OPEN_EXISTING,
|
||||
0,
|
||||
0);
|
||||
if (INVALID_HANDLE_VALUE == Handle)
|
||||
goto exit;
|
||||
|
||||
if (!ReadFile(Handle, Buffer, sizeof Buffer, &Size, 0))
|
||||
goto exit;
|
||||
|
||||
for (PCHAR P = Buffer, EndP = P + Size; EndP > P; P++)
|
||||
if ('\r' == *P || '\n' == *P)
|
||||
{
|
||||
Size = (DWORD)(P - Buffer);
|
||||
break;
|
||||
}
|
||||
|
||||
Size = MultiByteToWideChar(CP_UTF8, 0,
|
||||
Buffer, Size, WBuffer, ARRAYSIZE(WBuffer));
|
||||
if (0 == Size)
|
||||
goto exit;
|
||||
|
||||
FspSxsIdentBuf[0] = FSP_SXS_SEPARATOR_CHAR;
|
||||
memcpy(FspSxsIdentBuf + 1, WBuffer, Size * sizeof(WCHAR));
|
||||
FspSxsIdentBuf[1 + Size] = L'\0';
|
||||
|
||||
Result = TRUE;
|
||||
|
||||
exit:
|
||||
if (INVALID_HANDLE_VALUE != Handle)
|
||||
CloseHandle(Handle);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
static BOOLEAN FspSxsIdentInitializeFromDirectory(VOID)
|
||||
{
|
||||
extern HINSTANCE DllInstance;
|
||||
WCHAR Path[MAX_PATH];
|
||||
HANDLE Handle = INVALID_HANDLE_VALUE;
|
||||
WCHAR FinalPath[MAX_PATH];
|
||||
PWCHAR P, EndP, Q, EndQ;
|
||||
PWCHAR Ident = 0;
|
||||
BOOLEAN Result = FALSE;
|
||||
|
||||
if (0 == GetModuleFileNameW(DllInstance, Path, MAX_PATH))
|
||||
goto exit;
|
||||
|
||||
Handle = CreateFileW(
|
||||
Path,
|
||||
0,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
0,
|
||||
OPEN_EXISTING,
|
||||
0,
|
||||
0);
|
||||
if (INVALID_HANDLE_VALUE == Handle)
|
||||
goto exit;
|
||||
|
||||
if (!GetFinalPathNameByHandleW(Handle, FinalPath, MAX_PATH, VOLUME_NAME_NONE))
|
||||
goto exit;
|
||||
|
||||
EndP = FinalPath + lstrlenW(FinalPath);
|
||||
for (P = EndP - 1; FinalPath <= P; P--)
|
||||
{
|
||||
if (L'\\' == *P &&
|
||||
P + 9 < EndP &&
|
||||
(L'S' == P[1] || L's' == P[1]) &&
|
||||
(L'X' == P[2] || L'x' == P[2]) &&
|
||||
(L'S' == P[3] || L's' == P[3]) &&
|
||||
L'\\' == P[4] &&
|
||||
(L'S' == P[5] || L's' == P[5]) &&
|
||||
(L'X' == P[6] || L'x' == P[6]) &&
|
||||
(L'S' == P[7] || L's' == P[7]) &&
|
||||
L'.' == P[8] &&
|
||||
L'\\' != P[9])
|
||||
{
|
||||
Ident = P + 9;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (0 == Ident)
|
||||
goto exit;
|
||||
|
||||
FspSxsIdentBuf[0] = FSP_SXS_SEPARATOR_CHAR;
|
||||
EndQ = FspSxsIdentBuf + (ARRAYSIZE(FspSxsIdentBuf) - 1);
|
||||
for (P = Ident, Q = FspSxsIdentBuf + 1; EndP > P && EndQ > Q && L'\\' != *P; P++, Q++)
|
||||
*Q = *P;
|
||||
*Q = L'\0';
|
||||
|
||||
Result = TRUE;
|
||||
|
||||
exit:
|
||||
if (INVALID_HANDLE_VALUE != Handle)
|
||||
CloseHandle(Handle);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
static BOOL WINAPI FspSxsIdentInitialize(
|
||||
PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
|
||||
{
|
||||
if (FspSxsIdentInitializeFromFile())
|
||||
goto exit;
|
||||
|
||||
if (FspSxsIdentInitializeFromDirectory())
|
||||
goto exit;
|
||||
|
||||
exit:
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
FSP_API PWSTR FspSxsIdent(VOID)
|
||||
{
|
||||
InitOnceExecuteOnce(&FspSxsIdentInitOnce, FspSxsIdentInitialize, 0, 0);
|
||||
return FspSxsIdentBuf + 1;
|
||||
}
|
||||
|
||||
PWSTR FspSxsSuffix(VOID)
|
||||
{
|
||||
InitOnceExecuteOnce(&FspSxsIdentInitOnce, FspSxsIdentInitialize, 0, 0);
|
||||
return FspSxsIdentBuf;
|
||||
}
|
||||
|
||||
PWSTR FspSxsAppendSuffix(PWCHAR Buffer, SIZE_T Size, PWSTR Ident)
|
||||
{
|
||||
PWSTR Suffix;
|
||||
SIZE_T IdentSize, SuffixSize;
|
||||
|
||||
Suffix = FspSxsSuffix();
|
||||
IdentSize = lstrlenW(Ident) * sizeof(WCHAR);
|
||||
SuffixSize = lstrlenW(Suffix) * sizeof(WCHAR);
|
||||
if (Size < IdentSize + SuffixSize + sizeof(WCHAR))
|
||||
return L"<INVALID>";
|
||||
|
||||
memcpy(Buffer, Ident, IdentSize);
|
||||
memcpy((PUINT8)Buffer + IdentSize, Suffix, SuffixSize);
|
||||
*(PWCHAR)((PUINT8)Buffer + IdentSize + SuffixSize) = L'\0';
|
||||
|
||||
return Buffer;
|
||||
}
|
170
src/dll/util.c
170
src/dll/util.c
@ -21,6 +21,7 @@
|
||||
|
||||
#include <dll/library.h>
|
||||
#include <aclapi.h>
|
||||
#include <shlwapi.h>
|
||||
|
||||
static INIT_ONCE FspDiagIdentInitOnce = INIT_ONCE_STATIC_INIT;
|
||||
static WCHAR FspDiagIdentBuf[20] = L"UNKNOWN";
|
||||
@ -63,6 +64,145 @@ PWSTR FspDiagIdent(VOID)
|
||||
return FspDiagIdentBuf;
|
||||
}
|
||||
|
||||
static INIT_ONCE FspCreateDirectoryFileInitOnce = INIT_ONCE_STATIC_INIT;
|
||||
static NTSTATUS (NTAPI *FspNtCreateFile)(
|
||||
PHANDLE FileHandle,
|
||||
ACCESS_MASK DesiredAccess,
|
||||
POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
PIO_STATUS_BLOCK IoStatusBlock,
|
||||
PLARGE_INTEGER AllocationSize,
|
||||
ULONG FileAttributes,
|
||||
ULONG ShareAccess,
|
||||
ULONG CreateDisposition,
|
||||
ULONG CreateOptions,
|
||||
PVOID EaBuffer,
|
||||
ULONG EaLength);
|
||||
|
||||
static BOOL WINAPI FspCreateDirectoryFileInitialize(
|
||||
PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
|
||||
{
|
||||
HANDLE Handle;
|
||||
|
||||
Handle = GetModuleHandleW(L"ntdll.dll");
|
||||
if (0 != Handle)
|
||||
FspNtCreateFile = (PVOID)GetProcAddress(Handle, "NtCreateFile");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
HANDLE FspCreateDirectoryFileW(
|
||||
PWSTR FileName,
|
||||
DWORD DesiredAccess,
|
||||
DWORD ShareAccess,
|
||||
PSECURITY_ATTRIBUTES SecurityAttributes,
|
||||
DWORD FlagsAndAttributes)
|
||||
{
|
||||
InitOnceExecuteOnce(&FspCreateDirectoryFileInitOnce, FspCreateDirectoryFileInitialize, 0, 0);
|
||||
if (0 == FspNtCreateFile)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_FUNCTION);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
HANDLE Handle = INVALID_HANDLE_VALUE, ParentHandle = INVALID_HANDLE_VALUE;
|
||||
PWSTR FullFileName = 0;
|
||||
WCHAR *FilePart, FilePartChar;
|
||||
DWORD Length;
|
||||
UNICODE_STRING UFullFileName;
|
||||
OBJECT_ATTRIBUTES Obja;
|
||||
ULONG CreateFlags;
|
||||
IO_STATUS_BLOCK IoStatus;
|
||||
|
||||
Length = GetFullPathNameW(FileName, 0, 0, 0);
|
||||
if (0 == Length)
|
||||
goto exit;
|
||||
|
||||
FullFileName = MemAlloc((Length + 1) * sizeof(WCHAR));
|
||||
if (0 == FullFileName)
|
||||
{
|
||||
SetLastError(ERROR_NO_SYSTEM_RESOURCES);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Length = GetFullPathNameW(FileName, Length + 1, FullFileName, &FilePart);
|
||||
if (0 == Length)
|
||||
goto exit;
|
||||
|
||||
FilePartChar = *FilePart;
|
||||
*FilePart = L'\0';
|
||||
|
||||
ParentHandle = CreateFileW(
|
||||
FullFileName,
|
||||
0,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
0,
|
||||
OPEN_EXISTING,
|
||||
FILE_FLAG_BACKUP_SEMANTICS,
|
||||
0);
|
||||
if (INVALID_HANDLE_VALUE == ParentHandle)
|
||||
goto exit;
|
||||
|
||||
*FilePart = FilePartChar;
|
||||
|
||||
UFullFileName.Length = UFullFileName.MaximumLength = (USHORT)(lstrlenW(FilePart) * sizeof(WCHAR));
|
||||
UFullFileName.Buffer = FilePart;
|
||||
|
||||
memset(&Obja, 0, sizeof Obja);
|
||||
Obja.Length = sizeof Obja;
|
||||
Obja.ObjectName = &UFullFileName;
|
||||
Obja.Attributes =
|
||||
(!(FlagsAndAttributes & FILE_FLAG_POSIX_SEMANTICS) ? OBJ_CASE_INSENSITIVE : 0) |
|
||||
(SecurityAttributes->bInheritHandle ? OBJ_INHERIT : 0);
|
||||
Obja.RootDirectory = ParentHandle;
|
||||
Obja.SecurityDescriptor = SecurityAttributes->lpSecurityDescriptor;
|
||||
|
||||
DesiredAccess |=
|
||||
SYNCHRONIZE |
|
||||
FILE_READ_ATTRIBUTES |
|
||||
((FlagsAndAttributes & FILE_FLAG_DELETE_ON_CLOSE) ? DELETE : 0);
|
||||
|
||||
CreateFlags =
|
||||
FILE_DIRECTORY_FILE |
|
||||
((FlagsAndAttributes & FILE_FLAG_WRITE_THROUGH) ? FILE_WRITE_THROUGH : 0) |
|
||||
((FlagsAndAttributes & FILE_FLAG_OVERLAPPED) ? FILE_SYNCHRONOUS_IO_NONALERT : 0) |
|
||||
((FlagsAndAttributes & FILE_FLAG_NO_BUFFERING) ? FILE_NO_INTERMEDIATE_BUFFERING : 0) |
|
||||
((FlagsAndAttributes & FILE_FLAG_RANDOM_ACCESS) ? FILE_RANDOM_ACCESS : 0) |
|
||||
((FlagsAndAttributes & FILE_FLAG_SEQUENTIAL_SCAN) ? FILE_SEQUENTIAL_ONLY : 0) |
|
||||
((FlagsAndAttributes & FILE_FLAG_DELETE_ON_CLOSE) ? FILE_DELETE_ON_CLOSE : 0) |
|
||||
((FlagsAndAttributes & FILE_FLAG_BACKUP_SEMANTICS) ? FILE_OPEN_FOR_BACKUP_INTENT : 0) |
|
||||
((FlagsAndAttributes & FILE_FLAG_OPEN_REPARSE_POINT) ? FILE_OPEN_REPARSE_POINT : 0) |
|
||||
((FlagsAndAttributes & FILE_FLAG_OPEN_NO_RECALL) ? FILE_OPEN_NO_RECALL : 0);
|
||||
|
||||
IoStatus.Status = FspNtCreateFile(
|
||||
&Handle,
|
||||
DesiredAccess,
|
||||
&Obja,
|
||||
&IoStatus,
|
||||
0,
|
||||
FlagsAndAttributes & (0x7fff & ~FILE_ATTRIBUTE_DIRECTORY),
|
||||
ShareAccess,
|
||||
FILE_CREATE,
|
||||
CreateFlags,
|
||||
0,
|
||||
0);
|
||||
if (!NT_SUCCESS(IoStatus.Status))
|
||||
{
|
||||
SetLastError(FspWin32FromNtStatus(IoStatus.Status));
|
||||
Handle = INVALID_HANDLE_VALUE;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
SetLastError(0);
|
||||
|
||||
exit:
|
||||
if (INVALID_HANDLE_VALUE != ParentHandle)
|
||||
CloseHandle(ParentHandle);
|
||||
|
||||
MemFree(FullFileName);
|
||||
|
||||
return Handle;
|
||||
}
|
||||
|
||||
FSP_API NTSTATUS FspCallNamedPipeSecurely(PWSTR PipeName,
|
||||
PVOID InBuffer, ULONG InBufferSize, PVOID OutBuffer, ULONG OutBufferSize,
|
||||
PULONG PBytesTransferred, ULONG Timeout,
|
||||
@ -248,3 +388,33 @@ NTSTATUS FspGetModuleVersion(PWSTR ModuleFileName, PUINT32 PVersion)
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS FspGetModuleFileName(
|
||||
HMODULE Module,
|
||||
PWSTR FileName,
|
||||
ULONG Size,
|
||||
PWSTR RelativePath)
|
||||
{
|
||||
if (MAX_PATH > Size)
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
|
||||
if (0 != RelativePath &&
|
||||
L'\0' != RelativePath[0] &&
|
||||
(L'.' != RelativePath[0] || L'\0' != RelativePath[1]))
|
||||
{
|
||||
WCHAR Temp[MAX_PATH];
|
||||
|
||||
if (0 == GetModuleFileNameW(Module, Temp, MAX_PATH))
|
||||
return FspNtStatusFromWin32(GetLastError());
|
||||
|
||||
if (0 == PathCombineW(FileName, Temp, RelativePath))
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (0 == GetModuleFileNameW(Module, FileName, MAX_PATH))
|
||||
return FspNtStatusFromWin32(GetLastError());
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -62,10 +62,12 @@ static void usage(void)
|
||||
"\n"
|
||||
"commands:\n"
|
||||
" lsvol list file system devices (volumes)\n"
|
||||
//" list list running file system processes\n"
|
||||
//" kill kill file system process\n"
|
||||
" id [NAME|SID|UID] print user id\n"
|
||||
" perm [PATH|SDDL|UID:GID:MODE] print permissions\n",
|
||||
" perm [PATH|SDDL|UID:GID:MODE] print permissions\n"
|
||||
" lsdrv list drivers\n"
|
||||
" load load driver\n"
|
||||
" unload unload driver (requires load driver priv)\n"
|
||||
" ver print version\n",
|
||||
PROGNAME);
|
||||
}
|
||||
|
||||
@ -237,6 +239,29 @@ NTSTATUS FspToolGetSidFromName(PWSTR Name, PSID *PSid)
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static int ver(int argc, wchar_t **argv)
|
||||
{
|
||||
if (1 != argc)
|
||||
usage();
|
||||
|
||||
NTSTATUS Result;
|
||||
UINT32 Version;
|
||||
PWSTR SxsIdent;
|
||||
|
||||
Result = FspVersion(&Version);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return FspWin32FromNtStatus(Result);
|
||||
|
||||
SxsIdent = FspSxsIdent();
|
||||
|
||||
if (L'\0' == SxsIdent[0])
|
||||
info("%u.%u", Version >> 16, Version & 0xFFFF);
|
||||
else
|
||||
info("%u.%u (SxS=%S)", Version >> 16, Version & 0xFFFF, SxsIdent);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static NTSTATUS lsvol_dev(PWSTR DeviceName)
|
||||
{
|
||||
NTSTATUS Result;
|
||||
@ -255,7 +280,7 @@ static NTSTATUS lsvol_dev(PWSTR DeviceName)
|
||||
if (L'\0' == *P)
|
||||
{
|
||||
Drive[0] = FspToolGetDriveLetter(&LogicalDrives, VolumeName);
|
||||
info("%-4S%S", Drive[0] ? Drive : L"", VolumeName);
|
||||
info("%-4S%S", Drive[0] ? Drive : L"-", VolumeName);
|
||||
VolumeName = P + 1;
|
||||
}
|
||||
|
||||
@ -541,6 +566,52 @@ static int perm(int argc, wchar_t **argv)
|
||||
return FspWin32FromNtStatus(Result);
|
||||
}
|
||||
|
||||
static VOID lsdrv_enumfn(PVOID Context, PWSTR ServiceName, BOOLEAN Running)
|
||||
{
|
||||
info("%-4s%S", Running ? "R" : "-", ServiceName);
|
||||
}
|
||||
|
||||
static int lsdrv(int argc, wchar_t **argv)
|
||||
{
|
||||
if (1 != argc)
|
||||
usage();
|
||||
|
||||
NTSTATUS Result;
|
||||
|
||||
Result = FspFsctlEnumServices(lsdrv_enumfn, 0);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return FspWin32FromNtStatus(Result);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int load(int argc, wchar_t **argv)
|
||||
{
|
||||
if (1 != argc)
|
||||
usage();
|
||||
|
||||
NTSTATUS Result;
|
||||
|
||||
Result = FspFsctlStartService();
|
||||
if (!NT_SUCCESS(Result))
|
||||
return FspWin32FromNtStatus(Result);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int unload(int argc, wchar_t **argv)
|
||||
{
|
||||
if (1 != argc)
|
||||
usage();
|
||||
|
||||
NTSTATUS Result;
|
||||
|
||||
Result = FspFsctlStopService();
|
||||
if (!NT_SUCCESS(Result))
|
||||
return FspWin32FromNtStatus(Result);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wmain(int argc, wchar_t **argv)
|
||||
{
|
||||
argc--;
|
||||
@ -549,6 +620,9 @@ int wmain(int argc, wchar_t **argv)
|
||||
if (0 == argc)
|
||||
usage();
|
||||
|
||||
if (0 == invariant_wcscmp(L"ver", argv[0]))
|
||||
return ver(argc, argv);
|
||||
else
|
||||
if (0 == invariant_wcscmp(L"lsvol", argv[0]))
|
||||
return lsvol(argc, argv);
|
||||
else
|
||||
@ -557,6 +631,15 @@ int wmain(int argc, wchar_t **argv)
|
||||
else
|
||||
if (0 == invariant_wcscmp(L"perm", argv[0]))
|
||||
return perm(argc, argv);
|
||||
else
|
||||
if (0 == invariant_wcscmp(L"lsdrv", argv[0]))
|
||||
return lsdrv(argc, argv);
|
||||
else
|
||||
if (0 == invariant_wcscmp(L"load", argv[0]))
|
||||
return load(argc, argv);
|
||||
else
|
||||
if (0 == invariant_wcscmp(L"unload", argv[0]))
|
||||
return unload(argc, argv);
|
||||
else
|
||||
usage();
|
||||
|
||||
|
@ -30,4 +30,10 @@
|
||||
*/
|
||||
#define FSP_CFG_REJECT_EARLY_IRP
|
||||
|
||||
/*
|
||||
* SxS separator. The '+' in "WinFsp+20220906T173701Z".
|
||||
*/
|
||||
#define FSP_SXS_SEPARATOR_CHAR '+'
|
||||
#define FSP_SXS_SEPARATOR_STRING "+"
|
||||
|
||||
#endif
|
||||
|
599
src/shared/ku/mountmgr.c
Normal file
599
src/shared/ku/mountmgr.c
Normal file
@ -0,0 +1,599 @@
|
||||
/**
|
||||
* @file shared/ku/mountmgr.c
|
||||
*
|
||||
* @copyright 2015-2022 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
*
|
||||
* You can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License version 3 as published by the Free Software
|
||||
* Foundation.
|
||||
*
|
||||
* Licensees holding a valid commercial license may use this software
|
||||
* in accordance with the commercial license agreement provided in
|
||||
* conjunction with the software. The terms and conditions of any such
|
||||
* commercial license agreement shall govern, supersede, and render
|
||||
* ineffective any application of the GPLv3 license to this software,
|
||||
* notwithstanding of any reference thereto in the software or
|
||||
* associated repository.
|
||||
*/
|
||||
|
||||
#include <shared/ku/library.h>
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4459) /* declaration of 'identifier' hides global declaration */
|
||||
|
||||
static NTSTATUS FspMountmgrControl(ULONG IoControlCode,
|
||||
PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, PULONG POutputBufferLength);
|
||||
static NTSTATUS FspMountmgrNotifyVolumeArrival(
|
||||
PUNICODE_STRING VolumeName, GUID *UniqueId);
|
||||
static NTSTATUS FspMountmgrNotifyMountPoint(
|
||||
PUNICODE_STRING VolumeName, PUNICODE_STRING MountPoint, BOOLEAN Created);
|
||||
static NTSTATUS FspMountmgrCreateMountPoint(
|
||||
PUNICODE_STRING VolumeName, PUNICODE_STRING MountPoint);
|
||||
static NTSTATUS FspMountmgrDeleteMountPoint(
|
||||
PUNICODE_STRING MountPoint);
|
||||
static VOID FspMountmgrDeleteRegistry(
|
||||
GUID *UniqueId);
|
||||
NTSTATUS FspMountmgrCreateDrive(
|
||||
PUNICODE_STRING VolumeName, GUID *UniqueId, PUNICODE_STRING MountPoint);
|
||||
NTSTATUS FspMountmgrDeleteDrive(
|
||||
PUNICODE_STRING MountPoint);
|
||||
NTSTATUS FspMountmgrNotifyCreateDirectory(
|
||||
PUNICODE_STRING VolumeName, GUID *UniqueId, PUNICODE_STRING MountPoint);
|
||||
NTSTATUS FspMountmgrNotifyDeleteDirectory(
|
||||
PUNICODE_STRING VolumeName, PUNICODE_STRING MountPoint);
|
||||
|
||||
#if defined(_KERNEL_MODE)
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(PAGE, FspMountmgrControl)
|
||||
#pragma alloc_text(PAGE, FspMountmgrNotifyVolumeArrival)
|
||||
#pragma alloc_text(PAGE, FspMountmgrNotifyMountPoint)
|
||||
#pragma alloc_text(PAGE, FspMountmgrCreateMountPoint)
|
||||
#pragma alloc_text(PAGE, FspMountmgrDeleteMountPoint)
|
||||
#pragma alloc_text(PAGE, FspMountmgrCreateDrive)
|
||||
#pragma alloc_text(PAGE, FspMountmgrDeleteDrive)
|
||||
#pragma alloc_text(PAGE, FspMountmgrNotifyCreateDirectory)
|
||||
#pragma alloc_text(PAGE, FspMountmgrNotifyDeleteDirectory)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static NTSTATUS FspMountmgrControl(ULONG IoControlCode,
|
||||
PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, PULONG POutputBufferLength)
|
||||
{
|
||||
#if defined(_KERNEL_MODE)
|
||||
FSP_KU_CODE;
|
||||
|
||||
UNICODE_STRING DeviceName;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
IO_STATUS_BLOCK IoStatus;
|
||||
HANDLE MgrHandle = 0;
|
||||
ULONG Bytes = 0;
|
||||
|
||||
if (0 == POutputBufferLength)
|
||||
POutputBufferLength = &Bytes;
|
||||
|
||||
RtlInitUnicodeString(&DeviceName, L"\\Device\\MountPointManager");
|
||||
InitializeObjectAttributes(
|
||||
&ObjectAttributes,
|
||||
&DeviceName,
|
||||
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
|
||||
0/*RootDirectory*/,
|
||||
0);
|
||||
|
||||
IoStatus.Status = ZwOpenFile(
|
||||
&MgrHandle,
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
&ObjectAttributes,
|
||||
&IoStatus,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
FILE_SYNCHRONOUS_IO_ALERT);
|
||||
if (!NT_SUCCESS(IoStatus.Status))
|
||||
goto exit;
|
||||
|
||||
IoStatus.Status = ZwDeviceIoControlFile(
|
||||
MgrHandle,
|
||||
0, 0, 0,
|
||||
&IoStatus,
|
||||
IoControlCode,
|
||||
InputBuffer, InputBufferLength, OutputBuffer, *POutputBufferLength);
|
||||
if (!NT_SUCCESS(IoStatus.Status))
|
||||
goto exit;
|
||||
|
||||
*POutputBufferLength = (ULONG)IoStatus.Information;
|
||||
IoStatus.Status = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
if (0 != MgrHandle)
|
||||
ZwClose(MgrHandle);
|
||||
|
||||
return IoStatus.Status;
|
||||
#else
|
||||
HANDLE MgrHandle = INVALID_HANDLE_VALUE;
|
||||
DWORD Bytes = 0;
|
||||
NTSTATUS Result;
|
||||
|
||||
if (0 == POutputBufferLength)
|
||||
POutputBufferLength = &Bytes;
|
||||
|
||||
MgrHandle = CreateFileW(L"\\\\.\\MountPointManager",
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
0,
|
||||
OPEN_EXISTING,
|
||||
0,
|
||||
0);
|
||||
if (INVALID_HANDLE_VALUE == MgrHandle)
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!DeviceIoControl(MgrHandle,
|
||||
IoControlCode,
|
||||
InputBuffer, InputBufferLength, OutputBuffer, *POutputBufferLength,
|
||||
&Bytes, 0))
|
||||
{
|
||||
Result = FspNtStatusFromWin32(GetLastError());
|
||||
goto exit;
|
||||
}
|
||||
|
||||
*POutputBufferLength = Bytes;
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
if (INVALID_HANDLE_VALUE != MgrHandle)
|
||||
CloseHandle(MgrHandle);
|
||||
|
||||
return Result;
|
||||
#endif
|
||||
}
|
||||
|
||||
static NTSTATUS FspMountmgrNotifyVolumeArrival(
|
||||
PUNICODE_STRING VolumeName, GUID *UniqueId)
|
||||
{
|
||||
FSP_KU_CODE;
|
||||
|
||||
/* mountmgr.h */
|
||||
typedef enum
|
||||
{
|
||||
Disabled = 0,
|
||||
Enabled,
|
||||
} MOUNTMGR_AUTO_MOUNT_STATE;
|
||||
typedef struct
|
||||
{
|
||||
MOUNTMGR_AUTO_MOUNT_STATE CurrentState;
|
||||
} MOUNTMGR_QUERY_AUTO_MOUNT;
|
||||
typedef struct
|
||||
{
|
||||
MOUNTMGR_AUTO_MOUNT_STATE NewState;
|
||||
} MOUNTMGR_SET_AUTO_MOUNT;
|
||||
typedef struct
|
||||
{
|
||||
USHORT DeviceNameLength;
|
||||
WCHAR DeviceName[1];
|
||||
} MOUNTMGR_TARGET_NAME;
|
||||
|
||||
MOUNTMGR_QUERY_AUTO_MOUNT QueryAutoMount;
|
||||
MOUNTMGR_SET_AUTO_MOUNT SetAutoMount;
|
||||
MOUNTMGR_TARGET_NAME *TargetName = 0;
|
||||
ULONG QueryAutoMountSize, TargetNameSize;
|
||||
NTSTATUS Result;
|
||||
|
||||
QueryAutoMountSize = sizeof QueryAutoMount;
|
||||
TargetNameSize = FIELD_OFFSET(MOUNTMGR_TARGET_NAME, DeviceName) + VolumeName->Length;
|
||||
|
||||
TargetName = MemAlloc(TargetNameSize);
|
||||
if (0 == TargetName)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* query the current AutoMount value and save it */
|
||||
Result = FspMountmgrControl(
|
||||
CTL_CODE('m', 15, METHOD_BUFFERED, FILE_ANY_ACCESS),
|
||||
/* IOCTL_MOUNTMGR_QUERY_AUTO_MOUNT */
|
||||
0, 0, &QueryAutoMount, &QueryAutoMountSize);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
/* disable AutoMount */
|
||||
SetAutoMount.NewState = 0;
|
||||
Result = FspMountmgrControl(
|
||||
CTL_CODE('m', 16, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
||||
/* IOCTL_MOUNTMGR_SET_AUTO_MOUNT */
|
||||
&SetAutoMount, sizeof SetAutoMount, 0, 0);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
/* announce volume arrival */
|
||||
memset(TargetName, 0, sizeof *TargetName);
|
||||
TargetName->DeviceNameLength = VolumeName->Length;
|
||||
memcpy(TargetName->DeviceName, VolumeName->Buffer, VolumeName->Length);
|
||||
Result = FspMountmgrControl(
|
||||
CTL_CODE('m', 11, METHOD_BUFFERED, FILE_READ_ACCESS),
|
||||
/* IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION */
|
||||
TargetName, TargetNameSize, 0, 0);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
/* reset the AutoMount value to the saved one */
|
||||
SetAutoMount.NewState = QueryAutoMount.CurrentState;
|
||||
FspMountmgrControl(
|
||||
CTL_CODE('m', 16, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
||||
/* IOCTL_MOUNTMGR_SET_AUTO_MOUNT */
|
||||
&SetAutoMount, sizeof SetAutoMount, 0, 0);
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
MemFree(TargetName);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
static NTSTATUS FspMountmgrNotifyMountPoint(
|
||||
PUNICODE_STRING VolumeName, PUNICODE_STRING MountPoint, BOOLEAN Created)
|
||||
{
|
||||
FSP_KU_CODE;
|
||||
|
||||
/* mountmgr.h */
|
||||
typedef struct
|
||||
{
|
||||
USHORT SourceVolumeNameOffset;
|
||||
USHORT SourceVolumeNameLength;
|
||||
USHORT TargetVolumeNameOffset;
|
||||
USHORT TargetVolumeNameLength;
|
||||
} MOUNTMGR_VOLUME_MOUNT_POINT;
|
||||
|
||||
MOUNTMGR_VOLUME_MOUNT_POINT *VolumeMountPoint = 0;
|
||||
ULONG VolumeMountPointSize;
|
||||
NTSTATUS Result;
|
||||
|
||||
VolumeMountPointSize = sizeof *VolumeMountPoint +
|
||||
sizeof L"\\DosDevices\\" - sizeof(WCHAR) + MountPoint->Length + VolumeName->Length;
|
||||
|
||||
VolumeMountPoint = MemAlloc(VolumeMountPointSize);
|
||||
if (0 == VolumeMountPoint)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* notify volume mount point created/deleted */
|
||||
memset(VolumeMountPoint, 0, sizeof *VolumeMountPoint);
|
||||
VolumeMountPoint->SourceVolumeNameOffset = sizeof *VolumeMountPoint;
|
||||
VolumeMountPoint->SourceVolumeNameLength = (USHORT)(
|
||||
sizeof L"\\DosDevices\\" - sizeof(WCHAR) + MountPoint->Length);
|
||||
VolumeMountPoint->TargetVolumeNameOffset =
|
||||
VolumeMountPoint->SourceVolumeNameOffset + VolumeMountPoint->SourceVolumeNameLength;
|
||||
VolumeMountPoint->TargetVolumeNameLength = VolumeName->Length;
|
||||
memcpy((PUINT8)VolumeMountPoint + VolumeMountPoint->SourceVolumeNameOffset,
|
||||
L"\\DosDevices\\", sizeof L"\\DosDevices\\" - sizeof(WCHAR));
|
||||
memcpy((PUINT8)VolumeMountPoint +
|
||||
VolumeMountPoint->SourceVolumeNameOffset + (sizeof L"\\DosDevices\\" - sizeof(WCHAR)),
|
||||
MountPoint->Buffer, MountPoint->Length);
|
||||
memcpy((PUINT8)VolumeMountPoint + VolumeMountPoint->TargetVolumeNameOffset,
|
||||
VolumeName->Buffer, VolumeName->Length);
|
||||
Result = FspMountmgrControl(
|
||||
Created ?
|
||||
CTL_CODE('m', 6, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) :
|
||||
/* IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_CREATED */
|
||||
CTL_CODE('m', 7, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
||||
/* IOCTL_MOUNTMGR_VOLUME_MOUNT_POINT_DELETED */
|
||||
VolumeMountPoint, VolumeMountPointSize, 0, 0);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
MemFree(VolumeMountPoint);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
static NTSTATUS FspMountmgrCreateMountPoint(
|
||||
PUNICODE_STRING VolumeName, PUNICODE_STRING MountPoint)
|
||||
{
|
||||
FSP_KU_CODE;
|
||||
|
||||
/* mountmgr.h */
|
||||
typedef struct
|
||||
{
|
||||
USHORT SymbolicLinkNameOffset;
|
||||
USHORT SymbolicLinkNameLength;
|
||||
USHORT DeviceNameOffset;
|
||||
USHORT DeviceNameLength;
|
||||
} MOUNTMGR_CREATE_POINT_INPUT;
|
||||
|
||||
MOUNTMGR_CREATE_POINT_INPUT *CreatePointInput = 0;
|
||||
ULONG CreatePointInputSize;
|
||||
NTSTATUS Result;
|
||||
|
||||
CreatePointInputSize = sizeof *CreatePointInput +
|
||||
sizeof L"\\DosDevices\\X:" - sizeof(WCHAR) + VolumeName->Length;
|
||||
|
||||
CreatePointInput = MemAlloc(CreatePointInputSize);
|
||||
if (0 == CreatePointInput)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* create mount point */
|
||||
memset(CreatePointInput, 0, sizeof *CreatePointInput);
|
||||
CreatePointInput->SymbolicLinkNameOffset = sizeof *CreatePointInput;
|
||||
CreatePointInput->SymbolicLinkNameLength = sizeof L"\\DosDevices\\X:" - sizeof(WCHAR);
|
||||
CreatePointInput->DeviceNameOffset =
|
||||
CreatePointInput->SymbolicLinkNameOffset + CreatePointInput->SymbolicLinkNameLength;
|
||||
CreatePointInput->DeviceNameLength = VolumeName->Length;
|
||||
memcpy((PUINT8)CreatePointInput + CreatePointInput->SymbolicLinkNameOffset,
|
||||
L"\\DosDevices\\X:", CreatePointInput->SymbolicLinkNameLength);
|
||||
((PWCHAR)((PUINT8)CreatePointInput + CreatePointInput->SymbolicLinkNameOffset))[12] =
|
||||
MountPoint->Buffer[0] & ~0x20;
|
||||
/* convert to uppercase */
|
||||
memcpy((PUINT8)CreatePointInput + CreatePointInput->DeviceNameOffset,
|
||||
VolumeName->Buffer, VolumeName->Length);
|
||||
Result = FspMountmgrControl(
|
||||
CTL_CODE('m', 0, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
||||
/* IOCTL_MOUNTMGR_CREATE_POINT */
|
||||
CreatePointInput, CreatePointInputSize, 0, 0);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
MemFree(CreatePointInput);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
static NTSTATUS FspMountmgrDeleteMountPoint(
|
||||
PUNICODE_STRING MountPoint)
|
||||
{
|
||||
FSP_KU_CODE;
|
||||
|
||||
/* mountmgr.h */
|
||||
typedef struct
|
||||
{
|
||||
ULONG SymbolicLinkNameOffset;
|
||||
USHORT SymbolicLinkNameLength;
|
||||
USHORT Reserved1;
|
||||
ULONG UniqueIdOffset;
|
||||
USHORT UniqueIdLength;
|
||||
USHORT Reserved2;
|
||||
ULONG DeviceNameOffset;
|
||||
USHORT DeviceNameLength;
|
||||
USHORT Reserved3;
|
||||
} MOUNTMGR_MOUNT_POINT;
|
||||
typedef struct
|
||||
{
|
||||
ULONG Size;
|
||||
ULONG NumberOfMountPoints;
|
||||
MOUNTMGR_MOUNT_POINT MountPoints[1];
|
||||
} MOUNTMGR_MOUNT_POINTS;
|
||||
|
||||
MOUNTMGR_MOUNT_POINT *Input = 0;
|
||||
MOUNTMGR_MOUNT_POINTS *Output = 0;
|
||||
ULONG InputSize, OutputSize;
|
||||
NTSTATUS Result;
|
||||
|
||||
InputSize = sizeof *Input + sizeof L"\\DosDevices\\X:" - sizeof(WCHAR);
|
||||
OutputSize = 4096;
|
||||
|
||||
Input = MemAlloc(InputSize);
|
||||
if (0 == Input)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Output = MemAlloc(OutputSize);
|
||||
if (0 == Output)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* delete mount point */
|
||||
memset(Input, 0, sizeof *Input);
|
||||
Input->SymbolicLinkNameOffset = sizeof *Input;
|
||||
Input->SymbolicLinkNameLength = sizeof L"\\DosDevices\\X:" - sizeof(WCHAR);
|
||||
memcpy((PUINT8)Input + Input->SymbolicLinkNameOffset,
|
||||
L"\\DosDevices\\X:", Input->SymbolicLinkNameLength);
|
||||
((PWCHAR)((PUINT8)Input + Input->SymbolicLinkNameOffset))[12] =
|
||||
MountPoint->Buffer[0] & ~0x20;
|
||||
/* convert to uppercase */
|
||||
Result = FspMountmgrControl(
|
||||
CTL_CODE('m', 1, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS),
|
||||
/* IOCTL_MOUNTMGR_DELETE_POINTS */
|
||||
Input, InputSize, Output, &OutputSize);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
MemFree(Output);
|
||||
MemFree(Input);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
static VOID FspMountmgrDeleteRegistry(GUID *UniqueId)
|
||||
{
|
||||
#if defined(_KERNEL_MODE)
|
||||
FSP_KU_CODE;
|
||||
|
||||
UNICODE_STRING Path;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
HANDLE Handle = 0;
|
||||
union
|
||||
{
|
||||
KEY_VALUE_FULL_INFORMATION V;
|
||||
UINT8 B[FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name) + 255 + sizeof *UniqueId];
|
||||
} FullInformation;
|
||||
ULONG FullInformationLength;
|
||||
UNICODE_STRING ValueName;
|
||||
NTSTATUS Result;
|
||||
|
||||
RtlInitUnicodeString(&Path, L"\\Registry\\Machine\\System\\MountedDevices");
|
||||
InitializeObjectAttributes(
|
||||
&ObjectAttributes,
|
||||
&Path,
|
||||
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
|
||||
0/*RootDirectory*/,
|
||||
0);
|
||||
|
||||
Result = ZwOpenKey(&Handle, KEY_QUERY_VALUE, &ObjectAttributes);
|
||||
if (NT_SUCCESS(Result))
|
||||
{
|
||||
for (ULONG I = 0;; I++)
|
||||
{
|
||||
Result = ZwEnumerateValueKey(Handle,
|
||||
I, KeyValueFullInformation, &FullInformation,
|
||||
sizeof FullInformation, &FullInformationLength);
|
||||
if (STATUS_NO_MORE_ENTRIES == Result)
|
||||
break;
|
||||
else if (!NT_SUCCESS(Result))
|
||||
continue;
|
||||
|
||||
if (REG_BINARY == FullInformation.V.Type &&
|
||||
sizeof *UniqueId == FullInformation.V.DataLength &&
|
||||
InlineIsEqualGUID((GUID *)((PUINT8)&FullInformation.V + FullInformation.V.DataOffset),
|
||||
UniqueId))
|
||||
{
|
||||
ValueName.Length = ValueName.MaximumLength = (USHORT)FullInformation.V.NameLength;
|
||||
ValueName.Buffer = FullInformation.V.Name;
|
||||
Result = ZwDeleteValueKey(Handle, &ValueName);
|
||||
if (NT_SUCCESS(Result))
|
||||
/* reset index after modifying key; only safe way to use RegEnumValueW with modifications */
|
||||
I = (ULONG)-1;
|
||||
}
|
||||
}
|
||||
|
||||
ZwClose(Handle);
|
||||
}
|
||||
#else
|
||||
HKEY RegKey;
|
||||
LONG RegResult;
|
||||
WCHAR RegValueName[MAX_PATH];
|
||||
UINT8 RegValueData[sizeof *UniqueId];
|
||||
DWORD RegValueNameSize, RegValueDataSize;
|
||||
DWORD RegType;
|
||||
|
||||
RegResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"System\\MountedDevices",
|
||||
0, KEY_READ | KEY_WRITE, &RegKey);
|
||||
if (ERROR_SUCCESS == RegResult)
|
||||
{
|
||||
for (DWORD I = 0;; I++)
|
||||
{
|
||||
RegValueNameSize = MAX_PATH;
|
||||
RegValueDataSize = sizeof RegValueData;
|
||||
RegResult = RegEnumValueW(RegKey,
|
||||
I, RegValueName, &RegValueNameSize, 0, &RegType, RegValueData, &RegValueDataSize);
|
||||
if (ERROR_NO_MORE_ITEMS == RegResult)
|
||||
break;
|
||||
else if (ERROR_SUCCESS != RegResult)
|
||||
continue;
|
||||
|
||||
if (REG_BINARY == RegType &&
|
||||
sizeof RegValueData == RegValueDataSize &&
|
||||
InlineIsEqualGUID((GUID *)&RegValueData, UniqueId))
|
||||
{
|
||||
RegResult = RegDeleteValueW(RegKey, RegValueName);
|
||||
if (ERROR_SUCCESS == RegResult)
|
||||
/* reset index after modifying key; only safe way to use RegEnumValueW with modifications */
|
||||
I = -1;
|
||||
}
|
||||
}
|
||||
|
||||
RegCloseKey(RegKey);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
NTSTATUS FspMountmgrCreateDrive(
|
||||
PUNICODE_STRING VolumeName, GUID *UniqueId, PUNICODE_STRING MountPoint)
|
||||
{
|
||||
FSP_KU_CODE;
|
||||
|
||||
NTSTATUS Result;
|
||||
|
||||
/* notify the MountManager about the new volume */
|
||||
Result = FspMountmgrNotifyVolumeArrival(VolumeName, UniqueId);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
/* use the MountManager to create the drive */
|
||||
Result = FspMountmgrCreateMountPoint(VolumeName, MountPoint);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
/* HACK: delete the MountManager registry entries */
|
||||
FspMountmgrDeleteRegistry(UniqueId);
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
return Result;
|
||||
}
|
||||
|
||||
NTSTATUS FspMountmgrDeleteDrive(
|
||||
PUNICODE_STRING MountPoint)
|
||||
{
|
||||
FSP_KU_CODE;
|
||||
|
||||
NTSTATUS Result;
|
||||
|
||||
/* use the MountManager to delete the drive */
|
||||
Result = FspMountmgrDeleteMountPoint(MountPoint);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
return Result;
|
||||
}
|
||||
|
||||
NTSTATUS FspMountmgrNotifyCreateDirectory(
|
||||
PUNICODE_STRING VolumeName, GUID *UniqueId, PUNICODE_STRING MountPoint)
|
||||
{
|
||||
FSP_KU_CODE;
|
||||
|
||||
NTSTATUS Result;
|
||||
|
||||
/* notify the MountManager about the new volume */
|
||||
Result = FspMountmgrNotifyVolumeArrival(VolumeName, UniqueId);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
/* notify the MountManager about the created directory mount point */
|
||||
Result = FspMountmgrNotifyMountPoint(VolumeName, MountPoint, TRUE);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
/* HACK: delete the MountManager registry entries */
|
||||
FspMountmgrDeleteRegistry(UniqueId);
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
return Result;
|
||||
}
|
||||
|
||||
NTSTATUS FspMountmgrNotifyDeleteDirectory(
|
||||
PUNICODE_STRING VolumeName, PUNICODE_STRING MountPoint)
|
||||
{
|
||||
FSP_KU_CODE;
|
||||
|
||||
/* notify the MountManager about the deleted directory mount point */
|
||||
return FspMountmgrNotifyMountPoint(VolumeName, MountPoint, FALSE);
|
||||
}
|
||||
|
||||
#pragma warning(pop)
|
@ -30,6 +30,7 @@ NTSTATUS FspDeviceCreate(UINT32 Kind, ULONG ExtraSize,
|
||||
PDEVICE_OBJECT *PDeviceObject);
|
||||
NTSTATUS FspDeviceInitialize(PDEVICE_OBJECT DeviceObject);
|
||||
VOID FspDeviceDelete(PDEVICE_OBJECT DeviceObject);
|
||||
VOID FspDeviceDoIoDeleteDevice(PDEVICE_OBJECT DeviceObject);
|
||||
BOOLEAN FspDeviceReference(PDEVICE_OBJECT DeviceObject);
|
||||
VOID FspDeviceDereference(PDEVICE_OBJECT DeviceObject);
|
||||
_IRQL_requires_(DISPATCH_LEVEL)
|
||||
@ -59,19 +60,21 @@ VOID FspFsvolDeviceGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_I
|
||||
BOOLEAN FspFsvolDeviceTryGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_INFO *VolumeInfo);
|
||||
VOID FspFsvolDeviceSetVolumeInfo(PDEVICE_OBJECT DeviceObject, const FSP_FSCTL_VOLUME_INFO *VolumeInfo);
|
||||
VOID FspFsvolDeviceInvalidateVolumeInfo(PDEVICE_OBJECT DeviceObject);
|
||||
static NTSTATUS FspFsvrtDeviceInit(PDEVICE_OBJECT DeviceObject);
|
||||
static VOID FspFsvrtDeviceFini(PDEVICE_OBJECT DeviceObject);
|
||||
static NTSTATUS FspFsmupDeviceInit(PDEVICE_OBJECT DeviceObject);
|
||||
static VOID FspFsmupDeviceFini(PDEVICE_OBJECT DeviceObject);
|
||||
NTSTATUS FspDeviceCopyList(
|
||||
PDEVICE_OBJECT **PDeviceObjects, PULONG PDeviceObjectCount);
|
||||
VOID FspDeviceDeleteList(
|
||||
PDEVICE_OBJECT *DeviceObjects, ULONG DeviceObjectCount);
|
||||
VOID FspDeviceDeleteAll(VOID);
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(PAGE, FspDeviceCreateSecure)
|
||||
#pragma alloc_text(PAGE, FspDeviceCreate)
|
||||
#pragma alloc_text(PAGE, FspDeviceInitialize)
|
||||
#pragma alloc_text(PAGE, FspDeviceDelete)
|
||||
#pragma alloc_text(PAGE, FspDeviceDoIoDeleteDevice)
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceInit)
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceFini)
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceCopyContextList)
|
||||
@ -84,11 +87,12 @@ VOID FspDeviceDeleteAll(VOID);
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceCompareContextByName)
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceAllocateContextByName)
|
||||
#pragma alloc_text(PAGE, FspFsvolDeviceFreeContextByName)
|
||||
#pragma alloc_text(PAGE, FspFsvrtDeviceInit)
|
||||
#pragma alloc_text(PAGE, FspFsvrtDeviceFini)
|
||||
#pragma alloc_text(PAGE, FspFsmupDeviceInit)
|
||||
#pragma alloc_text(PAGE, FspFsmupDeviceFini)
|
||||
#pragma alloc_text(PAGE, FspDeviceCopyList)
|
||||
#pragma alloc_text(PAGE, FspDeviceDeleteList)
|
||||
#pragma alloc_text(PAGE, FspDeviceDeleteAll)
|
||||
#endif
|
||||
|
||||
NTSTATUS FspDeviceCreateSecure(UINT32 Kind, ULONG ExtraSize,
|
||||
@ -171,7 +175,7 @@ NTSTATUS FspDeviceInitialize(PDEVICE_OBJECT DeviceObject)
|
||||
Result = FspFsvolDeviceInit(DeviceObject);
|
||||
break;
|
||||
case FspFsvrtDeviceExtensionKind:
|
||||
Result = STATUS_SUCCESS;
|
||||
Result = FspFsvrtDeviceInit(DeviceObject);
|
||||
break;
|
||||
case FspFsmupDeviceExtensionKind:
|
||||
Result = FspFsmupDeviceInit(DeviceObject);
|
||||
@ -202,6 +206,7 @@ VOID FspDeviceDelete(PDEVICE_OBJECT DeviceObject)
|
||||
FspFsvolDeviceFini(DeviceObject);
|
||||
break;
|
||||
case FspFsvrtDeviceExtensionKind:
|
||||
FspFsvrtDeviceFini(DeviceObject);
|
||||
break;
|
||||
case FspFsmupDeviceExtensionKind:
|
||||
FspFsmupDeviceFini(DeviceObject);
|
||||
@ -213,12 +218,16 @@ VOID FspDeviceDelete(PDEVICE_OBJECT DeviceObject)
|
||||
return;
|
||||
}
|
||||
|
||||
#if DBG
|
||||
#pragma prefast(suppress:28175, "Debugging only: ok to access DeviceObject->Size")
|
||||
RtlFillMemory(&DeviceExtension->Kind,
|
||||
(PUINT8)DeviceObject + DeviceObject->Size - (PUINT8)&DeviceExtension->Kind, 0xBD);
|
||||
#endif
|
||||
FspDeviceDoIoDeleteDevice(DeviceObject);
|
||||
}
|
||||
|
||||
VOID FspDeviceDoIoDeleteDevice(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
FSP_DEVICE_EXTENSION *DeviceExtension = FspDeviceExtension(DeviceObject);
|
||||
|
||||
if (0 == InterlockedCompareExchange(&DeviceExtension->DidIoDeleteDevice, 1, 0))
|
||||
IoDeleteDevice(DeviceObject);
|
||||
}
|
||||
|
||||
@ -848,6 +857,27 @@ VOID FspFsvolDeviceInvalidateVolumeInfo(PDEVICE_OBJECT DeviceObject)
|
||||
KeReleaseSpinLock(&FsvolDeviceExtension->InfoSpinLock, Irql);
|
||||
}
|
||||
|
||||
static NTSTATUS FspFsvrtDeviceInit(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(DeviceObject);
|
||||
|
||||
ExInitializeFastMutex(&FsvrtDeviceExtension->MountMutex);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static VOID FspFsvrtDeviceFini(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(DeviceObject);
|
||||
|
||||
if (0 != FsvrtDeviceExtension->MountPoint.Buffer)
|
||||
FspFree(FsvrtDeviceExtension->MountPoint.Buffer);
|
||||
}
|
||||
|
||||
static NTSTATUS FspFsmupDeviceInit(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
PAGED_CODE();
|
||||
@ -916,22 +946,4 @@ VOID FspDeviceDeleteList(
|
||||
FspFree(DeviceObjects);
|
||||
}
|
||||
|
||||
VOID FspDeviceDeleteAll(VOID)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
NTSTATUS Result;
|
||||
PDEVICE_OBJECT *DeviceObjects = 0;
|
||||
ULONG DeviceObjectCount = 0;
|
||||
|
||||
Result = FspDeviceCopyList(&DeviceObjects, &DeviceObjectCount);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return;
|
||||
|
||||
for (ULONG i = 0; DeviceObjectCount > i; i++)
|
||||
FspDeviceDelete(DeviceObjects[i]);
|
||||
|
||||
FspDeviceDeleteList(DeviceObjects, DeviceObjectCount);
|
||||
}
|
||||
|
||||
FAST_MUTEX FspDeviceGlobalMutex;
|
||||
|
@ -55,6 +55,7 @@ NTSTATUS FspDeviceInitializeAllTimers(VOID)
|
||||
VOID FspDeviceFinalizeAllTimers(VOID)
|
||||
{
|
||||
KeCancelTimer(&FspDeviceTimer);
|
||||
KeFlushQueuedDpcs();
|
||||
|
||||
#if DBG
|
||||
KIRQL Irql;
|
||||
|
212
src/sys/driver.c
212
src/sys/driver.c
@ -22,15 +22,24 @@
|
||||
#include <sys/driver.h>
|
||||
|
||||
DRIVER_INITIALIZE DriverEntry;
|
||||
static DRIVER_UNLOAD DriverUnload;
|
||||
static VOID FspDriverMultiVersionInitialize(VOID);
|
||||
static NTSTATUS FspDriverInitializeDevices(VOID);
|
||||
static VOID FspDriverFinalizeDevices(VOID);
|
||||
static VOID FspDriverFinalizeDevicesForUnload(VOID);
|
||||
static VOID FspDriverFinalizeDevicesEx(BOOLEAN DeleteDevices);
|
||||
NTSTATUS FspDriverUnload(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(INIT, DriverEntry)
|
||||
#pragma alloc_text(PAGE, DriverUnload)
|
||||
#pragma alloc_text(INIT, FspDriverMultiVersionInitialize)
|
||||
#pragma alloc_text(PAGE, FspDriverInitializeDevices)
|
||||
#pragma alloc_text(PAGE, FspDriverFinalizeDevices)
|
||||
#pragma alloc_text(PAGE, FspDriverFinalizeDevicesForUnload)
|
||||
#pragma alloc_text(PAGE, FspDriverFinalizeDevicesEx)
|
||||
#pragma alloc_text(PAGE, FspDriverUnload)
|
||||
#endif
|
||||
|
||||
NTSTATUS DriverEntry(
|
||||
@ -40,7 +49,10 @@ NTSTATUS DriverEntry(
|
||||
|
||||
FSP_TRACE_INIT();
|
||||
|
||||
FspSxsIdentInitialize(&DriverObject->DriverName);
|
||||
|
||||
/* setup the driver object */
|
||||
DriverObject->DriverUnload = DriverUnload;
|
||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = FspCreate;
|
||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = FspClose;
|
||||
DriverObject->MajorFunction[IRP_MJ_READ] = FspRead;
|
||||
@ -128,6 +140,7 @@ NTSTATUS DriverEntry(
|
||||
FspDriverObject = DriverObject;
|
||||
FspDriverMultiVersionInitialize();
|
||||
|
||||
ExInitializeFastMutex(&FspDriverUnloadMutex);
|
||||
ExInitializeFastMutex(&FspDeviceGlobalMutex);
|
||||
|
||||
Result = FspSiloInitialize(FspDriverInitializeDevices, FspDriverFinalizeDevices);
|
||||
@ -150,6 +163,10 @@ NTSTATUS DriverEntry(
|
||||
goto exit;
|
||||
InitDoneDevices = TRUE;
|
||||
|
||||
Result = FspSiloPostInitialize();
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
@ -172,6 +189,26 @@ exit:
|
||||
&DriverObject->DriverName, RegistryPath);
|
||||
}
|
||||
|
||||
VOID DriverUnload(
|
||||
PDRIVER_OBJECT DriverObject)
|
||||
{
|
||||
FSP_ENTER_VOID(PAGED_CODE());
|
||||
|
||||
FspDriverFinalizeDevices();
|
||||
|
||||
FspDeviceFinalizeAllTimers();
|
||||
|
||||
FspProcessBufferFinalize();
|
||||
|
||||
FspSiloFinalize();
|
||||
|
||||
FSP_TRACE_FINI();
|
||||
|
||||
#pragma prefast(suppress:28175, "We are in DriverUnload: ok to access DriverName")
|
||||
FSP_LEAVE_VOID("DriverName=\"%wZ\"",
|
||||
&DriverObject->DriverName);
|
||||
}
|
||||
|
||||
static VOID FspDriverMultiVersionInitialize(VOID)
|
||||
{
|
||||
FspProcessorCount = KeQueryActiveProcessorCount(0);
|
||||
@ -202,6 +239,8 @@ static NTSTATUS FspDriverInitializeDevices(VOID)
|
||||
FSP_SILO_GLOBALS *Globals;
|
||||
UNICODE_STRING DeviceSddl;
|
||||
UNICODE_STRING DeviceName;
|
||||
WCHAR DeviceNameBuf[128];
|
||||
UNICODE_STRING SymlinkName;
|
||||
GUID Guid;
|
||||
NTSTATUS Result;
|
||||
|
||||
@ -210,20 +249,46 @@ static NTSTATUS FspDriverInitializeDevices(VOID)
|
||||
|
||||
/* create the file system control device objects */
|
||||
RtlInitUnicodeString(&DeviceSddl, L"" FSP_FSCTL_DEVICE_SDDL);
|
||||
RtlInitUnicodeString(&DeviceName, L"\\Device\\" FSP_FSCTL_DISK_DEVICE_NAME);
|
||||
RtlInitEmptyUnicodeString(&DeviceName, DeviceNameBuf, sizeof DeviceNameBuf);
|
||||
Result = RtlUnicodeStringPrintf(&DeviceName,
|
||||
L"\\Device\\" FSP_FSCTL_DISK_DEVICE_NAME "%wZ",
|
||||
FspSxsSuffix());
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
Result = FspDeviceCreateSecure(FspFsctlDeviceExtensionKind, 0,
|
||||
&DeviceName, FILE_DEVICE_DISK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN,
|
||||
&DeviceSddl, &FspFsctlDeviceClassGuid,
|
||||
&Globals->FsctlDiskDeviceObject);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
RtlInitUnicodeString(&DeviceName, L"\\Device\\" FSP_FSCTL_NET_DEVICE_NAME);
|
||||
if (0 != FspSxsIdent()->Length)
|
||||
{
|
||||
/* \Device\WinFsp.Disk SxS symlink */
|
||||
RtlInitUnicodeString(&SymlinkName, L"\\Device\\" FSP_FSCTL_DISK_DEVICE_NAME);
|
||||
Result = IoCreateSymbolicLink(&SymlinkName, &DeviceName);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
Globals->InitDoneSymlinkDisk = 1;
|
||||
}
|
||||
RtlInitEmptyUnicodeString(&DeviceName, DeviceNameBuf, sizeof DeviceNameBuf);
|
||||
Result = RtlUnicodeStringPrintf(&DeviceName,
|
||||
L"\\Device\\" FSP_FSCTL_NET_DEVICE_NAME "%wZ",
|
||||
FspSxsSuffix());
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
Result = FspDeviceCreateSecure(FspFsctlDeviceExtensionKind, 0,
|
||||
&DeviceName, FILE_DEVICE_NETWORK_FILE_SYSTEM, FILE_DEVICE_SECURE_OPEN,
|
||||
&DeviceSddl, &FspFsctlDeviceClassGuid,
|
||||
&Globals->FsctlNetDeviceObject);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
if (0 != FspSxsIdent()->Length)
|
||||
{
|
||||
/* \Device\WinFsp.Net SxS symlink */
|
||||
RtlInitUnicodeString(&SymlinkName, L"\\Device\\" FSP_FSCTL_NET_DEVICE_NAME);
|
||||
Result = IoCreateSymbolicLink(&SymlinkName, &DeviceName);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
Globals->InitDoneSymlinkNet = 1;
|
||||
}
|
||||
Result = FspDeviceCreate(FspFsmupDeviceExtensionKind, 0,
|
||||
FILE_DEVICE_NETWORK_FILE_SYSTEM, FILE_REMOTE_DEVICE,
|
||||
&Globals->FsmupDeviceObject);
|
||||
@ -257,8 +322,9 @@ static NTSTATUS FspDriverInitializeDevices(VOID)
|
||||
Result = RtlUnicodeStringPrintf(&DeviceName,
|
||||
0 == ((PULONG)&Guid)[0] && 0 == ((PULONG)&Guid)[1] &&
|
||||
0 == ((PULONG)&Guid)[2] && 0 == ((PULONG)&Guid)[3] ?
|
||||
L"\\Device\\" FSP_FSCTL_MUP_DEVICE_NAME :
|
||||
L"\\Device\\" FSP_FSCTL_MUP_DEVICE_NAME "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
|
||||
L"\\Device\\" FSP_FSCTL_MUP_DEVICE_NAME "%wZ":
|
||||
L"\\Device\\" FSP_FSCTL_MUP_DEVICE_NAME "%wZ{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
|
||||
FspSxsSuffix(),
|
||||
Guid.Data1, Guid.Data2, Guid.Data3,
|
||||
Guid.Data4[0], Guid.Data4[1], Guid.Data4[2], Guid.Data4[3],
|
||||
Guid.Data4[4], Guid.Data4[5], Guid.Data4[6], Guid.Data4[7]);
|
||||
@ -277,12 +343,25 @@ static NTSTATUS FspDriverInitializeDevices(VOID)
|
||||
* as a file system; we register with the MUP instead.
|
||||
*/
|
||||
IoRegisterFileSystem(Globals->FsctlDiskDeviceObject);
|
||||
Globals->InitDoneRegisterDisk = 1;
|
||||
|
||||
/*
|
||||
* Reference primary device objects to allow for IoDeleteDevice during FspDriverUnload.
|
||||
*/
|
||||
ObReferenceObject(Globals->FsctlDiskDeviceObject);
|
||||
ObReferenceObject(Globals->FsctlNetDeviceObject);
|
||||
ObReferenceObject(Globals->FsmupDeviceObject);
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
if (Globals->InitDoneRegisterDisk)
|
||||
{
|
||||
IoUnregisterFileSystem(Globals->FsctlDiskDeviceObject);
|
||||
Globals->InitDoneRegisterDisk = 0;
|
||||
}
|
||||
if (0 != Globals->MupHandle)
|
||||
{
|
||||
FsRtlDeregisterUncProvider(Globals->MupHandle);
|
||||
@ -293,11 +372,23 @@ exit:
|
||||
FspDeviceDelete(Globals->FsmupDeviceObject);
|
||||
Globals->FsmupDeviceObject = 0;
|
||||
}
|
||||
if (Globals->InitDoneSymlinkNet)
|
||||
{
|
||||
RtlInitUnicodeString(&SymlinkName, L"\\Device\\" FSP_FSCTL_NET_DEVICE_NAME);
|
||||
IoDeleteSymbolicLink(&SymlinkName);
|
||||
Globals->InitDoneSymlinkNet = 0;
|
||||
}
|
||||
if (0 != Globals->FsctlNetDeviceObject)
|
||||
{
|
||||
FspDeviceDelete(Globals->FsctlNetDeviceObject);
|
||||
Globals->FsctlNetDeviceObject = 0;
|
||||
}
|
||||
if (Globals->InitDoneSymlinkDisk)
|
||||
{
|
||||
RtlInitUnicodeString(&SymlinkName, L"\\Device\\" FSP_FSCTL_DISK_DEVICE_NAME);
|
||||
IoDeleteSymbolicLink(&SymlinkName);
|
||||
Globals->InitDoneSymlinkDisk = 0;
|
||||
}
|
||||
if (0 != Globals->FsctlDiskDeviceObject)
|
||||
{
|
||||
FspDeviceDelete(Globals->FsctlDiskDeviceObject);
|
||||
@ -314,40 +405,151 @@ static VOID FspDriverFinalizeDevices(VOID)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
FspDriverFinalizeDevicesEx(TRUE);
|
||||
}
|
||||
|
||||
static VOID FspDriverFinalizeDevicesForUnload(VOID)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
FspDriverFinalizeDevicesEx(FALSE);
|
||||
}
|
||||
|
||||
static VOID FspDriverFinalizeDevicesEx(BOOLEAN DeleteDevices)
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
FSP_SILO_GLOBALS *Globals;
|
||||
UNICODE_STRING SymlinkName;
|
||||
|
||||
FspSiloGetGlobals(&Globals);
|
||||
ASSERT(0 != Globals);
|
||||
|
||||
if (Globals->InitDoneRegisterDisk)
|
||||
{
|
||||
IoUnregisterFileSystem(Globals->FsctlDiskDeviceObject);
|
||||
|
||||
Globals->InitDoneRegisterDisk = 0;
|
||||
}
|
||||
if (0 != Globals->MupHandle)
|
||||
{
|
||||
FsRtlDeregisterUncProvider(Globals->MupHandle);
|
||||
Globals->MupHandle = 0;
|
||||
}
|
||||
if (0 != Globals->FsmupDeviceObject)
|
||||
{
|
||||
if (DeleteDevices)
|
||||
{
|
||||
FspDeviceDelete(Globals->FsmupDeviceObject);
|
||||
ObDereferenceObject(Globals->FsmupDeviceObject);
|
||||
Globals->FsmupDeviceObject = 0;
|
||||
}
|
||||
else
|
||||
FspDeviceDoIoDeleteDevice(Globals->FsmupDeviceObject);
|
||||
}
|
||||
if (Globals->InitDoneSymlinkNet)
|
||||
{
|
||||
RtlInitUnicodeString(&SymlinkName, L"\\Device\\" FSP_FSCTL_NET_DEVICE_NAME);
|
||||
IoDeleteSymbolicLink(&SymlinkName);
|
||||
Globals->InitDoneSymlinkNet = 0;
|
||||
}
|
||||
if (0 != Globals->FsctlNetDeviceObject)
|
||||
{
|
||||
if (DeleteDevices)
|
||||
{
|
||||
FspDeviceDelete(Globals->FsctlNetDeviceObject);
|
||||
ObDereferenceObject(Globals->FsctlNetDeviceObject);
|
||||
Globals->FsctlNetDeviceObject = 0;
|
||||
}
|
||||
else
|
||||
FspDeviceDoIoDeleteDevice(Globals->FsctlNetDeviceObject);
|
||||
}
|
||||
if (Globals->InitDoneSymlinkDisk)
|
||||
{
|
||||
RtlInitUnicodeString(&SymlinkName, L"\\Device\\" FSP_FSCTL_DISK_DEVICE_NAME);
|
||||
IoDeleteSymbolicLink(&SymlinkName);
|
||||
Globals->InitDoneSymlinkDisk = 0;
|
||||
}
|
||||
if (0 != Globals->FsctlDiskDeviceObject)
|
||||
{
|
||||
if (DeleteDevices)
|
||||
{
|
||||
FspDeviceDelete(Globals->FsctlDiskDeviceObject);
|
||||
ObDereferenceObject(Globals->FsctlDiskDeviceObject);
|
||||
Globals->FsctlDiskDeviceObject = 0;
|
||||
}
|
||||
else
|
||||
FspDeviceDoIoDeleteDevice(Globals->FsctlDiskDeviceObject);
|
||||
}
|
||||
|
||||
FspSiloDereferenceGlobals(Globals);
|
||||
}
|
||||
|
||||
NTSTATUS FspDriverUnload(
|
||||
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_UNLOAD == IrpSp->Parameters.FileSystemControl.FsControlCode);
|
||||
|
||||
NTSTATUS Result;
|
||||
UNICODE_STRING DriverServiceName, DriverName, Remain;
|
||||
WCHAR DriverServiceNameBuf[64 + 256];
|
||||
PDEVICE_OBJECT *DeviceObjects = 0;
|
||||
ULONG DeviceObjectCount = 0;
|
||||
|
||||
if (!FspSiloIsHost())
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
if (!SeSinglePrivilegeCheck(RtlConvertLongToLuid(SE_LOAD_DRIVER_PRIVILEGE), UserMode))
|
||||
return STATUS_PRIVILEGE_NOT_HELD;
|
||||
|
||||
ExAcquireFastMutexUnsafe(&FspDriverUnloadMutex);
|
||||
|
||||
if (!FspDriverUnloadDone)
|
||||
{
|
||||
FspFileNameSuffix(&FspDriverObject->DriverName, &Remain, &DriverName);
|
||||
RtlInitEmptyUnicodeString(&DriverServiceName, DriverServiceNameBuf, sizeof DriverServiceNameBuf);
|
||||
Result = RtlUnicodeStringPrintf(&DriverServiceName,
|
||||
L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\%wZ", &DriverName);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
Result = ZwUnloadDriver(&DriverServiceName);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
FspSiloEnumerate(FspDriverFinalizeDevicesForUnload);
|
||||
FspDriverFinalizeDevicesForUnload();
|
||||
|
||||
Result = FspDeviceCopyList(&DeviceObjects, &DeviceObjectCount);
|
||||
if (NT_SUCCESS(Result))
|
||||
{
|
||||
for (ULONG I = 0; DeviceObjectCount > I; I++)
|
||||
{
|
||||
FSP_DEVICE_EXTENSION *DeviceExtension = FspDeviceExtension(DeviceObjects[I]);
|
||||
if (FspFsvolDeviceExtensionKind == DeviceExtension->Kind)
|
||||
FspIoqStop(((FSP_FSVOL_DEVICE_EXTENSION *)DeviceExtension)->Ioq, FALSE);
|
||||
}
|
||||
FspDeviceDeleteList(DeviceObjects, DeviceObjectCount);
|
||||
}
|
||||
|
||||
FspDriverUnloadDone = TRUE;
|
||||
}
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
ExReleaseFastMutexUnsafe(&FspDriverUnloadMutex);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
PDRIVER_OBJECT FspDriverObject;
|
||||
FAST_IO_DISPATCH FspFastIoDispatch;
|
||||
CACHE_MANAGER_CALLBACKS FspCacheManagerCallbacks;
|
||||
FAST_MUTEX FspDriverUnloadMutex;
|
||||
BOOLEAN FspDriverUnloadDone;
|
||||
|
||||
ULONG FspProcessorCount;
|
||||
FSP_MV_CcCoherencyFlushAndPurgeCache *FspMvCcCoherencyFlushAndPurgeCache;
|
||||
|
@ -364,6 +364,10 @@ VOID FspTraceNtStatus(const char *file, int line, const char *func, NTSTATUS Sta
|
||||
/* missing typedef */
|
||||
typedef const void *PCVOID;
|
||||
|
||||
/* driver unload */
|
||||
NTSTATUS FspDriverUnload(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
|
||||
/* driver major functions */
|
||||
_Function_class_(DRIVER_DISPATCH)
|
||||
_IRQL_requires_max_(APC_LEVEL)
|
||||
@ -739,22 +743,34 @@ LONG FspCompareUnicodeString(
|
||||
PCUNICODE_STRING String2,
|
||||
BOOLEAN CaseInsensitive);
|
||||
|
||||
/* SxS */
|
||||
VOID FspSxsIdentInitialize(PUNICODE_STRING DriverName);
|
||||
PUNICODE_STRING FspSxsIdent(VOID);
|
||||
PUNICODE_STRING FspSxsSuffix(VOID);
|
||||
|
||||
/* silos */
|
||||
typedef struct
|
||||
{
|
||||
PVOID Silo;
|
||||
LIST_ENTRY ListEntry;
|
||||
PDEVICE_OBJECT FsctlDiskDeviceObject;
|
||||
PDEVICE_OBJECT FsctlNetDeviceObject;
|
||||
PDEVICE_OBJECT FsmupDeviceObject;
|
||||
HANDLE MupHandle;
|
||||
WCHAR FsmupDeviceNameBuf[64];
|
||||
WCHAR FsmupDeviceNameBuf[128];
|
||||
UINT32 InitDoneSymlinkDisk:1, InitDoneSymlinkNet:1, InitDoneRegisterDisk:1;
|
||||
} FSP_SILO_GLOBALS;
|
||||
typedef NTSTATUS (*FSP_SILO_INIT_CALLBACK)(VOID);
|
||||
typedef VOID (*FSP_SILO_FINI_CALLBACK)(VOID);
|
||||
typedef VOID (*FSP_SILO_ENUM_CALLBACK)(VOID);
|
||||
BOOLEAN FspSiloIsHost(VOID);
|
||||
NTSTATUS FspSiloGetGlobals(FSP_SILO_GLOBALS **PGlobals);
|
||||
VOID FspSiloDereferenceGlobals(FSP_SILO_GLOBALS *Globals);
|
||||
VOID FspSiloGetContainerId(GUID *ContainerId);
|
||||
NTSTATUS FspSiloInitialize(FSP_SILO_INIT_CALLBACK Init, FSP_SILO_FINI_CALLBACK Fini);
|
||||
NTSTATUS FspSiloPostInitialize(VOID);
|
||||
VOID FspSiloFinalize(VOID);
|
||||
VOID FspSiloEnumerate(FSP_SILO_ENUM_CALLBACK EnumFn);
|
||||
|
||||
/* process buffers */
|
||||
#define FspProcessBufferSizeMax (64 * 1024)
|
||||
@ -1181,9 +1197,8 @@ typedef struct
|
||||
KSPIN_LOCK SpinLock;
|
||||
LONG RefCount;
|
||||
UINT32 Kind;
|
||||
GUID SiloContainerId;
|
||||
/* IoTimer emulation */
|
||||
FSP_DEVICE_TIMER DeviceTimer;
|
||||
FSP_DEVICE_TIMER DeviceTimer; /* IoTimer emulation */
|
||||
LONG DidIoDeleteDevice;
|
||||
} FSP_DEVICE_EXTENSION;
|
||||
typedef struct
|
||||
{
|
||||
@ -1232,13 +1247,18 @@ typedef struct
|
||||
} FSP_FSVOL_DEVICE_EXTENSION;
|
||||
typedef struct
|
||||
{
|
||||
/* read-only after creation (and insertion in the ContextTable) */
|
||||
FSP_DEVICE_EXTENSION Base;
|
||||
UINT16 SectorSize;
|
||||
LONG IsMountdev;
|
||||
BOOLEAN Persistent;
|
||||
GUID UniqueId;
|
||||
UNICODE_STRING VolumeName;
|
||||
WCHAR VolumeNameBuf[FSP_FSCTL_VOLUME_NAME_SIZE / sizeof(WCHAR)];
|
||||
FAST_MUTEX MountMutex;
|
||||
/* interlocked access */
|
||||
LONG IsMountdev;
|
||||
/* protected under MountMutex */
|
||||
BOOLEAN Persistent;
|
||||
GUID UniqueId;
|
||||
UNICODE_STRING MountPoint;
|
||||
} FSP_FSVRT_DEVICE_EXTENSION;
|
||||
typedef struct
|
||||
{
|
||||
@ -1280,6 +1300,7 @@ NTSTATUS FspDeviceCreate(UINT32 Kind, ULONG ExtraSize,
|
||||
PDEVICE_OBJECT *PDeviceObject);
|
||||
NTSTATUS FspDeviceInitialize(PDEVICE_OBJECT DeviceObject);
|
||||
VOID FspDeviceDelete(PDEVICE_OBJECT DeviceObject);
|
||||
VOID FspDeviceDoIoDeleteDevice(PDEVICE_OBJECT DeviceObject);
|
||||
BOOLEAN FspDeviceReference(PDEVICE_OBJECT DeviceObject);
|
||||
VOID FspDeviceDereference(PDEVICE_OBJECT DeviceObject);
|
||||
static inline
|
||||
@ -1435,6 +1456,18 @@ BOOLEAN FspFsvolDeviceVolumePrefixInString(PDEVICE_OBJECT DeviceObject, PUNICODE
|
||||
TRUE);
|
||||
}
|
||||
static inline
|
||||
VOID FspFsvrtDeviceLockMount(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(DeviceObject);
|
||||
ExAcquireFastMutexUnsafe(&FsvrtDeviceExtension->MountMutex);
|
||||
}
|
||||
static inline
|
||||
VOID FspFsvrtDeviceUnlockMount(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(DeviceObject);
|
||||
ExReleaseFastMutexUnsafe(&FsvrtDeviceExtension->MountMutex);
|
||||
}
|
||||
static inline
|
||||
VOID FspFsmupDeviceLockPrefixTable(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
FSP_FSMUP_DEVICE_EXTENSION *FsmupDeviceExtension = FspFsmupDeviceExtension(DeviceObject);
|
||||
@ -1450,7 +1483,6 @@ NTSTATUS FspDeviceCopyList(
|
||||
PDEVICE_OBJECT **PDeviceObjects, PULONG PDeviceObjectCount);
|
||||
VOID FspDeviceDeleteList(
|
||||
PDEVICE_OBJECT *DeviceObjects, ULONG DeviceObjectCount);
|
||||
VOID FspDeviceDeleteAll(VOID);
|
||||
NTSTATUS FspDeviceInitializeAllTimers(VOID);
|
||||
VOID FspDeviceFinalizeAllTimers(VOID);
|
||||
NTSTATUS FspDeviceInitializeTimer(PDEVICE_OBJECT DeviceObject,
|
||||
@ -1524,6 +1556,16 @@ NTSTATUS FspMountdevMake(
|
||||
VOID FspMountdevFini(
|
||||
PDEVICE_OBJECT FsvrtDeviceObject);
|
||||
|
||||
/* mountmgr */
|
||||
NTSTATUS FspMountmgrCreateDrive(
|
||||
PUNICODE_STRING VolumeName, GUID *UniqueId, PUNICODE_STRING MountPoint);
|
||||
NTSTATUS FspMountmgrDeleteDrive(
|
||||
PUNICODE_STRING MountPoint);
|
||||
NTSTATUS FspMountmgrNotifyCreateDirectory(
|
||||
PUNICODE_STRING VolumeName, GUID *UniqueId, PUNICODE_STRING MountPoint);
|
||||
NTSTATUS FspMountmgrNotifyDeleteDirectory(
|
||||
PUNICODE_STRING VolumeName, PUNICODE_STRING MountPoint);
|
||||
|
||||
/* fsmup */
|
||||
NTSTATUS FspMupRegister(
|
||||
PDEVICE_OBJECT FsmupDeviceObject, PDEVICE_OBJECT FsvolDeviceObject);
|
||||
@ -1543,6 +1585,8 @@ NTSTATUS FspVolumeMount(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeMakeMountdev(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeUseMountmgr(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeGetName(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeGetNameList(
|
||||
@ -1970,6 +2014,8 @@ FSP_MV_CcCoherencyFlushAndPurgeCache(
|
||||
extern PDRIVER_OBJECT FspDriverObject;
|
||||
extern FAST_IO_DISPATCH FspFastIoDispatch;
|
||||
extern CACHE_MANAGER_CALLBACKS FspCacheManagerCallbacks;
|
||||
extern FAST_MUTEX FspDriverUnloadMutex;
|
||||
extern BOOLEAN FspDriverUnloadDone;
|
||||
extern FSP_IOPREP_DISPATCH *FspIopPrepareFunction[];
|
||||
extern FSP_IOCMPL_DISPATCH *FspIopCompleteFunction[];
|
||||
extern FAST_MUTEX FspDeviceGlobalMutex;
|
||||
|
@ -1475,7 +1475,7 @@ NTSTATUS FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp
|
||||
{
|
||||
Result = NT_SUCCESS(Result) ? STATUS_OPLOCK_BREAK_IN_PROGRESS : Result;
|
||||
DescendantFileNodes[DescendantFileNodeIndex] =
|
||||
(PVOID)((UINT_PTR)DescendantFileNode | 2);
|
||||
(PVOID)((UINT_PTR)DescendantFileNode | 4);
|
||||
}
|
||||
else
|
||||
Result = STATUS_ACCESS_DENIED;
|
||||
|
@ -81,6 +81,10 @@ static NTSTATUS FspFsctlFileSystemControl(
|
||||
if (0 != IrpSp->FileObject->FsContext2)
|
||||
Result = FspVolumeMakeMountdev(FsctlDeviceObject, Irp, IrpSp);
|
||||
break;
|
||||
case FSP_FSCTL_MOUNTMGR:
|
||||
if (0 != IrpSp->FileObject->FsContext2)
|
||||
Result = FspVolumeUseMountmgr(FsctlDeviceObject, Irp, IrpSp);
|
||||
break;
|
||||
case FSP_FSCTL_VOLUME_NAME:
|
||||
if (0 != IrpSp->FileObject->FsContext2)
|
||||
Result = FspVolumeGetName(FsctlDeviceObject, Irp, IrpSp);
|
||||
@ -124,6 +128,9 @@ static NTSTATUS FspFsctlFileSystemControl(
|
||||
if (0 != IrpSp->FileObject->FsContext2)
|
||||
Result = FspVolumeNotify(FsctlDeviceObject, Irp, IrpSp);
|
||||
break;
|
||||
case FSP_FSCTL_UNLOAD:
|
||||
Result = FspDriverUnload(FsctlDeviceObject, Irp, IrpSp);
|
||||
break;
|
||||
default:
|
||||
if (CTL_CODE(0, 0xC00, 0, 0) ==
|
||||
(IrpSp->Parameters.FileSystemControl.FsControlCode & CTL_CODE(0, 0xC00, 0, 0)))
|
||||
|
@ -138,7 +138,7 @@ NTSTATUS FspMountdevMake(
|
||||
* be mounted using the MountManager.
|
||||
*
|
||||
* This function requires protection against concurrency. In general this
|
||||
* is achieved by acquiring the GlobalDeviceLock.
|
||||
* is achieved by the caller acquiring the MountMutex.
|
||||
*/
|
||||
|
||||
PAGED_CODE();
|
||||
@ -178,11 +178,6 @@ NTSTATUS FspMountdevMake(
|
||||
|
||||
/* initialize the fsvrt device extension */
|
||||
RtlCopyMemory(&FsvrtDeviceExtension->UniqueId, &Guid, sizeof Guid);
|
||||
RtlInitEmptyUnicodeString(&FsvrtDeviceExtension->VolumeName,
|
||||
FsvrtDeviceExtension->VolumeNameBuf, sizeof FsvrtDeviceExtension->VolumeNameBuf);
|
||||
RtlCopyUnicodeString(&FsvrtDeviceExtension->VolumeName, &FsvolDeviceExtension->VolumeName);
|
||||
|
||||
/* mark the fsvrt device as initialized */
|
||||
InterlockedIncrement(&FspFsvrtDeviceExtension(FsvrtDeviceObject)->IsMountdev);
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
@ -123,6 +123,27 @@ NTSTATUS FspProcessBufferInitialize(VOID)
|
||||
VOID FspProcessBufferFinalize(VOID)
|
||||
{
|
||||
PsSetCreateProcessNotifyRoutine(FspProcessBufferNotifyRoutine, TRUE);
|
||||
|
||||
/*
|
||||
* Free any items in our process hash table.
|
||||
* Any virtual memory was released when the corresponding processes went away.
|
||||
*/
|
||||
for (ULONG HashIndex = 0; ProcessBufferBucketCount > HashIndex; HashIndex++)
|
||||
{
|
||||
for (FSP_PROCESS_BUFFER_ITEM *Item = ProcessBufferBuckets[HashIndex], *DictNext; Item; Item = DictNext)
|
||||
{
|
||||
for (FSP_PROCESS_BUFFER_LIST_ENTRY *P = Item->BufferList, *Next; P; P = Next)
|
||||
{
|
||||
Next = P->Next;
|
||||
FspFree(P);
|
||||
}
|
||||
|
||||
DictNext = Item->DictNext;
|
||||
FspFree(Item);
|
||||
}
|
||||
|
||||
ProcessBufferBuckets[HashIndex] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static VOID FspProcessBufferNotifyRoutine(HANDLE ParentId, HANDLE ProcessId, BOOLEAN Create)
|
||||
|
@ -22,9 +22,11 @@
|
||||
#include <sys/driver.h>
|
||||
|
||||
NTSTATUS FspSiloInitialize(FSP_SILO_INIT_CALLBACK Init, FSP_SILO_FINI_CALLBACK Fini);
|
||||
NTSTATUS FspSiloPostInitialize(VOID);
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(INIT, FspSiloInitialize)
|
||||
#pragma alloc_text(INIT, FspSiloPostInitialize)
|
||||
#endif
|
||||
|
||||
typedef PEJOB FSP_PESILO;
|
||||
@ -108,6 +110,9 @@ static FSP_SILO_INIT_CALLBACK FspSiloInitCallback;
|
||||
static FSP_SILO_FINI_CALLBACK FspSiloFiniCallback;
|
||||
static BOOLEAN FspSiloInitDone = FALSE;
|
||||
|
||||
static FAST_MUTEX FspSiloListMutex;
|
||||
static LIST_ENTRY FspSiloList;
|
||||
|
||||
static FSP_SILO_GLOBALS FspSiloHostGlobals;
|
||||
|
||||
#define FSP_SILO_MONITOR_REGISTRATION_VERSION 1
|
||||
@ -123,6 +128,11 @@ static FSP_SILO_GLOBALS FspSiloHostGlobals;
|
||||
}
|
||||
#define CALL(n) (FspSilo ## n)
|
||||
|
||||
BOOLEAN FspSiloIsHost(VOID)
|
||||
{
|
||||
return !FspSiloInitDone || 0 == CALL(PsGetCurrentServerSilo)();
|
||||
}
|
||||
|
||||
NTSTATUS FspSiloGetGlobals(FSP_SILO_GLOBALS **PGlobals)
|
||||
{
|
||||
FSP_PESILO Silo;
|
||||
@ -189,6 +199,7 @@ static NTSTATUS NTAPI FspSiloMonitorCreateCallback(FSP_PESILO Silo)
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
RtlZeroMemory(Globals, sizeof(FSP_SILO_GLOBALS));
|
||||
Globals->Silo = Silo;
|
||||
|
||||
/* PsInsertSiloContext adds reference to Globals */
|
||||
Result = CALL(PsInsertSiloContext)(Silo, ContextSlot, Globals);
|
||||
@ -196,6 +207,9 @@ static NTSTATUS NTAPI FspSiloMonitorCreateCallback(FSP_PESILO Silo)
|
||||
goto exit;
|
||||
Inserted = TRUE;
|
||||
|
||||
FsRtlEnterFileSystem();
|
||||
ExAcquireFastMutexUnsafe(&FspSiloListMutex);
|
||||
|
||||
if (0 != FspSiloInitCallback)
|
||||
{
|
||||
FSP_PESILO PreviousSilo = CALL(PsAttachSiloToCurrentThread)(Silo);
|
||||
@ -203,6 +217,12 @@ static NTSTATUS NTAPI FspSiloMonitorCreateCallback(FSP_PESILO Silo)
|
||||
CALL(PsDetachSiloFromCurrentThread)(PreviousSilo);
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(Result))
|
||||
InsertTailList(&FspSiloList, &Globals->ListEntry);
|
||||
|
||||
ExReleaseFastMutexUnsafe(&FspSiloListMutex);
|
||||
FsRtlExitFileSystem();
|
||||
|
||||
exit:
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
@ -237,6 +257,11 @@ static VOID NTAPI FspSiloMonitorTerminateCallback(FSP_PESILO Silo)
|
||||
Result = CALL(PsGetSiloContext)(Silo, ContextSlot, &Globals);
|
||||
if (!NT_SUCCESS(Result))
|
||||
return;
|
||||
|
||||
FsRtlEnterFileSystem();
|
||||
ExAcquireFastMutexUnsafe(&FspSiloListMutex);
|
||||
|
||||
RemoveEntryList(&Globals->ListEntry);
|
||||
CALL(PsDereferenceSiloContext)(Globals);
|
||||
Globals = 0;
|
||||
|
||||
@ -247,6 +272,9 @@ static VOID NTAPI FspSiloMonitorTerminateCallback(FSP_PESILO Silo)
|
||||
CALL(PsDetachSiloFromCurrentThread)(PreviousSilo);
|
||||
}
|
||||
|
||||
ExReleaseFastMutexUnsafe(&FspSiloListMutex);
|
||||
FsRtlExitFileSystem();
|
||||
|
||||
/* PsRemoveSiloContext removes reference to Globals (possibly freeing it) */
|
||||
CALL(PsRemoveSiloContext)(Silo, ContextSlot, 0);
|
||||
}
|
||||
@ -255,6 +283,9 @@ NTSTATUS FspSiloInitialize(FSP_SILO_INIT_CALLBACK Init, FSP_SILO_FINI_CALLBACK F
|
||||
{
|
||||
NTSTATUS Result = STATUS_SUCCESS;
|
||||
|
||||
ExInitializeFastMutex(&FspSiloListMutex);
|
||||
InitializeListHead(&FspSiloList);
|
||||
|
||||
if (FspIsNtDdiVersionAvailable(NTDDI_WIN10_RS5))
|
||||
{
|
||||
ULONG Fail = 0;
|
||||
@ -293,15 +324,11 @@ NTSTATUS FspSiloInitialize(FSP_SILO_INIT_CALLBACK Init, FSP_SILO_FINI_CALLBACK F
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
Result = CALL(PsStartSiloMonitor)(Monitor);
|
||||
if (!NT_SUCCESS(Result))
|
||||
goto exit;
|
||||
|
||||
FspSiloMonitor = Monitor;
|
||||
FspSiloInitCallback = Init;
|
||||
FspSiloFiniCallback = Fini;
|
||||
|
||||
FspSiloInitDone = TRUE;
|
||||
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
@ -316,10 +343,62 @@ NTSTATUS FspSiloInitialize(FSP_SILO_INIT_CALLBACK Init, FSP_SILO_FINI_CALLBACK F
|
||||
return Result;
|
||||
}
|
||||
|
||||
NTSTATUS FspSiloPostInitialize(VOID)
|
||||
{
|
||||
if (!FspSiloInitDone)
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
return CALL(PsStartSiloMonitor)(FspSiloMonitor);
|
||||
}
|
||||
|
||||
VOID FspSiloFinalize(VOID)
|
||||
{
|
||||
if (!FspSiloInitDone)
|
||||
return;
|
||||
|
||||
CALL(PsUnregisterSiloMonitor)(FspSiloMonitor);
|
||||
|
||||
#if DBG
|
||||
FsRtlEnterFileSystem();
|
||||
ExAcquireFastMutexUnsafe(&FspSiloListMutex);
|
||||
ASSERT(IsListEmpty(&FspSiloList));
|
||||
ExReleaseFastMutexUnsafe(&FspSiloListMutex);
|
||||
FsRtlExitFileSystem();
|
||||
#endif
|
||||
|
||||
FspSiloMonitor = 0;
|
||||
FspSiloInitCallback = 0;
|
||||
FspSiloFiniCallback = 0;
|
||||
FspSiloInitDone = FALSE;
|
||||
}
|
||||
|
||||
VOID FspSiloEnumerate(FSP_SILO_ENUM_CALLBACK EnumFn)
|
||||
{
|
||||
KAPC_STATE ApcState;
|
||||
PLIST_ENTRY ListEntry;
|
||||
FSP_SILO_GLOBALS *Globals;
|
||||
|
||||
FsRtlEnterFileSystem();
|
||||
ExAcquireFastMutexUnsafe(&FspSiloListMutex);
|
||||
|
||||
if (!IsListEmpty(&FspSiloList))
|
||||
{
|
||||
KeStackAttachProcess(PsInitialSystemProcess, &ApcState);
|
||||
|
||||
for (ListEntry = FspSiloList.Flink;
|
||||
&FspSiloList != ListEntry;
|
||||
ListEntry = ListEntry->Flink)
|
||||
{
|
||||
Globals = CONTAINING_RECORD(ListEntry, FSP_SILO_GLOBALS, ListEntry);
|
||||
|
||||
FSP_PESILO PreviousSilo = CALL(PsAttachSiloToCurrentThread)(Globals->Silo);
|
||||
EnumFn();
|
||||
CALL(PsDetachSiloFromCurrentThread)(PreviousSilo);
|
||||
}
|
||||
|
||||
KeUnstackDetachProcess(&ApcState);
|
||||
}
|
||||
|
||||
ExReleaseFastMutexUnsafe(&FspSiloListMutex);
|
||||
FsRtlExitFileSystem();
|
||||
}
|
||||
|
71
src/sys/sxs.c
Normal file
71
src/sys/sxs.c
Normal file
@ -0,0 +1,71 @@
|
||||
/**
|
||||
* @file sys/sxs.c
|
||||
*
|
||||
* @copyright 2015-2022 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
*
|
||||
* You can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License version 3 as published by the Free Software
|
||||
* Foundation.
|
||||
*
|
||||
* Licensees holding a valid commercial license may use this software
|
||||
* in accordance with the commercial license agreement provided in
|
||||
* conjunction with the software. The terms and conditions of any such
|
||||
* commercial license agreement shall govern, supersede, and render
|
||||
* ineffective any application of the GPLv3 license to this software,
|
||||
* notwithstanding of any reference thereto in the software or
|
||||
* associated repository.
|
||||
*/
|
||||
|
||||
#include <sys/driver.h>
|
||||
|
||||
VOID FspSxsIdentInitialize(PUNICODE_STRING DriverName);
|
||||
PUNICODE_STRING FspSxsIdent(VOID);
|
||||
PUNICODE_STRING FspSxsSuffix(VOID);
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(INIT, FspSxsIdentInitialize)
|
||||
#endif
|
||||
|
||||
static WCHAR FspSxsIdentBuf[32 + 1] = L"";
|
||||
static UNICODE_STRING FspSxsIdentStr = { 0, sizeof FspSxsIdentBuf - 1, FspSxsIdentBuf + 1 };
|
||||
static UNICODE_STRING FspSxsSuffixStr = { 0, sizeof FspSxsIdentBuf, FspSxsIdentBuf };
|
||||
|
||||
VOID FspSxsIdentInitialize(PUNICODE_STRING DriverName)
|
||||
{
|
||||
PWCHAR Ident = 0;
|
||||
USHORT Length;
|
||||
|
||||
for (PWCHAR P = DriverName->Buffer + DriverName->Length / sizeof(WCHAR) - 1; DriverName->Buffer <= P; P--)
|
||||
{
|
||||
if (L'\\' == *P)
|
||||
break;
|
||||
if (FSP_SXS_SEPARATOR_CHAR == *P)
|
||||
{
|
||||
Ident = P;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (0 == Ident)
|
||||
return;
|
||||
|
||||
Length = (USHORT)(((PUINT8)DriverName->Buffer + DriverName->Length) - (PUINT8)Ident);
|
||||
if (Length > sizeof FspSxsIdentBuf)
|
||||
Length = sizeof FspSxsIdentBuf;
|
||||
|
||||
RtlCopyMemory(FspSxsIdentBuf, Ident, Length);
|
||||
FspSxsIdentStr.Length = Length - sizeof(WCHAR);
|
||||
FspSxsSuffixStr.Length = Length;
|
||||
}
|
||||
|
||||
PUNICODE_STRING FspSxsIdent(VOID)
|
||||
{
|
||||
return &FspSxsIdentStr;
|
||||
}
|
||||
|
||||
PUNICODE_STRING FspSxsSuffix(VOID)
|
||||
{
|
||||
return &FspSxsSuffixStr;
|
||||
}
|
211
src/sys/volume.c
211
src/sys/volume.c
@ -38,6 +38,8 @@ static NTSTATUS FspVolumeMountNoLock(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeMakeMountdev(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeUseMountmgr(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeGetName(
|
||||
PDEVICE_OBJECT FsctlDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp);
|
||||
NTSTATUS FspVolumeGetNameList(
|
||||
@ -76,6 +78,7 @@ NTSTATUS FspVolumeWork(
|
||||
// ! #pragma alloc_text(PAGE, FspVolumeMount)
|
||||
// ! #pragma alloc_text(PAGE, FspVolumeMountNoLock)
|
||||
#pragma alloc_text(PAGE, FspVolumeMakeMountdev)
|
||||
#pragma alloc_text(PAGE, FspVolumeUseMountmgr)
|
||||
#pragma alloc_text(PAGE, FspVolumeGetName)
|
||||
#pragma alloc_text(PAGE, FspVolumeGetNameList)
|
||||
#pragma alloc_text(PAGE, FspVolumeGetNameListNoLock)
|
||||
@ -110,6 +113,57 @@ NTSTATUS FspVolumeCreate(
|
||||
|
||||
FspSiloDereferenceGlobals(Globals);
|
||||
|
||||
if (NT_SUCCESS(Result))
|
||||
{
|
||||
/*
|
||||
* If we have an fsvrt device, mount it NOW via opening the volume. This ensures
|
||||
* that the fsvrt is mounted by the correct fsvol device early on and remedies
|
||||
* a rare case where NTFS crashes the system when it attempts to mount our fsvrt.
|
||||
*
|
||||
* We use IoCreateFileEx with FILE_READ_DATA to ensure that the I/O Manager will
|
||||
* mount the fsvrt device.
|
||||
*
|
||||
* We ignore the IoCreateFileEx return code as it is only used for its side effect
|
||||
* of mounting the fsvrt. In the unlikely event that IoCreateFileEx fails, the
|
||||
* system will retry the mount when a file is accessed, etc.
|
||||
*/
|
||||
|
||||
PDEVICE_OBJECT FsvolDeviceObject = IrpSp->FileObject->FsContext2;
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||
PDEVICE_OBJECT FsvrtDeviceObject = FsvolDeviceExtension->FsvrtDeviceObject;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
IO_STATUS_BLOCK IoStatus;
|
||||
HANDLE Handle;
|
||||
|
||||
if (0 != FsvrtDeviceObject)
|
||||
{
|
||||
InitializeObjectAttributes(
|
||||
&ObjectAttributes,
|
||||
&FsvolDeviceExtension->VolumeName,
|
||||
OBJ_KERNEL_HANDLE,
|
||||
0/*RootDirectory*/,
|
||||
0/*SecurityDescriptor*/);
|
||||
IoStatus.Status = IoCreateFileEx(
|
||||
&Handle,
|
||||
FILE_READ_DATA,
|
||||
&ObjectAttributes,
|
||||
&IoStatus,
|
||||
0/*AllocationSize*/,
|
||||
0/*FileAttributes*/,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
FILE_OPEN,
|
||||
0/*CreateOptions*/,
|
||||
0/*EaBuffer*/,
|
||||
0/*EaLength*/,
|
||||
CreateFileTypeNone,
|
||||
0/*InternalParameters*/,
|
||||
0/*Options*/,
|
||||
0/*DriverContext*/);
|
||||
if (NT_SUCCESS(IoStatus.Status))
|
||||
ObCloseHandle(Handle, KernelMode);
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
@ -246,6 +300,11 @@ static NTSTATUS FspVolumeCreateNoLock(
|
||||
VolumeParams.AlwaysUseDoubleBuffering = 1;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Hardcode the RejectIrpPriorToTransact0 = 1 setting.
|
||||
*/
|
||||
VolumeParams.RejectIrpPriorToTransact0 = 1;
|
||||
|
||||
/* load any fsext provider */
|
||||
if (0 != VolumeParams.FsextControlCode)
|
||||
{
|
||||
@ -316,8 +375,12 @@ static NTSTATUS FspVolumeCreateNoLock(
|
||||
{
|
||||
if (0 != FsvrtDeviceObject)
|
||||
{
|
||||
FspFsvrtDeviceExtension(FsvrtDeviceObject)->SectorSize =
|
||||
FsvolDeviceExtension->VolumeParams.SectorSize;
|
||||
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject);
|
||||
FsvrtDeviceExtension->SectorSize = FsvolDeviceExtension->VolumeParams.SectorSize;
|
||||
RtlInitEmptyUnicodeString(&FsvrtDeviceExtension->VolumeName,
|
||||
FsvrtDeviceExtension->VolumeNameBuf, sizeof FsvrtDeviceExtension->VolumeNameBuf);
|
||||
RtlCopyUnicodeString(&FsvrtDeviceExtension->VolumeName, &FsvolDeviceExtension->VolumeName);
|
||||
|
||||
Result = FspDeviceInitialize(FsvrtDeviceObject);
|
||||
}
|
||||
}
|
||||
@ -638,7 +701,7 @@ NTSTATUS FspVolumeMakeMountdev(
|
||||
if (sizeof(GUID) > OutputBufferLength)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
|
||||
FspDeviceGlobalLock();
|
||||
FspFsvrtDeviceLockMount(FsvrtDeviceObject);
|
||||
|
||||
Result = FspMountdevMake(FsvrtDeviceObject, FsvolDeviceObject, Persistent);
|
||||
if (!NT_SUCCESS(Result))
|
||||
@ -654,7 +717,147 @@ NTSTATUS FspVolumeMakeMountdev(
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
exit:
|
||||
FspDeviceGlobalUnlock();
|
||||
FspFsvrtDeviceUnlockMount(FsvrtDeviceObject);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
NTSTATUS FspVolumeUseMountmgr(
|
||||
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_MOUNTMGR == IrpSp->Parameters.FileSystemControl.FsControlCode);
|
||||
ASSERT(0 != IrpSp->FileObject->FsContext2);
|
||||
|
||||
PDEVICE_OBJECT FsvolDeviceObject = IrpSp->FileObject->FsContext2;
|
||||
FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||
PDEVICE_OBJECT FsvrtDeviceObject = FsvolDeviceExtension->FsvrtDeviceObject;
|
||||
ULONG InputBufferLength = IrpSp->Parameters.FileSystemControl.InputBufferLength;
|
||||
NTSTATUS Result;
|
||||
|
||||
if (0 == FsvrtDeviceObject)
|
||||
return STATUS_INVALID_PARAMETER; /* cannot only use fsvrt with mount manager */
|
||||
if (1024 * sizeof(WCHAR) < InputBufferLength)
|
||||
return STATUS_INVALID_PARAMETER; /* disallow very long paths */
|
||||
|
||||
FspFsvrtDeviceLockMount(FsvrtDeviceObject);
|
||||
|
||||
if (0 < InputBufferLength)
|
||||
{
|
||||
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject);
|
||||
PWCHAR MountPointBuf = Irp->AssociatedIrp.SystemBuffer;
|
||||
UNICODE_STRING RegPath;
|
||||
UNICODE_STRING RegName;
|
||||
union
|
||||
{
|
||||
KEY_VALUE_PARTIAL_INFORMATION V;
|
||||
UINT8 B[FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) + sizeof(ULONG)];
|
||||
} RegValue;
|
||||
ULONG RegLength;
|
||||
BOOLEAN Persistent = FALSE;
|
||||
|
||||
if (!(
|
||||
2 * sizeof(WCHAR) <= InputBufferLength &&
|
||||
(
|
||||
(L'A' <= MountPointBuf[0] && MountPointBuf[0] <= L'Z') ||
|
||||
(L'a' <= MountPointBuf[0] && MountPointBuf[0] <= L'z')
|
||||
) &&
|
||||
L':' == MountPointBuf[1]
|
||||
))
|
||||
{
|
||||
Result = STATUS_INVALID_PARAMETER;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (0 != FsvrtDeviceExtension->MountPoint.Buffer)
|
||||
{
|
||||
Result = STATUS_INVALID_PARAMETER;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
RtlInitUnicodeString(&RegPath, L"" FSP_REGKEY);
|
||||
RtlInitUnicodeString(&RegName, L"MountUseMountmgrFromFSD");
|
||||
RegLength = sizeof RegValue;
|
||||
Result = FspRegistryGetValue(&RegPath, &RegName, &RegValue.V, &RegLength);
|
||||
if (!NT_SUCCESS(Result) || REG_DWORD != RegValue.V.Type || 1 != *(PULONG)&RegValue.V.Data)
|
||||
{
|
||||
Result = STATUS_ACCESS_DENIED;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Result = FspMountdevMake(FsvrtDeviceObject, FsvolDeviceObject, Persistent);
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
if (STATUS_TOO_LATE != Result)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
FsvrtDeviceExtension->MountPoint.Buffer = FspAllocNonPaged(InputBufferLength);
|
||||
if (0 == FsvrtDeviceExtension->MountPoint.Buffer)
|
||||
{
|
||||
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto exit;
|
||||
}
|
||||
FsvrtDeviceExtension->MountPoint.Length =
|
||||
FsvrtDeviceExtension->MountPoint.MaximumLength = (USHORT)InputBufferLength;
|
||||
RtlCopyMemory(FsvrtDeviceExtension->MountPoint.Buffer, MountPointBuf, InputBufferLength);
|
||||
|
||||
if (2 * sizeof(WCHAR) == FsvrtDeviceExtension->MountPoint.Length)
|
||||
Result = FspMountmgrCreateDrive(
|
||||
&FsvrtDeviceExtension->VolumeName,
|
||||
&FsvrtDeviceExtension->UniqueId,
|
||||
&FsvrtDeviceExtension->MountPoint);
|
||||
else
|
||||
Result = FspMountmgrNotifyCreateDirectory(
|
||||
&FsvrtDeviceExtension->VolumeName,
|
||||
&FsvrtDeviceExtension->UniqueId,
|
||||
&FsvrtDeviceExtension->MountPoint);
|
||||
if (!NT_SUCCESS(Result))
|
||||
{
|
||||
FspFree(FsvrtDeviceExtension->MountPoint.Buffer);
|
||||
FsvrtDeviceExtension->MountPoint.Buffer = 0;
|
||||
FsvrtDeviceExtension->MountPoint.Length =
|
||||
FsvrtDeviceExtension->MountPoint.MaximumLength = 0;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Irp->IoStatus.Information = 0;
|
||||
Result = STATUS_SUCCESS;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject);
|
||||
|
||||
if (0 == FsvrtDeviceExtension->MountPoint.Buffer)
|
||||
{
|
||||
Result = STATUS_INVALID_PARAMETER;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (2 * sizeof(WCHAR) == FsvrtDeviceExtension->MountPoint.Length)
|
||||
Result = FspMountmgrDeleteDrive(
|
||||
&FsvrtDeviceExtension->MountPoint);
|
||||
else
|
||||
Result = FspMountmgrNotifyDeleteDirectory(
|
||||
&FsvrtDeviceExtension->VolumeName,
|
||||
&FsvrtDeviceExtension->MountPoint);
|
||||
/* ignore Result */
|
||||
|
||||
FspFree(FsvrtDeviceExtension->MountPoint.Buffer);
|
||||
FsvrtDeviceExtension->MountPoint.Buffer = 0;
|
||||
FsvrtDeviceExtension->MountPoint.Length =
|
||||
FsvrtDeviceExtension->MountPoint.MaximumLength = 0;
|
||||
|
||||
Irp->IoStatus.Information = 0;
|
||||
Result = STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
exit:
|
||||
FspFsvrtDeviceUnlockMount(FsvrtDeviceObject);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
@ -1,30 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFOzCCAyOgAwIBAgIKYSBNtAAAAAAAJzANBgkqhkiG9w0BAQUFADB/MQswCQYD
|
||||
VQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEe
|
||||
MBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSkwJwYDVQQDEyBNaWNyb3Nv
|
||||
ZnQgQ29kZSBWZXJpZmljYXRpb24gUm9vdDAeFw0xMTA0MTUxOTQ1MzNaFw0yMTA0
|
||||
MTUxOTU1MzNaMGwxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMx
|
||||
GTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xKzApBgNVBAMTIkRpZ2lDZXJ0IEhp
|
||||
Z2ggQXNzdXJhbmNlIEVWIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
|
||||
ggEKAoIBAQDGzOVz5vvUu+UtLTKm3+WBP8nNJUm2cSrD1ZQ0Z6IKHLBfaaZAscS3
|
||||
so/QmKSpQVk609yU1jzbdDikSsxNJYL3SqVTEjju80ltcZF+Y7arpl/DpIT4T2JR
|
||||
vvjF7Ns4kuMG5QiRDMQoQVX7y1qJFX5x6DW/TXIJPb46OFBbdzEbjbPHJEWap6xt
|
||||
ABRaBLe6E+tRCphBQSJOZWGHgUFQpnlcid4ZSlfVLuZdHFMsfpjNGgYWpGhz0DQE
|
||||
E1yhcdNafFXbXmThN4cwVgTlEbQpgBLxeTmIogIRfCdmt4i3ePLKCqg4qwpkwr9m
|
||||
XZWEwaElHoddGlALIBLMQbtuC1E4uEvLAgMBAAGjgcswgcgwEQYDVR0gBAowCDAG
|
||||
BgRVHSAAMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSx
|
||||
PsNpA/i/RwHUmCYaCALvY2QrwzAfBgNVHSMEGDAWgBRi+wohW39DbhHaCVRQa/XS
|
||||
lnHxnjBVBgNVHR8ETjBMMEqgSKBGhkRodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20v
|
||||
cGtpL2NybC9wcm9kdWN0cy9NaWNyb3NvZnRDb2RlVmVyaWZSb290LmNybDANBgkq
|
||||
hkiG9w0BAQUFAAOCAgEAIIzBWe1vnGstwUo+dR1FTEFQHL2A6tmwkosGKhM/Uxae
|
||||
VjlqimO2eCR59X24uUehCpbC9su9omafBuGs0nkJDv083KwCDHCvPxvseH7U60sF
|
||||
YCbZc2GRIe2waGPglxKrb6AS7dmf0tonPLPkVvnR1IEPcb1CfKaJ3M3VvZWiq/GT
|
||||
EX3orDEpqF1mcEGd/HXJ1bMaOSrQhQVQi6yRysSTy3GlnaSUb1gM+m4gxAgxtYWd
|
||||
foH50j3KWxiFbAqG7CIJG6V0NE9/KLyVSqsdtpiwXQmkd3Z+76eOXYT2GCTL0W2m
|
||||
w6GcwhB1gP+dMv3mz0M6gvfOj+FyKptit1/tlRo5XC+UbUi3AV8zL7vcLXM0iQRC
|
||||
ChyLefmj+hfv+qEaEN/gssGV61wMBZc7NT4YiE3bbL8kiY3Ivdifezk6JKDV39Hz
|
||||
ShqX9qZveh+wkKmzrAE5kdNht2TxPlc4A6/OetK1kPWu3DmZ1bY8l+2myxbHfWsq
|
||||
TJCU5kxU/R7NIOzOaJyHWOlhYL7rDsnVGX2f6Xi9DqwhdQePqW7gjGoqa5zj52W8
|
||||
vC08bdwE3GdFNjKvBIG8qABuYUyVxVzUjo6fL8EydL29EWUDB83vt14CV9qG1Boo
|
||||
NK+ISbLPpd2CVm9oqhTiWVT+/+ru7+qScCJggeMlI8CfzA9JsjWqWMM6w9kWlBA=
|
||||
-----END CERTIFICATE-----
|
BIN
tools/DigiCertGlobalG3CodeSigningECCSHA3842021CA1.cer
Normal file
BIN
tools/DigiCertGlobalG3CodeSigningECCSHA3842021CA1.cer
Normal file
Binary file not shown.
@ -7,7 +7,8 @@ set Config=Debug
|
||||
set Suffix=x64
|
||||
set Deploy=C:\Deploy\winfsp
|
||||
set Target=Win10DBG
|
||||
set Chkpnt=winfsp
|
||||
set Chkpnt=docker+winfsp
|
||||
set CImage=mcr.microsoft.com/windows/servercore:1909
|
||||
if not X%1==X set Target=%1
|
||||
if not X%2==X set Chkpnt=%2
|
||||
|
||||
@ -15,6 +16,10 @@ if not X%2==X set Chkpnt=%2
|
||||
echo regsvr32 /s winfsp-x64.dll
|
||||
) > %~dp0..\build\VStudio\build\%Config%\deploy-setup.bat
|
||||
|
||||
(
|
||||
echo docker run -it --rm --isolation=process -v%Deploy%:%Deploy%:RW %CImage% cmd.exe /k cd %Deploy%
|
||||
) > %~dp0..\build\VStudio\build\%Config%\docker-run.bat
|
||||
|
||||
set Files=
|
||||
for %%f in (
|
||||
%~dp0..\build\VStudio\build\%Config%\
|
||||
@ -22,7 +27,9 @@ for %%f in (
|
||||
winfsp-%Suffix%.dll
|
||||
winfsp-tests-%Suffix%.exe
|
||||
memfs-%Suffix%.exe
|
||||
fsptool-%Suffix%.exe
|
||||
deploy-setup.bat
|
||||
docker-run.bat
|
||||
) do (
|
||||
set File=%%~f
|
||||
if [!File:~-1!] == [\] (
|
||||
|
@ -1,28 +1,53 @@
|
||||
@echo off
|
||||
|
||||
setlocal
|
||||
setlocal EnableDelayedExpansion
|
||||
|
||||
echo WINFSP INSTALLATION DIRECTORY AND LAUNCHER REGISTRATIONS
|
||||
reg query HKLM\SOFTWARE\WinFsp /s /reg:32
|
||||
REM Determine the SxS (side-by-side) identifier.
|
||||
set SxsDir=
|
||||
set RegKey="HKLM\SOFTWARE\WinFsp"
|
||||
set RegVal="SxsDir"
|
||||
reg query !RegKey! /v !RegVal! /reg:32 >nul 2>&1
|
||||
if !ERRORLEVEL! equ 0 (
|
||||
for /f "tokens=2,*" %%i in ('reg query !RegKey! /v !RegVal! /reg:32 ^| findstr !RegVal!') do (
|
||||
set SxsDir=%%j
|
||||
)
|
||||
)
|
||||
set SxsSuffix=
|
||||
if defined SxsDir (
|
||||
set SxsSuffix=!SxsDir:*SxS\sxs.=!
|
||||
if !SxsSuffix:~-1!==\ set SxsSuffix=!SxsSuffix:~0,-1!
|
||||
set SxsSuffix=+!SxsSuffix!
|
||||
)
|
||||
|
||||
echo WINFSP FSD
|
||||
sc query WinFsp!SxsSuffix!
|
||||
sc qc WinFsp!SxsSuffix!
|
||||
sc sdshow WinFsp!SxsSuffix!
|
||||
echo.
|
||||
echo.
|
||||
|
||||
echo WINFSP DLL REGISTRATIONS
|
||||
echo WINFSP DLL
|
||||
reg query HKLM\SYSTEM\CurrentControlSet\Control\NetworkProvider\Order
|
||||
reg query HKLM\SYSTEM\CurrentControlSet\Services\WinFsp.Np\NetworkProvider
|
||||
reg query HKLM\SYSTEM\CurrentControlSet\Services\EventLog\Application\WinFsp
|
||||
echo.
|
||||
|
||||
echo WINFSP FSD CONFIGURATION AND STATUS
|
||||
sc query WinFsp
|
||||
sc qc WinFsp
|
||||
sc sdshow WinFsp
|
||||
echo.
|
||||
|
||||
echo WINFSP LAUNCHER SERVICE CONFIGURATION AND STATUS
|
||||
echo WINFSP LAUNCHER
|
||||
sc query WinFsp.Launcher
|
||||
sc qc WinFsp.Launcher
|
||||
sc sdshow WinFsp.Launcher
|
||||
echo.
|
||||
echo.
|
||||
|
||||
echo WINFSP REGISTRY
|
||||
reg query HKLM\SOFTWARE\WinFsp /s /reg:32
|
||||
echo.
|
||||
|
||||
echo FILE SYSTEM FILTERS (REQUIRES ADMINISTRATOR)
|
||||
fltmc filters
|
||||
echo.
|
||||
echo.
|
||||
|
||||
echo OS INFORMATION
|
||||
systeminfo
|
||||
|
341
tools/make-release.ps1
Normal file
341
tools/make-release.ps1
Normal file
@ -0,0 +1,341 @@
|
||||
param (
|
||||
[string]$StateFile = "release.state"
|
||||
)
|
||||
|
||||
function Write-Stdout ($Message) {
|
||||
[System.Console]::WriteLine($Message)
|
||||
}
|
||||
|
||||
function Write-Stderr ($Message) {
|
||||
[System.Console]::Error.WriteLine($Message)
|
||||
}
|
||||
|
||||
function Git-Describe {
|
||||
$GitDesc = git describe --long --dirty
|
||||
if ($GitDesc -match "^(.+)-([0-9]+)-g([0-9A-Fa-f]+)-?(dirty)?$") {
|
||||
$matches[1]
|
||||
$matches[2]
|
||||
$matches[3]
|
||||
$matches[4]
|
||||
}
|
||||
}
|
||||
|
||||
function Git-Dirty {
|
||||
$Dirty = $False
|
||||
git status --porcelain=v2 2>$null | ForEach-Object {
|
||||
$Dirty = $True
|
||||
}
|
||||
return $Dirty
|
||||
}
|
||||
|
||||
function Git-LogGrep ($Tag) {
|
||||
git log -n 1 --grep $Tag
|
||||
}
|
||||
|
||||
function Get-ReleaseInfo ($Tag) {
|
||||
$Found = 0
|
||||
$ReleaseInfo = [PSCustomObject]@{
|
||||
Tag = ""
|
||||
ProductVersion = ""
|
||||
Prerelease = $False
|
||||
PreviousTag = ""
|
||||
PreviousProductVersion = ""
|
||||
Text = @()
|
||||
}
|
||||
foreach ($Line in Get-Content "$ProjectRoot\Changelog.md") {
|
||||
if ($Line -match "^## (v[^ ]+) *\(([^)]+)\)") {
|
||||
if ($Found) {
|
||||
$Found = 2
|
||||
$PreviousTag = $matches[1]
|
||||
$PreviousProductVersion = $matches[2]
|
||||
if ($PreviousTag -match "^v[0-9.]+$") {
|
||||
$ReleaseInfo.PreviousTag = $PreviousTag
|
||||
$ReleaseInfo.PreviousProductVersion = $PreviousProductVersion
|
||||
break
|
||||
}
|
||||
} elseif ($Tag -eq $matches[1]) {
|
||||
$Found = 1
|
||||
$ReleaseInfo.Tag = $matches[1]
|
||||
$ReleaseInfo.ProductVersion = $matches[2]
|
||||
$ReleaseInfo.Prerelease = !($ReleaseInfo.Tag -match "^v[0-9.]+$")
|
||||
}
|
||||
} elseif (1 -eq $Found) {
|
||||
$ReleaseInfo.Text += $Line
|
||||
}
|
||||
}
|
||||
if ($Found) {
|
||||
return $ReleaseInfo
|
||||
}
|
||||
}
|
||||
|
||||
function Get-FileVersion ($FileName) {
|
||||
return [System.Diagnostics.FileVersionInfo]::GetVersionInfo($FileName).FileVersion
|
||||
}
|
||||
|
||||
function Task ($ScriptBlock) {
|
||||
$Name = (Get-PSCallStack)[1].FunctionName
|
||||
if ($State -contains $Name) {
|
||||
return
|
||||
}
|
||||
|
||||
Write-Stdout $Name
|
||||
Invoke-Command -ScriptBlock $ScriptBlock
|
||||
Write-Stdout "$Name COMPLETE"
|
||||
|
||||
Add-Content $StateFile -Value $Name
|
||||
|
||||
exit 0
|
||||
}
|
||||
|
||||
function Check-Prerequisites {
|
||||
$Name = (Get-PSCallStack)[0].FunctionName
|
||||
|
||||
# check git.exe
|
||||
if (!(Get-Command "git.exe" -ErrorAction SilentlyContinue)) {
|
||||
Write-Stderr "error: cannot find git.exe"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# check gh.exe
|
||||
if (!(Get-Command "gh.exe" -ErrorAction SilentlyContinue)) {
|
||||
Write-Stderr "error: cannot find gh.exe"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# check choco.exe
|
||||
if (!(Get-Command "choco.exe" -ErrorAction SilentlyContinue)) {
|
||||
Write-Stderr "error: cannot find choco.exe"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# check git tag
|
||||
$Tag, $CommitCount, $Commit, $_ = Git-Describe
|
||||
if ("0" -ne $CommitCount) {
|
||||
Write-Stderr "error: cannot find clean git tag"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# check release info
|
||||
$script:ReleaseInfo = Get-ReleaseInfo $Tag
|
||||
if (!$script:ReleaseInfo) {
|
||||
Write-Stderr "error: cannot get release info for tag $Tag"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# check winfsp.sym
|
||||
if (!(Test-Path "$ProjectRoot\..\winfsp.sym" -ErrorAction SilentlyContinue)) {
|
||||
Write-Stderr "error: cannot find winfsp.sym repository"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# check winfsp.sym git status
|
||||
Push-Location "$ProjectRoot\..\winfsp.sym"
|
||||
$SymDirty = Git-Dirty
|
||||
Pop-Location
|
||||
if ($SymDirty) {
|
||||
Write-Stderr "error: winfsp.sym repository is dirty"
|
||||
exit 1
|
||||
}
|
||||
|
||||
if ($State -contains $Name) {
|
||||
if (!($State -contains "$Tag-$CommitCount-g$Commit")) {
|
||||
Write-Stderr "error: invalid state for tag $Tag"
|
||||
exit 1
|
||||
}
|
||||
} else {
|
||||
Add-Content $StateFile -Value $Name
|
||||
Add-Content $StateFile -Value "$Tag-$CommitCount-g$Commit"
|
||||
}
|
||||
}
|
||||
|
||||
function Check-Assets {
|
||||
# check winfsp.msi
|
||||
if (!(Test-Path "$ProjectRoot\build\VStudio\build\Release\winfsp*.msi" -ErrorAction SilentlyContinue)) {
|
||||
Write-Stderr "error: cannot find winfsp*.msi"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# check winfsp-tests.zip
|
||||
if (!(Test-Path "$ProjectRoot\build\VStudio\build\Release\winfsp-tests*.zip" -ErrorAction SilentlyContinue)) {
|
||||
Write-Stderr "error: cannot find winfsp-tests*.zip"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# check winfsp.nupkg
|
||||
if (!(Test-Path "$ProjectRoot\build\VStudio\build\Release\winfsp*.nupkg" -ErrorAction SilentlyContinue)) {
|
||||
Write-Stderr "error: cannot find winfsp*.nupkg"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# check winfsp signature
|
||||
if ("Valid" -ne (Get-AuthenticodeSignature "$ProjectRoot\build\VStudio\build\Release\winfsp-x64.sys" -ErrorAction SilentlyContinue).Status) {
|
||||
Write-Stderr "error: invalid winfsp signature"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
function Build-AssetsPhase1 {
|
||||
Task -ScriptBlock {
|
||||
Push-Location "$ProjectRoot"
|
||||
tools\build.bat Release
|
||||
if ($LastExitCode -ne 0) {
|
||||
Write-Stderr "error: cannot build assets"
|
||||
exit 1
|
||||
}
|
||||
Pop-Location
|
||||
|
||||
Write-Stdout @"
|
||||
|
||||
Upload file driver.cab to Microsoft Partner Center for attestation signing.
|
||||
When the file has been signed, download and extract to ~\Downloads\drivers
|
||||
|
||||
"@
|
||||
}
|
||||
}
|
||||
|
||||
function Build-AssetsPhase2 {
|
||||
Task -ScriptBlock {
|
||||
Check-Assets
|
||||
|
||||
# check signed drivers folder
|
||||
if (!(Test-Path ~\Downloads\drivers -ErrorAction SilentlyContinue)) {
|
||||
Write-Stderr "error: cannot find ~\Downloads\drivers"
|
||||
exit 1
|
||||
}
|
||||
|
||||
$SignedPackage = Resolve-Path ~\Downloads\drivers
|
||||
|
||||
$VerX64 = Get-FileVersion "$ProjectRoot\build\VStudio\build\Release\winfsp-x64.sys"
|
||||
if ($VerX64 -ne (Get-FileVersion "$SignedPackage\x64\winfsp-x64.sys")) {
|
||||
Write-Stderr "error: incompatible versions in ~\Downloads\drivers"
|
||||
exit 1
|
||||
}
|
||||
|
||||
Push-Location "$ProjectRoot"
|
||||
tools\build.bat Release $SignedPackage
|
||||
if ($LastExitCode -ne 0) {
|
||||
Write-Stderr "error: cannot build assets"
|
||||
exit 1
|
||||
}
|
||||
Pop-Location
|
||||
|
||||
Write-Stdout @"
|
||||
|
||||
Assets have been built and signed. You may want to perform some smoke testing.
|
||||
|
||||
"@
|
||||
}
|
||||
}
|
||||
|
||||
function Make-GitHubRelease {
|
||||
Task -ScriptBlock {
|
||||
Check-Assets
|
||||
|
||||
if ((Resolve-Path "$ProjectRoot\build\VStudio\build\Release\winfsp*.msi") -match "\\winfsp-(.+)\.msi") {
|
||||
$Version = $matches[1]
|
||||
}
|
||||
|
||||
$DownloadColor = "blue"
|
||||
$PrereleaseOpt = ""
|
||||
if ($ReleaseInfo.Prerelease) {
|
||||
$DownloadColor = "e52e4b"
|
||||
$PrereleaseOpt = "-p"
|
||||
}
|
||||
|
||||
$ReleaseNotes = @"
|
||||
[](https://github.com/billziss-gh/winfsp/releases/download/$($ReleaseInfo.Tag)/winfsp-$Version.msi)
|
||||
|
||||
[VirusTotal Scan Results]()
|
||||
|
||||
## CHANGES SINCE WINFSP $($ReleaseInfo.PreviousProductVersion)
|
||||
$($ReleaseInfo.Text -join "`n")
|
||||
"@
|
||||
|
||||
gh release create $ReleaseInfo.Tag --draft --title "WinFsp $($ReleaseInfo.ProductVersion)" --notes "$ReleaseNotes" $PrereleaseOpt (Resolve-Path "$ProjectRoot\build\VStudio\build\Release\winfsp*.msi") (Resolve-Path "$ProjectRoot\build\VStudio\build\Release\winfsp-tests*.zip")
|
||||
if ($LastExitCode -ne 0) {
|
||||
Write-Stderr "error: cannot create GitHub release"
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Stdout @"
|
||||
|
||||
Draft GitHub release for tag $($ReleaseInfo.Tag) has been created.
|
||||
Publish the release on GitHub and update the VirusTotal link.
|
||||
|
||||
"@
|
||||
}
|
||||
}
|
||||
|
||||
function Upload-Symbols {
|
||||
Task -ScriptBlock {
|
||||
Check-Assets
|
||||
|
||||
# check winfsp.sym git log
|
||||
Push-Location "$ProjectRoot\..\winfsp.sym"
|
||||
$SymHasTag = Git-LogGrep $ReleaseInfo.Tag
|
||||
Pop-Location
|
||||
if ($SymHasTag) {
|
||||
Write-Stderr "warning: winfsp.sym repository already has commit for tag $($ReleaseInfo.Tag)"
|
||||
} else {
|
||||
Push-Location "$ProjectRoot\..\winfsp.sym"
|
||||
.\tools\symadd.ps1 ..\winfsp\build\VStudio\build\Release -PdbKind Private
|
||||
if ($LastExitCode -ne 0) {
|
||||
Write-Stderr "error: cannot add files to winfsp.sym repository"
|
||||
exit 1
|
||||
}
|
||||
git add .
|
||||
if ($LastExitCode -ne 0) {
|
||||
Write-Stderr "error: cannot add files to winfsp.sym repository staging area"
|
||||
exit 1
|
||||
}
|
||||
git commit -m $ReleaseInfo.Tag
|
||||
if ($LastExitCode -ne 0) {
|
||||
Write-Stderr "error: cannot commit files to winfsp.sym repository"
|
||||
exit 1
|
||||
}
|
||||
Pop-Location
|
||||
|
||||
Write-Stdout @"
|
||||
|
||||
Commit for $($ReleaseInfo.Tag) symbols has been created.
|
||||
Push the winfsp.sym repository to GitHub.
|
||||
|
||||
"@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Make-ChocoRelease {
|
||||
Task -ScriptBlock {
|
||||
Check-Assets
|
||||
|
||||
Push-Location "$ProjectRoot\build\VStudio\build\Release"
|
||||
choco push
|
||||
if ($LastExitCode -ne 0) {
|
||||
Write-Stderr "error: cannot push to Chocolatey"
|
||||
exit 1
|
||||
}
|
||||
Pop-Location
|
||||
|
||||
Write-Stdout @"
|
||||
|
||||
Chocolatey release for $($ReleaseInfo.Tag) has been pushed.
|
||||
|
||||
"@
|
||||
}
|
||||
}
|
||||
|
||||
$ProjectRoot = Split-Path $PSScriptRoot
|
||||
$StateFile = Join-Path $pwd $StateFile
|
||||
|
||||
Write-Stdout "Using state file $StateFile"
|
||||
$State = @(Get-Content $StateFile -ErrorAction Ignore)
|
||||
|
||||
Check-Prerequisites
|
||||
|
||||
# Workflow tasks
|
||||
Build-AssetsPhase1
|
||||
Build-AssetsPhase2
|
||||
Make-GitHubRelease
|
||||
Upload-Symbols
|
||||
Make-ChocoRelease
|
@ -36,6 +36,10 @@ set dfl_tests=^
|
||||
winfsp-tests-x64-mountpoint-drive ^
|
||||
winfsp-tests-x64-mountpoint-dir ^
|
||||
winfsp-tests-x64-mountpoint-dir-case-sensitive ^
|
||||
winfsp-tests-x64-mountmgr-drive ^
|
||||
winfsp-tests-x64-mountmgr-dir ^
|
||||
winfsp-tests-x64-mountmgrfsd-drive ^
|
||||
winfsp-tests-x64-mountmgrfsd-dir ^
|
||||
winfsp-tests-x64-no-traverse ^
|
||||
winfsp-tests-x64-oplock ^
|
||||
winfsp-tests-x64-notify ^
|
||||
@ -43,28 +47,32 @@ set dfl_tests=^
|
||||
winfsp-tests-x64-external-share ^
|
||||
memfs-x64-disk-fsx ^
|
||||
memfs-x64-net-fsx ^
|
||||
memfs-x64-disk-standby ^
|
||||
memfs-x64-net-standby ^
|
||||
RETIRED-memfs-x64-disk-standby ^
|
||||
RETIRED-memfs-x64-net-standby ^
|
||||
memfs-x64-net-use ^
|
||||
memfs-x64-disk-winfstest ^
|
||||
memfs-x64-net-winfstest ^
|
||||
fscrash-x64 ^
|
||||
winfsp-tests-x86 ^
|
||||
winfsp-tests-x86-case-randomize ^
|
||||
winfsp-tests-x86-flushpurge ^
|
||||
winfsp-tests-x86-legacy-unlink-rename ^
|
||||
winfsp-tests-x86-mountpoint-drive ^
|
||||
winfsp-tests-x86-mountpoint-dir ^
|
||||
winfsp-tests-x86-mountpoint-dir-case-sensitive ^
|
||||
winfsp-tests-x86-no-traverse ^
|
||||
winfsp-tests-x86-oplock ^
|
||||
winfsp-tests-x86-notify ^
|
||||
RETIRED-winfsp-tests-x86-case-randomize ^
|
||||
RETIRED-winfsp-tests-x86-flushpurge ^
|
||||
RETIRED-winfsp-tests-x86-legacy-unlink-rename ^
|
||||
RETIRED-winfsp-tests-x86-mountpoint-drive ^
|
||||
RETIRED-winfsp-tests-x86-mountpoint-dir ^
|
||||
RETIRED-winfsp-tests-x86-mountpoint-dir-case-sensitive ^
|
||||
RETIRED-winfsp-tests-x86-mountmgr-drive ^
|
||||
RETIRED-winfsp-tests-x86-mountmgr-dir ^
|
||||
RETIRED-winfsp-tests-x86-mountmgrfsd-drive ^
|
||||
RETIRED-winfsp-tests-x86-mountmgrfsd-dir ^
|
||||
RETIRED-winfsp-tests-x86-no-traverse ^
|
||||
RETIRED-winfsp-tests-x86-oplock ^
|
||||
RETIRED-winfsp-tests-x86-notify ^
|
||||
winfsp-tests-x86-external ^
|
||||
winfsp-tests-x86-external-share ^
|
||||
memfs-x86-disk-fsx ^
|
||||
memfs-x86-net-fsx ^
|
||||
memfs-x86-disk-standby ^
|
||||
memfs-x86-net-standby ^
|
||||
RETIRED-memfs-x86-disk-standby ^
|
||||
RETIRED-memfs-x86-net-standby ^
|
||||
memfs-x86-net-use ^
|
||||
memfs-x86-disk-winfstest ^
|
||||
memfs-x86-net-winfstest ^
|
||||
@ -115,20 +123,25 @@ set opt_tests=^
|
||||
|
||||
set tests=
|
||||
for %%f in (%dfl_tests%) do (
|
||||
set test=%%f
|
||||
if NOT "XRETIRED-!test:RETIRED-=!"=="X!test!" (
|
||||
if X%2==X (
|
||||
set tests=!tests! %%f
|
||||
) else (
|
||||
set test=%%f
|
||||
if "X%2!test:%2=!"=="X!test!" set tests=!tests! %%f
|
||||
)
|
||||
)
|
||||
)
|
||||
for %%f in (%opt_tests%) do (
|
||||
set test=%%f
|
||||
if NOT "XRETIRED-!test:RETIRED-=!"=="X!test!" (
|
||||
if X%2==X (
|
||||
rem
|
||||
) else (
|
||||
set test=%%f
|
||||
if "X%2!test:%2=!"=="X!test!" set tests=!tests! %%f
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
set testpass=0
|
||||
@ -151,11 +164,12 @@ for %%f in (%tests%) do (
|
||||
set "endtimecalc=!endtime:%time:~8,1%=%%100)*100+1!" & set "begtimecalc=!begtime:%time:~8,1%=%%100)*100+1!"
|
||||
set /A "duration=((((10!endtimecalc:%time:~2,1%=%%100)*60+1!%%100)-((((10!begtimecalc:%time:~2,1%=%%100)*60+1!%%100), duration-=(duration>>31)*24*60*60*100"
|
||||
set /A "duration=10*duration"
|
||||
set /A "durationSec=duration/1000"
|
||||
|
||||
if !ERRORLEVEL_save! neq 0 (
|
||||
set /a testfail=testfail+1
|
||||
|
||||
echo === Failed %%f ^(!duration! ms^)
|
||||
echo === Failed %%f ^(!durationSec!s^)
|
||||
|
||||
if defined APPVEYOR (
|
||||
appveyor UpdateTest "%%f" -FileName None -Framework None -Outcome Failed -Duration !duration!
|
||||
@ -163,7 +177,7 @@ for %%f in (%tests%) do (
|
||||
) else (
|
||||
set /a testpass=testpass+1
|
||||
|
||||
echo === Passed %%f ^(!duration! ms^)
|
||||
echo === Passed %%f ^(!durationSec!s^)
|
||||
|
||||
if defined APPVEYOR (
|
||||
appveyor UpdateTest "%%f" -FileName None -Framework None -Outcome Passed -Duration !duration!
|
||||
@ -232,6 +246,30 @@ winfsp-tests-x64 --mountpoint=mymnt * +ea*
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:winfsp-tests-x64-mountmgr-drive
|
||||
winfsp-tests-x64 --mountpoint=\\.\X: --resilient * +ea* -exec*
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:winfsp-tests-x64-mountmgr-dir
|
||||
winfsp-tests-x64 --mountpoint=\\.\%cd%\mnt --resilient * +ea* -exec*
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:winfsp-tests-x64-mountmgrfsd-drive
|
||||
reg add HKLM\Software\WinFsp /v MountUseMountmgrFromFSD /t REG_DWORD /d 1 /f /reg:32
|
||||
winfsp-tests-x64 --mountpoint=\\.\X: --resilient * +ea* -exec*
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
reg delete HKLM\Software\WinFsp /v MountUseMountmgrFromFSD /f /reg:32
|
||||
exit /b 0
|
||||
|
||||
:winfsp-tests-x64-mountmgrfsd-dir
|
||||
reg add HKLM\Software\WinFsp /v MountUseMountmgrFromFSD /t REG_DWORD /d 1 /f /reg:32
|
||||
winfsp-tests-x64 --mountpoint=\\.\%cd%\mnt --resilient * +ea* -exec*
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
reg delete HKLM\Software\WinFsp /v MountUseMountmgrFromFSD /f /reg:32
|
||||
exit /b 0
|
||||
|
||||
:winfsp-tests-x64-no-traverse
|
||||
winfsp-tests-x64 --no-traverse * +ea*
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
@ -282,6 +320,30 @@ winfsp-tests-x86 --mountpoint=mymnt * +ea*
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:winfsp-tests-x86-mountmgr-drive
|
||||
winfsp-tests-x86 --mountpoint=\\.\X: --resilient * +ea* -exec*
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:winfsp-tests-x86-mountmgr-dir
|
||||
winfsp-tests-x86 --mountpoint=\\.\%cd%\mnt --resilient * +ea* -exec*
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
exit /b 0
|
||||
|
||||
:winfsp-tests-x86-mountmgrfsd-drive
|
||||
reg add HKLM\Software\WinFsp /v MountUseMountmgrFromFSD /t REG_DWORD /d 1 /f /reg:32
|
||||
winfsp-tests-x86 --mountpoint=\\.\X: --resilient * +ea* -exec*
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
reg delete HKLM\Software\WinFsp /v MountUseMountmgrFromFSD /f /reg:32
|
||||
exit /b 0
|
||||
|
||||
:winfsp-tests-x86-mountmgrfsd-dir
|
||||
reg add HKLM\Software\WinFsp /v MountUseMountmgrFromFSD /t REG_DWORD /d 1 /f /reg:32
|
||||
winfsp-tests-x86 --mountpoint=\\.\%cd%\mnt --resilient * +ea* -exec*
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
reg delete HKLM\Software\WinFsp /v MountUseMountmgrFromFSD /f /reg:32
|
||||
exit /b 0
|
||||
|
||||
:winfsp-tests-x86-no-traverse
|
||||
winfsp-tests-x86 --no-traverse * +ea*
|
||||
if !ERRORLEVEL! neq 0 goto fail
|
||||
|
24
tools/sxsident.bat
Normal file
24
tools/sxsident.bat
Normal file
@ -0,0 +1,24 @@
|
||||
@echo off
|
||||
|
||||
setlocal
|
||||
setlocal EnableDelayedExpansion
|
||||
|
||||
set SxsDir=
|
||||
set RegKey="HKLM\SOFTWARE\WinFsp"
|
||||
set RegVal="SxsDir"
|
||||
reg query !RegKey! /v !RegVal! /reg:32 >nul 2>&1
|
||||
if !ERRORLEVEL! equ 0 (
|
||||
for /f "tokens=2,*" %%i in ('reg query !RegKey! /v !RegVal! /reg:32 ^| findstr !RegVal!') do (
|
||||
set SxsDir=%%j
|
||||
)
|
||||
)
|
||||
if defined SxsDir (
|
||||
set SxsDir=!SxsDir:*SxS\sxs.=!
|
||||
if !SxsDir:~-1!==\ set SxsDir=!SxsDir:~0,-1!
|
||||
echo !SxsDir!
|
||||
)
|
||||
|
||||
exit /b 0
|
||||
|
||||
:fail
|
||||
exit /b 1
|
@ -40,6 +40,11 @@ FSP_FSCTL_STATIC_ASSERT(MEMFS_MAX_PATH > MAX_PATH,
|
||||
*/
|
||||
//#define MEMFS_STANDALONE
|
||||
|
||||
/*
|
||||
* Define the MEMFS_DISPATCHER_STOPPED macro to include DispatcherStopped support.
|
||||
*/
|
||||
#define MEMFS_DISPATCHER_STOPPED
|
||||
|
||||
/*
|
||||
* Define the MEMFS_NAME_NORMALIZATION macro to include name normalization support.
|
||||
*/
|
||||
@ -2269,6 +2274,14 @@ static NTSTATUS SetEa(FSP_FILE_SYSTEM *FileSystem,
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MEMFS_DISPATCHER_STOPPED)
|
||||
static void DispatcherStopped(FSP_FILE_SYSTEM *FileSystem,
|
||||
BOOLEAN Normally)
|
||||
{
|
||||
//FspDebugLog(__FUNCTION__ ": Normally=%d\n", Normally);
|
||||
}
|
||||
#endif
|
||||
|
||||
static FSP_FILE_SYSTEM_INTERFACE MemfsInterface =
|
||||
{
|
||||
GetVolumeInfo,
|
||||
@ -2336,6 +2349,12 @@ static FSP_FILE_SYSTEM_INTERFACE MemfsInterface =
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
#endif
|
||||
0,
|
||||
#if defined(MEMFS_DISPATCHER_STOPPED)
|
||||
DispatcherStopped,
|
||||
#else
|
||||
0,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -62,7 +62,8 @@ static NTSTATUS GetFileInfoInternal(HANDLE Handle, FSP_FSCTL_FILE_INFO *FileInfo
|
||||
FileInfo->LastAccessTime = ((PLARGE_INTEGER)&ByHandleFileInfo.ftLastAccessTime)->QuadPart;
|
||||
FileInfo->LastWriteTime = ((PLARGE_INTEGER)&ByHandleFileInfo.ftLastWriteTime)->QuadPart;
|
||||
FileInfo->ChangeTime = FileInfo->LastWriteTime;
|
||||
FileInfo->IndexNumber = 0;
|
||||
FileInfo->IndexNumber =
|
||||
((UINT64)ByHandleFileInfo.nFileIndexHigh << 32) | (UINT64)ByHandleFileInfo.nFileIndexLow;
|
||||
FileInfo->HardLinks = 0;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
|
48
tst/winfsp-tests/loadun-test.c
Normal file
48
tst/winfsp-tests/loadun-test.c
Normal file
@ -0,0 +1,48 @@
|
||||
/**
|
||||
* @file loadun-test.c
|
||||
*
|
||||
* @copyright 2015-2022 Bill Zissimopoulos
|
||||
*/
|
||||
/*
|
||||
* This file is part of WinFsp.
|
||||
*
|
||||
* You can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License version 3 as published by the Free Software
|
||||
* Foundation.
|
||||
*
|
||||
* Licensees holding a valid commercial license may use this software
|
||||
* in accordance with the commercial license agreement provided in
|
||||
* conjunction with the software. The terms and conditions of any such
|
||||
* commercial license agreement shall govern, supersede, and render
|
||||
* ineffective any application of the GPLv3 license to this software,
|
||||
* notwithstanding of any reference thereto in the software or
|
||||
* associated repository.
|
||||
*/
|
||||
|
||||
#include <winfsp/winfsp.h>
|
||||
#include <tlib/testsuite.h>
|
||||
|
||||
#include "winfsp-tests.h"
|
||||
|
||||
static void load_unload_test(void)
|
||||
{
|
||||
/* this is not a real test! */
|
||||
|
||||
FspFsctlStartService();
|
||||
FspFsctlStartService();
|
||||
|
||||
FspFsctlStopService();
|
||||
FspFsctlStopService();
|
||||
}
|
||||
|
||||
void load_unload_tests(void)
|
||||
{
|
||||
if (OptExternal)
|
||||
return;
|
||||
|
||||
/*
|
||||
* An attempt to unload the driver while other tests are executing can make all tests fail.
|
||||
* For this reason we do not enable this test, except when doing specialized testing.
|
||||
*/
|
||||
//TEST_OPT(load_unload_test);
|
||||
}
|
@ -67,6 +67,9 @@ void *memfs_start_ex(ULONG Flags, ULONG FileInfoTimeout)
|
||||
Result = MemfsStart(Memfs);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
|
||||
Result = FspFsctlTransact(MemfsFileSystem(Memfs)->VolumeHandle, 0, 0, 0, 0, FALSE);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
|
||||
memfs_running = 1;
|
||||
memfs_handle = MemfsFileSystem(Memfs)->VolumeHandle;
|
||||
|
||||
|
@ -215,6 +215,9 @@ void mount_volume_transact_dotest(PWSTR DeviceName, PWSTR Prefix)
|
||||
ASSERT(0 == wcsncmp(L"\\Device\\Volume{", VolumeName, 15));
|
||||
ASSERT(INVALID_HANDLE_VALUE != VolumeHandle);
|
||||
|
||||
Result = FspFsctlTransact(VolumeHandle, 0, 0, 0, 0, FALSE);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
|
||||
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\file0",
|
||||
Prefix ? L"" : L"\\\\?\\GLOBALROOT", Prefix ? Prefix : VolumeName);
|
||||
Thread = (HANDLE)_beginthreadex(0, 0, mount_volume_transact_dotest_thread, FilePath, 0, 0);
|
||||
@ -246,6 +249,8 @@ void mount_volume_transact_dotest(PWSTR DeviceName, PWSTR Prefix)
|
||||
ASSERT(0 != Request->Hint);
|
||||
ASSERT(FspFsctlTransactCreateKind == Request->Kind ||
|
||||
FspFsctlTransactQueryVolumeInformationKind == Request->Kind);
|
||||
/* since we made RejectIrpPriorToTransact0 mandatory the assertions below do not hold */
|
||||
#if 0
|
||||
if (FspFsctlTransactCreateKind == Request->Kind)
|
||||
{
|
||||
ASSERT(FILE_CREATE == ((Request->Req.Create.CreateOptions >> 24) & 0xff));
|
||||
@ -265,6 +270,7 @@ void mount_volume_transact_dotest(PWSTR DeviceName, PWSTR Prefix)
|
||||
ASSERT((wcslen((PVOID)Request->Buffer) + 1) * sizeof(WCHAR) == Request->FileName.Size);
|
||||
ASSERT(0 == mywcscmp((PVOID)Request->Buffer, -1, L"\\file0", -1));
|
||||
}
|
||||
#endif
|
||||
|
||||
ASSERT(FspFsctlTransactCanProduceResponse(Response, ResponseBufEnd));
|
||||
|
||||
@ -294,7 +300,8 @@ void mount_volume_transact_dotest(PWSTR DeviceName, PWSTR Prefix)
|
||||
GetExitCodeThread(Thread, &ExitCode);
|
||||
CloseHandle(Thread);
|
||||
|
||||
ASSERT(ERROR_ACCESS_DENIED == ExitCode || ERROR_OPERATION_ABORTED == ExitCode);
|
||||
ASSERT(0 != ExitCode);
|
||||
//ASSERT(ERROR_ACCESS_DENIED == ExitCode || ERROR_OPERATION_ABORTED == ExitCode);
|
||||
}
|
||||
|
||||
void mount_volume_transact_test(void)
|
||||
|
@ -158,7 +158,10 @@ static void posix_map_sid_test(void)
|
||||
|
||||
CloseHandle(Token);
|
||||
|
||||
for (size_t i = 0; sizeof map / sizeof map[0] > i; i++)
|
||||
size_t n = sizeof map / sizeof map[0];
|
||||
if (RunningInContainer)
|
||||
n -= 2; /* container: disable tests for "user manager\containeradministrator" */
|
||||
for (size_t i = 0; n > i; i++)
|
||||
{
|
||||
Success = ConvertStringSidToSidW(map[i].SidStr, &Sid0);
|
||||
ASSERT(Success);
|
||||
|
@ -187,6 +187,8 @@ void timeout_transact_dotest(PWSTR DeviceName, PWSTR Prefix)
|
||||
ASSERT(0 == wcsncmp(L"\\Device\\Volume{", VolumeName, 15));
|
||||
ASSERT(INVALID_HANDLE_VALUE != VolumeHandle);
|
||||
|
||||
Result = FspFsctlTransact(VolumeHandle, 0, 0, 0, 0, FALSE);
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
|
||||
FSP_FSCTL_DECLSPEC_ALIGN UINT8 RequestBuf[FSP_FSCTL_TRANSACT_BATCH_BUFFER_SIZEMIN];
|
||||
FSP_FSCTL_DECLSPEC_ALIGN UINT8 ResponseBuf[FSP_FSCTL_TRANSACT_RSP_SIZEMAX];
|
||||
@ -223,6 +225,8 @@ void timeout_transact_dotest(PWSTR DeviceName, PWSTR Prefix)
|
||||
ASSERT(0 != Request->Hint);
|
||||
ASSERT(FspFsctlTransactCreateKind == Request->Kind ||
|
||||
FspFsctlTransactQueryVolumeInformationKind == Request->Kind);
|
||||
/* since we made RejectIrpPriorToTransact0 mandatory the assertions below do not hold */
|
||||
#if 0
|
||||
if (FspFsctlTransactCreateKind == Request->Kind)
|
||||
{
|
||||
ASSERT(FILE_CREATE == ((Request->Req.Create.CreateOptions >> 24) & 0xff));
|
||||
@ -239,6 +243,7 @@ void timeout_transact_dotest(PWSTR DeviceName, PWSTR Prefix)
|
||||
ASSERT(!Request->Req.Create.OpenTargetDirectory);
|
||||
ASSERT(!Request->Req.Create.CaseSensitive);
|
||||
}
|
||||
#endif
|
||||
|
||||
ResponseBufSize = 0;
|
||||
RequestBufSize = sizeof RequestBuf;
|
||||
|
@ -89,7 +89,7 @@ static void volpath_test(void)
|
||||
* when *not* using the MountManager and therefore disable
|
||||
* this test when using a non-MountManager mount point.
|
||||
*/
|
||||
if (!NtfsTests && !OptMountPoint)
|
||||
if (NtfsTests || OptMountPoint)
|
||||
return;
|
||||
|
||||
if (WinFspDiskTests)
|
||||
@ -107,8 +107,15 @@ static void volpath_mount_dotest(ULONG Flags, PWSTR Prefix, PWSTR MountPoint)
|
||||
BOOLEAN Success, VolumePathNameSuccess[8];
|
||||
WCHAR FilePath[MAX_PATH];
|
||||
WCHAR VolumePathName[MAX_PATH], VolumeName[MAX_PATH];
|
||||
WCHAR FinalPath[MAX_PATH];
|
||||
DWORD FinalResult;
|
||||
|
||||
Result = FspFileSystemSetMountPoint(MemfsFileSystem(memfs), MountPoint);
|
||||
if (STATUS_ACCESS_DENIED == Result)
|
||||
{
|
||||
FspDebugLog(__FUNCTION__ ": need Administrator\n");
|
||||
goto exit;
|
||||
}
|
||||
ASSERT(NT_SUCCESS(Result));
|
||||
|
||||
Prefix = FspFileSystemMountPoint(MemfsFileSystem(memfs));
|
||||
@ -125,6 +132,9 @@ static void volpath_mount_dotest(ULONG Flags, PWSTR Prefix, PWSTR MountPoint)
|
||||
Handle = CreateFileW(FilePath,
|
||||
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
ASSERT(INVALID_HANDLE_VALUE != Handle);
|
||||
FinalResult = GetFinalPathNameByHandleW(
|
||||
Handle, FinalPath, MAX_PATH - 1, VOLUME_NAME_DOS | FILE_NAME_OPENED);
|
||||
ASSERT(0 != FinalResult && FinalResult < MAX_PATH);
|
||||
CloseHandle(Handle);
|
||||
|
||||
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\",
|
||||
@ -187,6 +197,9 @@ static void volpath_mount_dotest(ULONG Flags, PWSTR Prefix, PWSTR MountPoint)
|
||||
Handle = CreateFileW(FilePath,
|
||||
GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
ASSERT(INVALID_HANDLE_VALUE != Handle);
|
||||
FinalResult = GetFinalPathNameByHandleW(
|
||||
Handle, FinalPath, MAX_PATH - 1, VOLUME_NAME_DOS | FILE_NAME_OPENED);
|
||||
ASSERT(0 != FinalResult && FinalResult < MAX_PATH);
|
||||
CloseHandle(Handle);
|
||||
|
||||
StringCbPrintfW(FilePath, sizeof FilePath, L"%s%s\\",
|
||||
@ -232,6 +245,7 @@ static void volpath_mount_dotest(ULONG Flags, PWSTR Prefix, PWSTR MountPoint)
|
||||
ASSERT(VolumePathNameSuccess[6]);
|
||||
}
|
||||
|
||||
exit:
|
||||
memfs_stop(memfs);
|
||||
}
|
||||
|
||||
@ -240,8 +254,13 @@ static void volpath_mount_test(void)
|
||||
/*
|
||||
* This test does FspFileSystemSetMountPoint and therefore
|
||||
* cannot be used with --external or --mountpoint.
|
||||
*
|
||||
* Also the MountMgr appears to be buggy and fail with spurious
|
||||
* STATUS_NOT_SUPPORTED and STATUS_INVALID_PARAMETER error codes
|
||||
* under Windows Containers (at least with ServerCore 1909). So
|
||||
* disable if RunningInContainer.
|
||||
*/
|
||||
if (NtfsTests || OptMountPoint)
|
||||
if (NtfsTests || OptMountPoint || RunningInContainer)
|
||||
return;
|
||||
|
||||
if (WinFspDiskTests)
|
||||
@ -270,6 +289,24 @@ static void volpath_mount_test(void)
|
||||
|
||||
//volpath_mount_dotest(MemfsDisk, 0, 0);
|
||||
volpath_mount_dotest(MemfsDisk, 0, MountPoint);
|
||||
|
||||
WCHAR DirBuf[MAX_PATH];
|
||||
int DirBufLen;
|
||||
GetTestDirectory(DirBuf);
|
||||
ASSERT(
|
||||
L'\\' == DirBuf[0] &&
|
||||
L'\\' == DirBuf[1] &&
|
||||
L'?' == DirBuf[2] &&
|
||||
L'\\' == DirBuf[3]);
|
||||
DirBuf[2] = '.';
|
||||
DirBufLen = lstrlenW(DirBuf);
|
||||
ASSERT(MAX_PATH >= DirBufLen + 5);
|
||||
DirBuf[DirBufLen++] = L'\\';
|
||||
DirBuf[DirBufLen++] = L'm';
|
||||
DirBuf[DirBufLen++] = L'n';
|
||||
DirBuf[DirBufLen++] = L't';
|
||||
DirBuf[DirBufLen++] = L'\0';
|
||||
volpath_mount_dotest(MemfsDisk, 0, DirBuf);
|
||||
}
|
||||
if (WinFspNetTests)
|
||||
{
|
||||
@ -290,7 +327,12 @@ void volpath_tests(void)
|
||||
/*
|
||||
* This test does FspFileSystemSetMountPoint and therefore
|
||||
* cannot be used with --external or --mountpoint.
|
||||
*
|
||||
* Also the MountMgr appears to be buggy and fail with spurious
|
||||
* STATUS_NOT_SUPPORTED and STATUS_INVALID_PARAMETER error codes
|
||||
* under Windows Containers (at least with ServerCore 1909). So
|
||||
* disable if RunningInContainer.
|
||||
*/
|
||||
if (!NtfsTests && !OptMountPoint)
|
||||
if (!NtfsTests && !OptMountPoint && !RunningInContainer)
|
||||
TEST(volpath_mount_test);
|
||||
}
|
||||
|
@ -32,6 +32,7 @@
|
||||
int NtfsTests = 0;
|
||||
int WinFspDiskTests = 1;
|
||||
int WinFspNetTests = 1;
|
||||
int RunningInContainer = 0;
|
||||
|
||||
BOOLEAN OptExternal = FALSE;
|
||||
BOOLEAN OptFuseExternal = FALSE;
|
||||
@ -220,6 +221,7 @@ LONG WINAPI UnhandledExceptionHandler(struct _EXCEPTION_POINTERS *ExceptionInfo)
|
||||
argv[argc] = 0
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
TESTSUITE(load_unload_tests);
|
||||
TESTSUITE(fuse_opt_tests);
|
||||
TESTSUITE(fuse_tests);
|
||||
TESTSUITE(posix_tests);
|
||||
@ -258,6 +260,12 @@ int main(int argc, char *argv[])
|
||||
if (0 == getenv("WINFSP_TESTS_EXCEPTION_FILTER_DISABLE"))
|
||||
SetUnhandledExceptionFilter(UnhandledExceptionHandler);
|
||||
|
||||
RunningInContainer = ERROR_SUCCESS == RegGetValueW(
|
||||
HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control",
|
||||
L"ContainerType",
|
||||
RRF_RT_REG_DWORD, 0,
|
||||
0, 0);
|
||||
|
||||
for (int argi = 1; argc > argi; argi++)
|
||||
{
|
||||
const char *a = argv[argi];
|
||||
@ -266,6 +274,7 @@ int main(int argc, char *argv[])
|
||||
if (0 == strcmp("--ntfs", a) || 0 == strcmp("--external", a))
|
||||
{
|
||||
OptExternal = TRUE;
|
||||
OptFuseExternal = FALSE;
|
||||
NtfsTests = 1;
|
||||
WinFspDiskTests = 0;
|
||||
WinFspNetTests = 0;
|
||||
@ -404,6 +413,10 @@ int main(int argc, char *argv[])
|
||||
if (!NtfsTests && OptShareName)
|
||||
ABORT("option --share requires --ntfs/--external");
|
||||
|
||||
if (RunningInContainer)
|
||||
/* container: disable network file system tests */
|
||||
WinFspNetTests = 0;
|
||||
|
||||
DisableBackupRestorePrivileges();
|
||||
|
||||
AddNetShareIfNeeded();
|
||||
|
@ -213,6 +213,7 @@ VOID GetTestDirectoryEx(PWSTR DirBuf, ULONG DirBufSize, PWSTR DriveBuf);
|
||||
extern int NtfsTests;
|
||||
extern int WinFspDiskTests;
|
||||
extern int WinFspNetTests;
|
||||
extern int RunningInContainer;
|
||||
|
||||
extern BOOLEAN OptExternal;
|
||||
extern BOOLEAN OptFuseExternal;
|
||||
|
Reference in New Issue
Block a user