mirror of
https://github.com/winfsp/winfsp.git
synced 2025-07-03 09:22:57 -05:00
Compare commits
45 Commits
Author | SHA1 | Date | |
---|---|---|---|
858df29ba2 | |||
4366866653 | |||
e4b808806c | |||
13cee6e019 | |||
35b9cb15a3 | |||
0d8f0f9ac8 | |||
a4e2ad9dd6 | |||
9b4318c655 | |||
5827b1fa9c | |||
913f7ac9cd | |||
0e2f46dc90 | |||
e7cba96c74 | |||
03db443406 | |||
0b65bc7e01 | |||
12e1caaa98 | |||
7a690a789b | |||
8ca419830c | |||
c310d8ea1b | |||
c3ddf73661 | |||
6b00b8e28a | |||
35c722e91b | |||
ae8802514b | |||
e90aa46a27 | |||
760cd5e46f | |||
b36b6c60e2 | |||
e4984bf675 | |||
0c8bcd5d7d | |||
b5d8cd3ea6 | |||
af5f409233 | |||
cffb066d46 | |||
804434d836 | |||
f7595e40b6 | |||
669dd07ce2 | |||
b6fa54d301 | |||
342e7e39e2 | |||
9dfdd19616 | |||
2c651b1bd8 | |||
41764f7b41 | |||
08e697c52c | |||
66cc043149 | |||
518cd0e8c0 | |||
c0344f53b0 | |||
76445a5403 | |||
0577b8febb | |||
610a7ac2a6 |
37
README.md
37
README.md
@ -1,5 +1,7 @@
|
|||||||
# WinFsp - Windows File System Proxy
|
# WinFsp - Windows File System Proxy
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
WinFsp is a set of software components for Windows computers that allows the creation of user mode file systems. In this sense it is similar to FUSE (Filesystem in Userspace), which provides the same functionality on UNIX-like computers.
|
WinFsp is a set of software components for Windows computers that allows the creation of user mode file systems. In this sense it is similar to FUSE (Filesystem in Userspace), which provides the same functionality on UNIX-like computers.
|
||||||
|
|
||||||
Some of the benefits and features of using WinFsp are listed below:
|
Some of the benefits and features of using WinFsp are listed below:
|
||||||
@ -34,9 +36,40 @@ The project source code is organized as follows:
|
|||||||
* tst/memfs: Source code to an example file system written in C++ (memfs).
|
* tst/memfs: Source code to an example file system written in C++ (memfs).
|
||||||
* tst/winfsp-tests: WinFsp test suite.
|
* tst/winfsp-tests: WinFsp test suite.
|
||||||
|
|
||||||
## Building
|
## Building and Running
|
||||||
|
|
||||||
In order to build WinFsp you will need Windows 10 and Visual Studio 2015. You will also need the Windows Driver Kit (WDK) 10.
|
In order to build WinFsp you will need the following:
|
||||||
|
|
||||||
|
* Windows 10
|
||||||
|
* Visual Studio 2015
|
||||||
|
* Windows Driver Kit (WDK) 10
|
||||||
|
* [Wix toolset](http://wixtoolset.org)
|
||||||
|
|
||||||
|
If you build the driver yourself it will not be signed and Windows will refuse to load it unless you enable "testsigning". You can enable "testsigning" using the command `bcdedit.exe -set testsigning`. For more information see this [document](http://www.secfs.net/winfsp/develop/debug/).
|
||||||
|
|
||||||
|
WinFsp is designed to run on Vista and above. It has been tested on the following platforms so far:
|
||||||
|
|
||||||
|
* Windows 7 Enterprise
|
||||||
|
* Windows 8 Pro
|
||||||
|
* Windows 10 Pro
|
||||||
|
* Windows Server 2012
|
||||||
|
|
||||||
|
## How to Help
|
||||||
|
|
||||||
|
I am looking for help in the following areas:
|
||||||
|
|
||||||
|
* If you have a file system that runs on FUSE please consider porting it to WinFsp. WinFsp has a native API, but it also has a FUSE (high-level) API.
|
||||||
|
* If you are working with a language other than C/C++ (e.g. Delphi, C#, etc.) and you are interested in porting/wrapping WinFsp I would love to hear from you.
|
||||||
|
* There are a number of outstanding issues listed in the [GitHub repository](https://github.com/billziss-gh/winfsp/issues) ~~[BitBucket repository](https://bitbucket.org/billziss/winfsp/issues?status=new&status=open)~~. Many of these require knowledge of Windows kernel-mode and an understanding of the internals of WinFsp so they are not for the faint of heart. If you decide to tackle any of those please coordinate with me as I am actively working on that issue list.
|
||||||
|
|
||||||
|
In all cases I can provide ideas and/or support.
|
||||||
|
|
||||||
|
## Where to Discuss
|
||||||
|
|
||||||
|
If you wish to discuss WinFsp there are now two options:
|
||||||
|
|
||||||
|
- [WinFsp Google Group](https://groups.google.com/forum/#!forum/winfsp)
|
||||||
|
- [Author's Twitter](https://twitter.com/BZissimopoulos)
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ environment:
|
|||||||
install:
|
install:
|
||||||
- git submodule update --init --recursive
|
- git submodule update --init --recursive
|
||||||
- appveyor AddMessage "Change boot configuration and reboot" -Category Information
|
- appveyor AddMessage "Change boot configuration and reboot" -Category Information
|
||||||
|
- verifier /standard /driver winfsp-x64.sys
|
||||||
- bcdedit /set testsigning on
|
- bcdedit /set testsigning on
|
||||||
- ps: Restart-Computer -Force
|
- ps: Restart-Computer -Force
|
||||||
- ps: Start-Sleep -s 10
|
- ps: Start-Sleep -s 10
|
||||||
@ -19,3 +20,4 @@ test_script:
|
|||||||
- for %%f in ("build\VStudio\build\%CONFIGURATION%\winfsp-*.msi") do start /wait msiexec /i %%f /qn INSTALLLEVEL=1000
|
- for %%f in ("build\VStudio\build\%CONFIGURATION%\winfsp-*.msi") do start /wait msiexec /i %%f /qn INSTALLLEVEL=1000
|
||||||
- tools\nmake-ext-test.bat %CONFIGURATION%
|
- tools\nmake-ext-test.bat %CONFIGURATION%
|
||||||
- tools\run-tests.bat %CONFIGURATION%
|
- tools\run-tests.bat %CONFIGURATION%
|
||||||
|
- verifier /query
|
||||||
|
BIN
art/winfsp-outln.afdesign
Normal file
BIN
art/winfsp-outln.afdesign
Normal file
Binary file not shown.
BIN
art/winfsp-solid.afdesign
Normal file
BIN
art/winfsp-solid.afdesign
Normal file
Binary file not shown.
BIN
art/winfsp-solid.png
Normal file
BIN
art/winfsp-solid.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
BIN
art/wixbanner.pxm
Normal file
BIN
art/wixbanner.pxm
Normal file
Binary file not shown.
BIN
art/wixdialog.pxm
Normal file
BIN
art/wixdialog.pxm
Normal file
Binary file not shown.
@ -45,13 +45,14 @@
|
|||||||
</Directory>
|
</Directory>
|
||||||
|
|
||||||
<DirectoryRef Id="INSTALLDIR">
|
<DirectoryRef Id="INSTALLDIR">
|
||||||
<Component Id="C.INSTALLDIR">
|
<Component Id="C.INSTALLDIR" Guid="{F876F26E-5016-4AC6-93B3-653C0312A6CE}">
|
||||||
<RegistryValue
|
<RegistryValue
|
||||||
Root="HKLM"
|
Root="HKLM"
|
||||||
Key="[P.RegistryKey]"
|
Key="[P.RegistryKey]"
|
||||||
Name="InstallDir"
|
Name="InstallDir"
|
||||||
Type="string"
|
Type="string"
|
||||||
Value="[INSTALLDIR]" />
|
Value="[INSTALLDIR]"
|
||||||
|
KeyPath="yes" />
|
||||||
</Component>
|
</Component>
|
||||||
</DirectoryRef>
|
</DirectoryRef>
|
||||||
<DirectoryRef Id="BINDIR" FileSource="..\build\$(var.Configuration)">
|
<DirectoryRef Id="BINDIR" FileSource="..\build\$(var.Configuration)">
|
||||||
@ -325,6 +326,8 @@
|
|||||||
</Feature>
|
</Feature>
|
||||||
</Feature>
|
</Feature>
|
||||||
|
|
||||||
|
<WixVariable Id="WixUIBannerBmp" Value="wixbanner.bmp" />
|
||||||
|
<WixVariable Id="WixUIDialogBmp" Value="wixdialog.bmp" />
|
||||||
<UI Id="FeatureTree">
|
<UI Id="FeatureTree">
|
||||||
<UIRef Id="WixUI_FeatureTree" />
|
<UIRef Id="WixUI_FeatureTree" />
|
||||||
<!-- skip the license agreement dialog; higher Order takes priority (weird) -->
|
<!-- skip the license agreement dialog; higher Order takes priority (weird) -->
|
||||||
|
BIN
build/VStudio/installer/wixbanner.bmp
Normal file
BIN
build/VStudio/installer/wixbanner.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 112 KiB |
BIN
build/VStudio/installer/wixdialog.bmp
Normal file
BIN
build/VStudio/installer/wixdialog.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 601 KiB |
@ -110,6 +110,7 @@
|
|||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
|
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
@ -128,6 +129,7 @@
|
|||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
|
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
@ -149,6 +151,7 @@
|
|||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
|
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
@ -170,6 +173,7 @@
|
|||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
|
<AdditionalDependencies>%(AdditionalDependencies);rpcrt4.lib</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -7,7 +7,12 @@
|
|||||||
<MyCopyright>2015-2016 Bill Zissimopoulos</MyCopyright>
|
<MyCopyright>2015-2016 Bill Zissimopoulos</MyCopyright>
|
||||||
<!-- build number: concat 2-digit year with 3-digit day of the year (16-bits until 2066) -->
|
<!-- build number: concat 2-digit year with 3-digit day of the year (16-bits until 2066) -->
|
||||||
<MyBuildNumber>$([System.DateTime]::Now.ToString(`yy`))$([System.DateTime]::Now.DayOfYear.ToString(`000`))</MyBuildNumber>
|
<MyBuildNumber>$([System.DateTime]::Now.ToString(`yy`))$([System.DateTime]::Now.DayOfYear.ToString(`000`))</MyBuildNumber>
|
||||||
<MyVersion>0.13.$(MyBuildNumber)</MyVersion>
|
<MyVersion>0.15.$(MyBuildNumber)</MyVersion>
|
||||||
<MyVersionWithCommas>$(MyVersion.Replace('.',',')),0</MyVersionWithCommas>
|
<MyVersionWithCommas>$(MyVersion.Replace('.',',')),0</MyVersionWithCommas>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup>
|
||||||
|
<ClCompile>
|
||||||
|
<PreprocessorDefinitions>NTDDI_VERSION=0x06000000;_WIN32_WINNT=0x0600</PreprocessorDefinitions>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
</Project>
|
</Project>
|
@ -182,7 +182,7 @@ copy /b $(OutDir)fuse-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse-$(Platfor
|
|||||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||||
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
||||||
<AdditionalDependencies>%(AdditionalDependencies);version.lib</AdditionalDependencies>
|
<AdditionalDependencies>%(AdditionalDependencies);credui.lib;version.lib</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
@ -207,7 +207,7 @@ copy /b $(OutDir)fuse-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse-$(Platfor
|
|||||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
||||||
<AdditionalDependencies>%(AdditionalDependencies);version.lib</AdditionalDependencies>
|
<AdditionalDependencies>%(AdditionalDependencies);credui.lib;version.lib</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
@ -235,7 +235,7 @@ copy /b $(OutDir)fuse-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse-$(Platfor
|
|||||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||||
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
||||||
<AdditionalDependencies>%(AdditionalDependencies);version.lib</AdditionalDependencies>
|
<AdditionalDependencies>%(AdditionalDependencies);credui.lib;version.lib</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
@ -263,7 +263,7 @@ copy /b $(OutDir)fuse-$(PlatformTarget).pc + %(FullPath) $(OutDir)fuse-$(Platfor
|
|||||||
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
<MapFileName>$(OutDir)$(TargetFileName).map</MapFileName>
|
||||||
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
<ModuleDefinitionFile>..\..\src\dll\library.def</ModuleDefinitionFile>
|
||||||
<AdditionalDependencies>%(AdditionalDependencies);version.lib</AdditionalDependencies>
|
<AdditionalDependencies>%(AdditionalDependencies);credui.lib;version.lib</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
<TargetVersion>Windows10</TargetVersion>
|
<TargetVersion>Windows10</TargetVersion>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<KernelBufferOverflowLib>$(DDK_LIB_PATH)\BufferOverflowK.lib</KernelBufferOverflowLib>
|
||||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||||
<ConfigurationType>Driver</ConfigurationType>
|
<ConfigurationType>Driver</ConfigurationType>
|
||||||
<DriverType>WDM</DriverType>
|
<DriverType>WDM</DriverType>
|
||||||
@ -41,6 +42,7 @@
|
|||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
<TargetVersion>Windows10</TargetVersion>
|
<TargetVersion>Windows10</TargetVersion>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<KernelBufferOverflowLib>$(DDK_LIB_PATH)\BufferOverflowK.lib</KernelBufferOverflowLib>
|
||||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||||
<ConfigurationType>Driver</ConfigurationType>
|
<ConfigurationType>Driver</ConfigurationType>
|
||||||
<DriverType>WDM</DriverType>
|
<DriverType>WDM</DriverType>
|
||||||
@ -48,6 +50,7 @@
|
|||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
<TargetVersion>Windows10</TargetVersion>
|
<TargetVersion>Windows10</TargetVersion>
|
||||||
<UseDebugLibraries>true</UseDebugLibraries>
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<KernelBufferOverflowLib>$(DDK_LIB_PATH)\BufferOverflowK.lib</KernelBufferOverflowLib>
|
||||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||||
<ConfigurationType>Driver</ConfigurationType>
|
<ConfigurationType>Driver</ConfigurationType>
|
||||||
<DriverType>WDM</DriverType>
|
<DriverType>WDM</DriverType>
|
||||||
@ -55,6 +58,7 @@
|
|||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
<TargetVersion>Windows10</TargetVersion>
|
<TargetVersion>Windows10</TargetVersion>
|
||||||
<UseDebugLibraries>false</UseDebugLibraries>
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<KernelBufferOverflowLib>$(DDK_LIB_PATH)\BufferOverflowK.lib</KernelBufferOverflowLib>
|
||||||
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
<PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset>
|
||||||
<ConfigurationType>Driver</ConfigurationType>
|
<ConfigurationType>Driver</ConfigurationType>
|
||||||
<DriverType>WDM</DriverType>
|
<DriverType>WDM</DriverType>
|
||||||
|
@ -1,6 +1,22 @@
|
|||||||
= Changelog
|
= Changelog
|
||||||
|
|
||||||
|
|
||||||
|
v0.15::
|
||||||
|
|
||||||
|
This is a minor release that brings support for Windows 7 and 32-bit OS'es.
|
||||||
|
|
||||||
|
- Fixes a number of issues for Windows 7. Windows 7 is now officially supported.
|
||||||
|
- Fixes a number of issues with the 32-bit FSD and user mode components. 32-bit versions of Windows are now officially supported.
|
||||||
|
|
||||||
|
|
||||||
|
v0.14::
|
||||||
|
|
||||||
|
This release includes support for file systems protected by credentials.
|
||||||
|
|
||||||
|
- WinFsp now supports file systems that require username/password to be unlocked (e.g. sshfs/secfs). Such file systems must add a DWORD registry value with name "Credentials" and value 1 under their WinFsp.Launcher service entry. The WinFsp network provider will then prompt for credentials using the `CredUIPromptForWindowsCredentials` API. Credentials can optionally be saved with the Windows Credential Manager.
|
||||||
|
- WinFsp-FUSE now uses the S-1-0-65534 <--> 65534 mapping for unmapped SID/UID's. The Anonymous SID mapping from the previous release had security issues.
|
||||||
|
|
||||||
|
|
||||||
v0.13::
|
v0.13::
|
||||||
|
|
||||||
This release includes a Cygwin package, an API change and some other minor changes:
|
This release includes a Cygwin package, an API change and some other minor changes:
|
||||||
|
2
ext/test
2
ext/test
Submodule ext/test updated: da7b88d6cf...a651263c4c
@ -244,6 +244,7 @@ struct fsp_fuse_env
|
|||||||
void (*memfree)(void *);
|
void (*memfree)(void *);
|
||||||
int (*daemonize)(int);
|
int (*daemonize)(int);
|
||||||
int (*set_signal_handlers)(void *);
|
int (*set_signal_handlers)(void *);
|
||||||
|
void (*reserved[4])();
|
||||||
};
|
};
|
||||||
|
|
||||||
FSP_FUSE_API void FSP_FUSE_API_NAME(fsp_fuse_signal_handler)(int sig);
|
FSP_FUSE_API void FSP_FUSE_API_NAME(fsp_fuse_signal_handler)(int sig);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
NAME="fuse"
|
NAME="fuse"
|
||||||
VERSION=2.8
|
VERSION=2.8
|
||||||
RELEASE=2
|
RELEASE=3
|
||||||
CATEGORY="Utils"
|
CATEGORY="Utils"
|
||||||
SUMMARY="WinFsp-FUSE compatibility layer"
|
SUMMARY="WinFsp-FUSE compatibility layer"
|
||||||
DESCRIPTION="WinFsp-FUSE enables FUSE file systems to be run on Cygwin."
|
DESCRIPTION="WinFsp-FUSE enables FUSE file systems to be run on Cygwin."
|
||||||
|
@ -132,7 +132,9 @@ exit:
|
|||||||
|
|
||||||
FSP_API NTSTATUS FspFsctlStop(HANDLE VolumeHandle)
|
FSP_API NTSTATUS FspFsctlStop(HANDLE VolumeHandle)
|
||||||
{
|
{
|
||||||
if (!DeviceIoControl(VolumeHandle, FSP_FSCTL_STOP, 0, 0, 0, 0, 0, 0))
|
DWORD Bytes;
|
||||||
|
|
||||||
|
if (!DeviceIoControl(VolumeHandle, FSP_FSCTL_STOP, 0, 0, 0, 0, &Bytes, 0))
|
||||||
return FspNtStatusFromWin32(GetLastError());
|
return FspNtStatusFromWin32(GetLastError());
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
|
@ -463,9 +463,9 @@ static int fsp_fuse_core_opt_proc(void *opt_data0, const char *arg, int key,
|
|||||||
return 1;
|
return 1;
|
||||||
case 'U':
|
case 'U':
|
||||||
if ('U' == arg[2])
|
if ('U' == arg[2])
|
||||||
arg += sizeof "--UNC" - 1;
|
arg += sizeof "--UNC=" - 1;
|
||||||
else if ('V' == arg[2])
|
else if ('V' == arg[2])
|
||||||
arg += sizeof "--VolumePrefix" - 1;
|
arg += sizeof "--VolumePrefix=" - 1;
|
||||||
if (0 == MultiByteToWideChar(CP_UTF8, 0, arg, -1,
|
if (0 == MultiByteToWideChar(CP_UTF8, 0, arg, -1,
|
||||||
opt_data->VolumeParams.Prefix, sizeof opt_data->VolumeParams.Prefix / sizeof(WCHAR)))
|
opt_data->VolumeParams.Prefix, sizeof opt_data->VolumeParams.Prefix / sizeof(WCHAR)))
|
||||||
return -1;
|
return -1;
|
||||||
@ -507,6 +507,9 @@ FSP_FUSE_API struct fuse *fsp_fuse_new(struct fsp_fuse_env *env,
|
|||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
f->env = env;
|
f->env = env;
|
||||||
|
f->set_umask = opt_data.set_umask; f->umask = opt_data.umask;
|
||||||
|
f->set_uid = opt_data.set_uid; f->uid = opt_data.uid;
|
||||||
|
f->set_gid = opt_data.set_gid; f->gid = opt_data.gid;
|
||||||
memcpy(&f->ops, ops, opsize);
|
memcpy(&f->ops, ops, opsize);
|
||||||
f->data = data;
|
f->data = data;
|
||||||
f->DebugLog = opt_data.debug ? -1 : 0;
|
f->DebugLog = opt_data.debug ? -1 : 0;
|
||||||
|
@ -205,6 +205,13 @@ static NTSTATUS fsp_fuse_intf_GetFileInfoEx(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
if (0 != err)
|
if (0 != err)
|
||||||
return fsp_fuse_ntstatus_from_errno(f->env, err);
|
return fsp_fuse_ntstatus_from_errno(f->env, err);
|
||||||
|
|
||||||
|
if (f->set_umask)
|
||||||
|
stbuf.st_mode = (stbuf.st_mode & 0170000) | (0777 & ~f->umask);
|
||||||
|
if (f->set_uid)
|
||||||
|
stbuf.st_uid = f->uid;
|
||||||
|
if (f->set_gid)
|
||||||
|
stbuf.st_gid = f->gid;
|
||||||
|
|
||||||
*PUid = stbuf.st_uid;
|
*PUid = stbuf.st_uid;
|
||||||
*PGid = stbuf.st_gid;
|
*PGid = stbuf.st_gid;
|
||||||
*PMode = stbuf.st_mode;
|
*PMode = stbuf.st_mode;
|
||||||
|
@ -32,6 +32,9 @@
|
|||||||
struct fuse
|
struct fuse
|
||||||
{
|
{
|
||||||
struct fsp_fuse_env *env;
|
struct fsp_fuse_env *env;
|
||||||
|
int set_umask, umask;
|
||||||
|
int set_uid, uid;
|
||||||
|
int set_gid, gid;
|
||||||
struct fuse_operations ops;
|
struct fuse_operations ops;
|
||||||
void *data;
|
void *data;
|
||||||
UINT32 DebugLog;
|
UINT32 DebugLog;
|
||||||
|
332
src/dll/np.c
332
src/dll/np.c
@ -18,10 +18,29 @@
|
|||||||
#include <dll/library.h>
|
#include <dll/library.h>
|
||||||
#include <launcher/launcher.h>
|
#include <launcher/launcher.h>
|
||||||
#include <npapi.h>
|
#include <npapi.h>
|
||||||
|
#include <wincred.h>
|
||||||
|
|
||||||
#define FSP_NP_NAME LIBRARY_NAME ".Np"
|
#define FSP_NP_NAME LIBRARY_NAME ".Np"
|
||||||
#define FSP_NP_TYPE ' spF' /* pick a value hopefully not in use */
|
#define FSP_NP_TYPE ' spF' /* pick a value hopefully not in use */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define the following macro to use CredUIPromptForWindowsCredentials.
|
||||||
|
* Otherwise CredUIPromptForCredentials will be used.
|
||||||
|
*/
|
||||||
|
#define FSP_NP_CREDUI_PROMPT_NEW
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define the following macro to include support for the credential manager.
|
||||||
|
*/
|
||||||
|
#define FSP_NP_CREDENTIAL_MANAGER
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
FSP_NP_CREDENTIALS_NONE = 0,
|
||||||
|
FSP_NP_CREDENTIALS_PASSWORD = 1,
|
||||||
|
FSP_NP_CREDENTIALS_USERPASS = 3,
|
||||||
|
};
|
||||||
|
|
||||||
DWORD APIENTRY NPGetCaps(DWORD Index)
|
DWORD APIENTRY NPGetCaps(DWORD Index)
|
||||||
{
|
{
|
||||||
switch (Index)
|
switch (Index)
|
||||||
@ -102,6 +121,9 @@ static inline BOOLEAN FspNpParseRemoteName(PWSTR RemoteName,
|
|||||||
PWSTR ClassName, InstanceName, P;
|
PWSTR ClassName, InstanceName, P;
|
||||||
ULONG ClassNameLen, InstanceNameLen;
|
ULONG ClassNameLen, InstanceNameLen;
|
||||||
|
|
||||||
|
if (!FspNpCheckRemoteName(RemoteName))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
ClassName = RemoteName + 2; /* skip \\ */
|
ClassName = RemoteName + 2; /* skip \\ */
|
||||||
for (P = ClassName; *P; P++)
|
for (P = ClassName; *P; P++)
|
||||||
if (L'\\' == *P)
|
if (L'\\' == *P)
|
||||||
@ -129,6 +151,27 @@ static inline BOOLEAN FspNpParseRemoteName(PWSTR RemoteName,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline BOOLEAN FspNpParseUserName(PWSTR RemoteName,
|
||||||
|
PWSTR UserName, ULONG UserNameSize/* in chars */)
|
||||||
|
{
|
||||||
|
PWSTR ClassName, InstanceName, P;
|
||||||
|
ULONG ClassNameLen, InstanceNameLen;
|
||||||
|
|
||||||
|
if (FspNpParseRemoteName(RemoteName,
|
||||||
|
&ClassName, &ClassNameLen, &InstanceName, &InstanceNameLen))
|
||||||
|
{
|
||||||
|
for (P = InstanceName; *P; P++)
|
||||||
|
if ('@' == *P && (ULONG)(P - InstanceName) < UserNameSize)
|
||||||
|
{
|
||||||
|
memcpy(UserName, InstanceName, (P - InstanceName) * sizeof(WCHAR));
|
||||||
|
UserName[P - InstanceName] = L'\0';
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static inline DWORD FspNpCallLauncherPipe(PWSTR PipeBuf, ULONG SendSize, ULONG RecvSize)
|
static inline DWORD FspNpCallLauncherPipe(PWSTR PipeBuf, ULONG SendSize, ULONG RecvSize)
|
||||||
{
|
{
|
||||||
DWORD NpResult;
|
DWORD NpResult;
|
||||||
@ -225,6 +268,144 @@ static WCHAR FspNpGetDriveLetter(PDWORD PLogicalDrives, PWSTR VolumeName)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DWORD FspNpGetCredentialsKind(PWSTR RemoteName, PDWORD PCredentialsKind)
|
||||||
|
{
|
||||||
|
HKEY RegKey = 0;
|
||||||
|
DWORD NpResult, RegSize;
|
||||||
|
DWORD Credentials;
|
||||||
|
PWSTR ClassName, InstanceName;
|
||||||
|
ULONG ClassNameLen, InstanceNameLen;
|
||||||
|
WCHAR ClassNameBuf[sizeof(((FSP_FSCTL_VOLUME_PARAMS *)0)->Prefix) / sizeof(WCHAR)];
|
||||||
|
|
||||||
|
*PCredentialsKind = FSP_NP_CREDENTIALS_NONE;
|
||||||
|
|
||||||
|
if (!FspNpParseRemoteName(RemoteName,
|
||||||
|
&ClassName, &ClassNameLen, &InstanceName, &InstanceNameLen))
|
||||||
|
return WN_BAD_NETNAME;
|
||||||
|
|
||||||
|
if (ClassNameLen > sizeof ClassNameBuf / sizeof ClassNameBuf[0] - 1)
|
||||||
|
ClassNameLen = sizeof ClassNameBuf / sizeof ClassNameBuf[0] - 1;
|
||||||
|
memcpy(ClassNameBuf, ClassName, ClassNameLen * sizeof(WCHAR));
|
||||||
|
ClassNameBuf[ClassNameLen] = '\0';
|
||||||
|
|
||||||
|
NpResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"" LAUNCHER_REGKEY, 0, KEY_READ, &RegKey);
|
||||||
|
if (ERROR_SUCCESS != NpResult)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
RegSize = sizeof Credentials;
|
||||||
|
Credentials = 0; /* default is NO credentials */
|
||||||
|
NpResult = RegGetValueW(RegKey, ClassNameBuf, L"Credentials", RRF_RT_REG_DWORD, 0,
|
||||||
|
&Credentials, &RegSize);
|
||||||
|
if (ERROR_SUCCESS != NpResult && ERROR_FILE_NOT_FOUND != NpResult)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
switch (Credentials)
|
||||||
|
{
|
||||||
|
case FSP_NP_CREDENTIALS_NONE:
|
||||||
|
case FSP_NP_CREDENTIALS_PASSWORD:
|
||||||
|
case FSP_NP_CREDENTIALS_USERPASS:
|
||||||
|
*PCredentialsKind = Credentials;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
NpResult = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (0 != RegKey)
|
||||||
|
RegCloseKey(RegKey);
|
||||||
|
|
||||||
|
return NpResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DWORD FspNpGetCredentials(
|
||||||
|
HWND hwndOwner, PWSTR Caption, DWORD PrevNpResult,
|
||||||
|
DWORD CredentialsKind,
|
||||||
|
PBOOL PSave,
|
||||||
|
PWSTR UserName, ULONG UserNameSize/* in chars */,
|
||||||
|
PWSTR Password, ULONG PasswordSize/* in chars */)
|
||||||
|
{
|
||||||
|
DWORD NpResult;
|
||||||
|
CREDUI_INFOW UiInfo;
|
||||||
|
|
||||||
|
memset(&UiInfo, 0, sizeof UiInfo);
|
||||||
|
UiInfo.cbSize = sizeof UiInfo;
|
||||||
|
UiInfo.hwndParent = hwndOwner;
|
||||||
|
UiInfo.pszCaptionText = Caption;
|
||||||
|
UiInfo.pszMessageText = L"Enter credentials to unlock this file system.";
|
||||||
|
|
||||||
|
#if !defined(FSP_NP_CREDUI_PROMPT_NEW)
|
||||||
|
NpResult = CredUIPromptForCredentialsW(&UiInfo, L"NONE", 0, 0,
|
||||||
|
UserName, UserNameSize,
|
||||||
|
Password, PasswordSize,
|
||||||
|
PSave,
|
||||||
|
CREDUI_FLAGS_GENERIC_CREDENTIALS |
|
||||||
|
CREDUI_FLAGS_DO_NOT_PERSIST |
|
||||||
|
CREDUI_FLAGS_ALWAYS_SHOW_UI |
|
||||||
|
(0 != PrevNpResult ? CREDUI_FLAGS_INCORRECT_PASSWORD : 0) |
|
||||||
|
(0 != PSave ? CREDUI_FLAGS_SHOW_SAVE_CHECK_BOX : 0) |
|
||||||
|
(FSP_NP_CREDENTIALS_PASSWORD == CredentialsKind ? 0/*CREDUI_FLAGS_KEEP_USERNAME*/ : 0));
|
||||||
|
#else
|
||||||
|
WCHAR Domain[CREDUI_MAX_DOMAIN_TARGET_LENGTH + 1];
|
||||||
|
ULONG AuthPackage = 0;
|
||||||
|
PVOID InAuthBuf = 0, OutAuthBuf = 0;
|
||||||
|
ULONG InAuthSize, OutAuthSize, DomainSize;
|
||||||
|
|
||||||
|
InAuthSize = 0;
|
||||||
|
if (!CredPackAuthenticationBufferW(
|
||||||
|
CRED_PACK_GENERIC_CREDENTIALS, UserName, Password, 0, &InAuthSize) &&
|
||||||
|
ERROR_INSUFFICIENT_BUFFER != GetLastError())
|
||||||
|
{
|
||||||
|
NpResult = GetLastError();
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
InAuthBuf = MemAlloc(InAuthSize);
|
||||||
|
if (0 == InAuthBuf)
|
||||||
|
{
|
||||||
|
NpResult = ERROR_NO_SYSTEM_RESOURCES;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CredPackAuthenticationBufferW(
|
||||||
|
CRED_PACK_GENERIC_CREDENTIALS, UserName, Password, InAuthBuf, &InAuthSize))
|
||||||
|
{
|
||||||
|
NpResult = GetLastError();
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
NpResult = CredUIPromptForWindowsCredentialsW(&UiInfo, PrevNpResult,
|
||||||
|
&AuthPackage, InAuthBuf, InAuthSize, &OutAuthBuf, &OutAuthSize, PSave,
|
||||||
|
CREDUIWIN_GENERIC | (0 != PSave ? CREDUIWIN_CHECKBOX : 0));
|
||||||
|
if (ERROR_SUCCESS != NpResult)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
DomainSize = sizeof Domain / sizeof Domain[0];
|
||||||
|
if (!CredUnPackAuthenticationBufferW(0, OutAuthBuf, OutAuthSize,
|
||||||
|
UserName, &UserNameSize, Domain, &DomainSize, Password, &PasswordSize))
|
||||||
|
{
|
||||||
|
NpResult = GetLastError();
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
NpResult = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (0 != OutAuthBuf)
|
||||||
|
{
|
||||||
|
SecureZeroMemory(OutAuthBuf, OutAuthSize);
|
||||||
|
CoTaskMemFree(OutAuthBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != InAuthBuf)
|
||||||
|
{
|
||||||
|
SecureZeroMemory(InAuthBuf, InAuthSize);
|
||||||
|
MemFree(InAuthBuf);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return NpResult;
|
||||||
|
}
|
||||||
|
|
||||||
DWORD APIENTRY NPGetConnection(
|
DWORD APIENTRY NPGetConnection(
|
||||||
LPWSTR lpLocalName, LPWSTR lpRemoteName, LPDWORD lpnBufferLen)
|
LPWSTR lpLocalName, LPWSTR lpRemoteName, LPDWORD lpnBufferLen)
|
||||||
{
|
{
|
||||||
@ -303,12 +484,6 @@ DWORD APIENTRY NPGetConnection(
|
|||||||
}
|
}
|
||||||
|
|
||||||
DWORD APIENTRY NPAddConnection(LPNETRESOURCEW lpNetResource, LPWSTR lpPassword, LPWSTR lpUserName)
|
DWORD APIENTRY NPAddConnection(LPNETRESOURCEW lpNetResource, LPWSTR lpPassword, LPWSTR lpUserName)
|
||||||
{
|
|
||||||
return NPAddConnection3(0, lpNetResource, lpPassword, lpUserName, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD APIENTRY NPAddConnection3(HWND hwndOwner,
|
|
||||||
LPNETRESOURCEW lpNetResource, LPWSTR lpPassword, LPWSTR lpUserName, DWORD dwFlags)
|
|
||||||
{
|
{
|
||||||
DWORD NpResult;
|
DWORD NpResult;
|
||||||
DWORD dwType = lpNetResource->dwType;
|
DWORD dwType = lpNetResource->dwType;
|
||||||
@ -317,14 +492,15 @@ DWORD APIENTRY NPAddConnection3(HWND hwndOwner,
|
|||||||
WCHAR LocalNameBuf[3];
|
WCHAR LocalNameBuf[3];
|
||||||
PWSTR ClassName, InstanceName, RemoteName, P;
|
PWSTR ClassName, InstanceName, RemoteName, P;
|
||||||
ULONG ClassNameLen, InstanceNameLen;
|
ULONG ClassNameLen, InstanceNameLen;
|
||||||
|
DWORD CredentialsKind;
|
||||||
PWSTR PipeBuf = 0;
|
PWSTR PipeBuf = 0;
|
||||||
|
#if defined(FSP_NP_CREDENTIAL_MANAGER)
|
||||||
|
PCREDENTIALW Credential = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (dwType & RESOURCETYPE_PRINT)
|
if (dwType & RESOURCETYPE_PRINT)
|
||||||
return WN_BAD_VALUE;
|
return WN_BAD_VALUE;
|
||||||
|
|
||||||
if (!FspNpCheckRemoteName(lpRemoteName))
|
|
||||||
return WN_BAD_NETNAME;
|
|
||||||
|
|
||||||
if (!FspNpParseRemoteName(lpRemoteName,
|
if (!FspNpParseRemoteName(lpRemoteName,
|
||||||
&ClassName, &ClassNameLen, &InstanceName, &InstanceNameLen))
|
&ClassName, &ClassNameLen, &InstanceName, &InstanceNameLen))
|
||||||
return WN_BAD_NETNAME;
|
return WN_BAD_NETNAME;
|
||||||
@ -344,22 +520,75 @@ DWORD APIENTRY NPAddConnection3(HWND hwndOwner,
|
|||||||
return WN_ALREADY_CONNECTED;
|
return WN_ALREADY_CONNECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FspNpGetCredentialsKind(lpRemoteName, &CredentialsKind);
|
||||||
|
|
||||||
|
#if defined(FSP_NP_CREDENTIAL_MANAGER)
|
||||||
|
/* if we need credentials and none were passed check with the credential manager */
|
||||||
|
if (FSP_NP_CREDENTIALS_NONE != CredentialsKind && 0 == lpPassword &&
|
||||||
|
CredReadW(lpRemoteName, CRED_TYPE_GENERIC, 0, &Credential))
|
||||||
|
{
|
||||||
|
if (sizeof(WCHAR) <= Credential->CredentialBlobSize &&
|
||||||
|
L'\0' == ((PWSTR)(Credential->CredentialBlob))
|
||||||
|
[(Credential->CredentialBlobSize / sizeof(WCHAR)) - 1])
|
||||||
|
{
|
||||||
|
lpUserName = Credential->UserName;
|
||||||
|
lpPassword = (PVOID)Credential->CredentialBlob;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* if we need credentials and we don't have any return ACCESS DENIED */
|
||||||
|
if (FSP_NP_CREDENTIALS_NONE != CredentialsKind)
|
||||||
|
{
|
||||||
|
int Length;
|
||||||
|
if (0 == lpPassword ||
|
||||||
|
(0 == (Length = lstrlenW(lpPassword))) || CREDUI_MAX_PASSWORD_LENGTH < Length)
|
||||||
|
{
|
||||||
|
NpResult = WN_ACCESS_DENIED;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (FSP_NP_CREDENTIALS_USERPASS == CredentialsKind)
|
||||||
|
{
|
||||||
|
int Length;
|
||||||
|
if (0 == lpUserName ||
|
||||||
|
(0 == (Length = lstrlenW(lpUserName))) || CREDUI_MAX_USERNAME_LENGTH < Length)
|
||||||
|
{
|
||||||
|
NpResult = WN_ACCESS_DENIED;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PipeBuf = MemAlloc(LAUNCHER_PIPE_BUFFER_SIZE);
|
PipeBuf = MemAlloc(LAUNCHER_PIPE_BUFFER_SIZE);
|
||||||
if (0 == PipeBuf)
|
if (0 == PipeBuf)
|
||||||
return WN_OUT_OF_MEMORY;
|
{
|
||||||
|
NpResult = WN_OUT_OF_MEMORY;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we do not explicitly check, but assumption is it all fits in LAUNCHER_PIPE_BUFFER_SIZE */
|
||||||
P = PipeBuf;
|
P = PipeBuf;
|
||||||
*P++ = LauncherSvcInstanceStart;
|
*P++ = FSP_NP_CREDENTIALS_NONE != CredentialsKind ?
|
||||||
|
LauncherSvcInstanceStartWithSecret : LauncherSvcInstanceStart;
|
||||||
memcpy(P, ClassName, ClassNameLen * sizeof(WCHAR)); P += ClassNameLen; *P++ = L'\0';
|
memcpy(P, ClassName, ClassNameLen * sizeof(WCHAR)); P += ClassNameLen; *P++ = L'\0';
|
||||||
memcpy(P, InstanceName, InstanceNameLen * sizeof(WCHAR)); P += InstanceNameLen; *P++ = L'\0';
|
memcpy(P, InstanceName, InstanceNameLen * sizeof(WCHAR)); P += InstanceNameLen; *P++ = L'\0';
|
||||||
lstrcpyW(P, RemoteName); P += lstrlenW(RemoteName) + 1;
|
lstrcpyW(P, RemoteName); P += lstrlenW(RemoteName) + 1;
|
||||||
lstrcpyW(P, LocalNameBuf); P += lstrlenW(LocalNameBuf) + 1;
|
lstrcpyW(P, LocalNameBuf); P += lstrlenW(LocalNameBuf) + 1;
|
||||||
|
if (FSP_NP_CREDENTIALS_USERPASS == CredentialsKind)
|
||||||
|
{
|
||||||
|
lstrcpyW(P, lpUserName); P += lstrlenW(lpUserName) + 1;
|
||||||
|
}
|
||||||
|
if (FSP_NP_CREDENTIALS_NONE != CredentialsKind)
|
||||||
|
{
|
||||||
|
lstrcpyW(P, lpPassword); P += lstrlenW(lpPassword) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
NpResult = FspNpCallLauncherPipe(
|
NpResult = FspNpCallLauncherPipe(
|
||||||
PipeBuf, (ULONG)(P - PipeBuf) * sizeof(WCHAR), LAUNCHER_PIPE_BUFFER_SIZE);
|
PipeBuf, (ULONG)(P - PipeBuf) * sizeof(WCHAR), LAUNCHER_PIPE_BUFFER_SIZE);
|
||||||
switch (NpResult)
|
switch (NpResult)
|
||||||
{
|
{
|
||||||
case WN_SUCCESS:
|
case WN_SUCCESS:
|
||||||
|
case WN_ACCESS_DENIED:
|
||||||
break;
|
break;
|
||||||
case ERROR_ALREADY_EXISTS:
|
case ERROR_ALREADY_EXISTS:
|
||||||
/*
|
/*
|
||||||
@ -393,8 +622,89 @@ DWORD APIENTRY NPAddConnection3(HWND hwndOwner,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
MemFree(PipeBuf);
|
MemFree(PipeBuf);
|
||||||
|
|
||||||
|
#if defined(FSP_NP_CREDENTIAL_MANAGER)
|
||||||
|
if (0 != Credential)
|
||||||
|
CredFree(Credential);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return NpResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD APIENTRY NPAddConnection3(HWND hwndOwner,
|
||||||
|
LPNETRESOURCEW lpNetResource, LPWSTR lpPassword, LPWSTR lpUserName, DWORD dwFlags)
|
||||||
|
{
|
||||||
|
DWORD NpResult;
|
||||||
|
PWSTR RemoteName = lpNetResource->lpRemoteName;
|
||||||
|
DWORD CredentialsKind;
|
||||||
|
WCHAR UserName[CREDUI_MAX_USERNAME_LENGTH + 1], Password[CREDUI_MAX_PASSWORD_LENGTH + 1];
|
||||||
|
#if defined(FSP_NP_CREDENTIAL_MANAGER)
|
||||||
|
BOOL Save = TRUE;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//dwFlags |= CONNECT_INTERACTIVE | CONNECT_PROMPT; /* TESTING ONLY! */
|
||||||
|
|
||||||
|
/* CONNECT_PROMPT is only valid if CONNECT_INTERACTIVE is also set */
|
||||||
|
if (CONNECT_PROMPT == (dwFlags & (CONNECT_INTERACTIVE | CONNECT_PROMPT)))
|
||||||
|
return WN_BAD_VALUE;
|
||||||
|
|
||||||
|
/* if not CONNECT_PROMPT go ahead and attempt to NPAddConnection once */
|
||||||
|
if (0 == (dwFlags & CONNECT_PROMPT))
|
||||||
|
{
|
||||||
|
NpResult = NPAddConnection(lpNetResource, lpPassword, lpUserName);
|
||||||
|
if (WN_ACCESS_DENIED != NpResult || 0 == (dwFlags & CONNECT_INTERACTIVE))
|
||||||
|
return NpResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
FspNpGetCredentialsKind(RemoteName, &CredentialsKind);
|
||||||
|
if (FSP_NP_CREDENTIALS_NONE == CredentialsKind)
|
||||||
|
return WN_CANCEL;
|
||||||
|
|
||||||
|
/* if CONNECT_INTERACTIVE keep asking the user for valid credentials or cancel */
|
||||||
|
NpResult = WN_SUCCESS;
|
||||||
|
lstrcpyW(UserName, L"UNSPECIFIED");
|
||||||
|
Password[0] = L'\0';
|
||||||
|
if (FSP_NP_CREDENTIALS_PASSWORD == CredentialsKind)
|
||||||
|
FspNpParseUserName(RemoteName, UserName, sizeof UserName / sizeof UserName[0]);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
NpResult = FspNpGetCredentials(
|
||||||
|
hwndOwner, RemoteName, NpResult,
|
||||||
|
CredentialsKind,
|
||||||
|
#if defined(FSP_NP_CREDENTIAL_MANAGER)
|
||||||
|
&Save,
|
||||||
|
#else
|
||||||
|
0,
|
||||||
|
#endif
|
||||||
|
UserName, sizeof UserName / sizeof UserName[0],
|
||||||
|
Password, sizeof Password / sizeof Password[0]);
|
||||||
|
if (WN_SUCCESS != NpResult)
|
||||||
|
break;
|
||||||
|
|
||||||
|
NpResult = NPAddConnection(lpNetResource, Password, UserName);
|
||||||
|
} while (WN_ACCESS_DENIED == NpResult);
|
||||||
|
|
||||||
|
#if defined(FSP_NP_CREDENTIAL_MANAGER)
|
||||||
|
if (WN_SUCCESS == NpResult && Save)
|
||||||
|
{
|
||||||
|
CREDENTIALW Credential;
|
||||||
|
|
||||||
|
memset(&Credential, 0, sizeof Credential);
|
||||||
|
Credential.Type = CRED_TYPE_GENERIC;
|
||||||
|
Credential.Persist = CRED_PERSIST_LOCAL_MACHINE;
|
||||||
|
Credential.TargetName = RemoteName;
|
||||||
|
Credential.UserName = UserName;
|
||||||
|
Credential.CredentialBlobSize = (lstrlenW(Password) + 1) * sizeof(WCHAR);
|
||||||
|
Credential.CredentialBlob = (PVOID)Password;
|
||||||
|
|
||||||
|
CredWriteW(&Credential, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SecureZeroMemory(Password, sizeof Password);
|
||||||
|
|
||||||
return NpResult;
|
return NpResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,16 +42,16 @@ union
|
|||||||
UINT8 B[sizeof(SID) - sizeof(DWORD) + (1 * sizeof(DWORD))];
|
UINT8 B[sizeof(SID) - sizeof(DWORD) + (1 * sizeof(DWORD))];
|
||||||
} FspUnmappedSidBuf =
|
} FspUnmappedSidBuf =
|
||||||
{
|
{
|
||||||
/* S-1-5-7 (Anonymous) */
|
/* S-1-0-65534 */
|
||||||
.V.Revision = SID_REVISION,
|
.V.Revision = SID_REVISION,
|
||||||
.V.SubAuthorityCount = 1,
|
.V.SubAuthorityCount = 1,
|
||||||
.V.IdentifierAuthority.Value[5] = 5,
|
.V.IdentifierAuthority.Value[5] = 0,
|
||||||
.V.SubAuthority[0] = 7,
|
.V.SubAuthority[0] = 65534,
|
||||||
};
|
};
|
||||||
static PISID FspAccountDomainSid, FspPrimaryDomainSid;
|
static PISID FspAccountDomainSid, FspPrimaryDomainSid;
|
||||||
|
|
||||||
#define FspUnmappedSid (&FspUnmappedSidBuf.V)
|
#define FspUnmappedSid (&FspUnmappedSidBuf.V)
|
||||||
#define FspUnmappedUid (7)
|
#define FspUnmappedUid (65534)
|
||||||
|
|
||||||
static BOOL WINAPI FspPosixInitialize(
|
static BOOL WINAPI FspPosixInitialize(
|
||||||
PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
|
PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
|
||||||
@ -223,7 +223,7 @@ FSP_API NTSTATUS FspPosixMapUidToSid(UINT32 Uid, PSID *PSid)
|
|||||||
* Other well-known SIDs in the NT_AUTHORITY domain (S-1-5-X-RID):
|
* Other well-known SIDs in the NT_AUTHORITY domain (S-1-5-X-RID):
|
||||||
* S-1-5-X-RID <=> uid/gid: 0x1000 * X + RID
|
* S-1-5-X-RID <=> uid/gid: 0x1000 * X + RID
|
||||||
*/
|
*/
|
||||||
else if (0x1000 <= Uid && Uid < 0x100000)
|
else if (FspUnmappedUid != Uid && 0x1000 <= Uid && Uid < 0x100000)
|
||||||
*PSid = FspPosixCreateSid(5, 2, Uid >> 12, Uid & 0xfff);
|
*PSid = FspPosixCreateSid(5, 2, Uid >> 12, Uid & 0xfff);
|
||||||
|
|
||||||
if (0 == *PSid)
|
if (0 == *PSid)
|
||||||
@ -325,7 +325,9 @@ FSP_API NTSTATUS FspPosixMapSidToUid(PSID Sid, PUINT32 PUid)
|
|||||||
*/
|
*/
|
||||||
*PUid = 0x60000 + Rid;
|
*PUid = 0x60000 + Rid;
|
||||||
}
|
}
|
||||||
else
|
else if (
|
||||||
|
FspUnmappedSid->IdentifierAuthority.Value[5] != Authority ||
|
||||||
|
FspUnmappedSid->SubAuthority[0] != Rid)
|
||||||
{
|
{
|
||||||
/* [IDMAP]
|
/* [IDMAP]
|
||||||
* Other well-known SIDs:
|
* Other well-known SIDs:
|
||||||
|
@ -54,9 +54,10 @@ static void usage(void)
|
|||||||
"usage: %s COMMAND ARGS\n"
|
"usage: %s COMMAND ARGS\n"
|
||||||
"\n"
|
"\n"
|
||||||
"commands:\n"
|
"commands:\n"
|
||||||
" start ClassName InstanceName Args...\n"
|
" start ClassName InstanceName Args...\n"
|
||||||
" stop ClassName InstanceName\n"
|
" startWithSecret ClassName InstanceName Args... Secret\n"
|
||||||
" info ClassName InstanceName\n"
|
" stop ClassName InstanceName\n"
|
||||||
|
" info ClassName InstanceName\n"
|
||||||
" list\n",
|
" list\n",
|
||||||
PROGNAME);
|
PROGNAME);
|
||||||
}
|
}
|
||||||
@ -115,7 +116,8 @@ static int call_pipe_and_report(PWSTR PipeBuf, ULONG SendSize, ULONG RecvSize)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int start(PWSTR PipeBuf, ULONG PipeBufSize,
|
int start(PWSTR PipeBuf, ULONG PipeBufSize,
|
||||||
PWSTR ClassName, PWSTR InstanceName, DWORD Argc, PWSTR *Argv)
|
PWSTR ClassName, PWSTR InstanceName, DWORD Argc, PWSTR *Argv,
|
||||||
|
BOOLEAN HasSecret)
|
||||||
{
|
{
|
||||||
PWSTR P;
|
PWSTR P;
|
||||||
DWORD ClassNameSize, InstanceNameSize, ArgvSize;
|
DWORD ClassNameSize, InstanceNameSize, ArgvSize;
|
||||||
@ -130,7 +132,7 @@ int start(PWSTR PipeBuf, ULONG PipeBufSize,
|
|||||||
return ERROR_INVALID_PARAMETER;
|
return ERROR_INVALID_PARAMETER;
|
||||||
|
|
||||||
P = PipeBuf;
|
P = PipeBuf;
|
||||||
*P++ = LauncherSvcInstanceStart;
|
*P++ = HasSecret ? LauncherSvcInstanceStartWithSecret : LauncherSvcInstanceStart;
|
||||||
memcpy(P, ClassName, ClassNameSize * sizeof(WCHAR)); P += ClassNameSize;
|
memcpy(P, ClassName, ClassNameSize * sizeof(WCHAR)); P += ClassNameSize;
|
||||||
memcpy(P, InstanceName, InstanceNameSize * sizeof(WCHAR)); P += InstanceNameSize;
|
memcpy(P, InstanceName, InstanceNameSize * sizeof(WCHAR)); P += InstanceNameSize;
|
||||||
for (DWORD Argi = 0; Argc > Argi; Argi++)
|
for (DWORD Argi = 0; Argc > Argi; Argi++)
|
||||||
@ -230,7 +232,17 @@ int wmain(int argc, wchar_t **argv)
|
|||||||
if (3 > argc || argc > 12)
|
if (3 > argc || argc > 12)
|
||||||
usage();
|
usage();
|
||||||
|
|
||||||
return start(PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE, argv[1], argv[2], argc - 3, argv + 3);
|
return start(PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE, argv[1], argv[2], argc - 3, argv + 3,
|
||||||
|
FALSE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (0 == lstrcmpW(L"startWithSecret", argv[0]))
|
||||||
|
{
|
||||||
|
if (4 > argc || argc > 13)
|
||||||
|
usage();
|
||||||
|
|
||||||
|
return start(PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE, argv[1], argv[2], argc - 3, argv + 3,
|
||||||
|
TRUE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (0 == lstrcmpW(L"stop", argv[0]))
|
if (0 == lstrcmpW(L"stop", argv[0]))
|
||||||
|
@ -19,7 +19,54 @@
|
|||||||
#include <sddl.h>
|
#include <sddl.h>
|
||||||
|
|
||||||
#define PROGNAME "WinFsp.Launcher"
|
#define PROGNAME "WinFsp.Launcher"
|
||||||
#define REGKEY "SYSTEM\\CurrentControlSet\\Services\\" PROGNAME "\\Services"
|
#define REGKEY LAUNCHER_REGKEY
|
||||||
|
|
||||||
|
BOOL CreateOverlappedPipe(
|
||||||
|
PHANDLE PReadPipe, PHANDLE PWritePipe, PSECURITY_ATTRIBUTES SecurityAttributes, DWORD Size,
|
||||||
|
DWORD ReadMode, DWORD WriteMode)
|
||||||
|
{
|
||||||
|
RPC_STATUS RpcStatus;
|
||||||
|
UUID Uuid;
|
||||||
|
WCHAR PipeNameBuf[MAX_PATH];
|
||||||
|
HANDLE ReadPipe, WritePipe;
|
||||||
|
DWORD LastError;
|
||||||
|
|
||||||
|
RpcStatus = UuidCreate(&Uuid);
|
||||||
|
if (S_OK != RpcStatus && RPC_S_UUID_LOCAL_ONLY != RpcStatus)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_INTERNAL_ERROR);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
wsprintfW(PipeNameBuf, L"\\\\.\\pipe\\"
|
||||||
|
"%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
|
||||||
|
Uuid.Data1, Uuid.Data2, Uuid.Data3,
|
||||||
|
Uuid.Data4[0], Uuid.Data4[1], Uuid.Data4[2], Uuid.Data4[3],
|
||||||
|
Uuid.Data4[4], Uuid.Data4[5], Uuid.Data4[6], Uuid.Data4[7]);
|
||||||
|
|
||||||
|
ReadPipe = CreateNamedPipeW(PipeNameBuf,
|
||||||
|
PIPE_ACCESS_INBOUND | FILE_FLAG_FIRST_PIPE_INSTANCE | ReadMode,
|
||||||
|
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS,
|
||||||
|
1, Size, Size, 120 * 1000, SecurityAttributes);
|
||||||
|
if (INVALID_HANDLE_VALUE == ReadPipe)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
WritePipe = CreateFileW(PipeNameBuf,
|
||||||
|
GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||||
|
SecurityAttributes, OPEN_EXISTING, WriteMode, 0);
|
||||||
|
if (INVALID_HANDLE_VALUE == WritePipe)
|
||||||
|
{
|
||||||
|
LastError = GetLastError();
|
||||||
|
CloseHandle(ReadPipe);
|
||||||
|
SetLastError(LastError);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*PReadPipe = ReadPipe;
|
||||||
|
*PWritePipe = WritePipe;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -80,6 +127,7 @@ static VOID CALLBACK KillProcessWait(PVOID Context, BOOLEAN Timeout)
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
LONG RefCount;
|
||||||
PWSTR ClassName;
|
PWSTR ClassName;
|
||||||
PWSTR InstanceName;
|
PWSTR InstanceName;
|
||||||
PWSTR CommandLine;
|
PWSTR CommandLine;
|
||||||
@ -87,6 +135,7 @@ typedef struct
|
|||||||
DWORD ProcessId;
|
DWORD ProcessId;
|
||||||
HANDLE Process;
|
HANDLE Process;
|
||||||
HANDLE ProcessWait;
|
HANDLE ProcessWait;
|
||||||
|
HANDLE StdioHandles[2];
|
||||||
LIST_ENTRY ListEntry;
|
LIST_ENTRY ListEntry;
|
||||||
WCHAR Buffer[];
|
WCHAR Buffer[];
|
||||||
} SVC_INSTANCE;
|
} SVC_INSTANCE;
|
||||||
@ -231,8 +280,132 @@ static NTSTATUS SvcInstanceAccessCheck(HANDLE ClientToken, ULONG DesiredAccess,
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NTSTATUS SvcInstanceCreateProcess(PWSTR Executable, PWSTR CommandLine,
|
||||||
|
HANDLE StdioHandles[2],
|
||||||
|
PPROCESS_INFORMATION ProcessInfo)
|
||||||
|
{
|
||||||
|
STARTUPINFOEXW StartupInfoEx;
|
||||||
|
HANDLE ChildHandles[3] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, 0/* DO NOT CLOSE!*/ };
|
||||||
|
HANDLE ParentHandles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
|
||||||
|
SECURITY_ATTRIBUTES PipeAttributes = { sizeof(SECURITY_ATTRIBUTES), 0, TRUE };
|
||||||
|
PPROC_THREAD_ATTRIBUTE_LIST AttrList = 0;
|
||||||
|
SIZE_T Size;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
memset(&StartupInfoEx, 0, sizeof StartupInfoEx);
|
||||||
|
StartupInfoEx.StartupInfo.cb = sizeof StartupInfoEx.StartupInfo;
|
||||||
|
|
||||||
|
if (0 != StdioHandles)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Create child process and redirect stdin/stdout. Do *not* inherit other handles.
|
||||||
|
*
|
||||||
|
* For explanation see:
|
||||||
|
* https://blogs.msdn.microsoft.com/oldnewthing/20111216-00/?p=8873/
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* create stdin read/write ends; make them inheritable */
|
||||||
|
if (!CreateOverlappedPipe(&ChildHandles[0], &ParentHandles[0], &PipeAttributes, 0,
|
||||||
|
0, 0))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* create stdout read/write ends; make them inheritable */
|
||||||
|
if (!CreateOverlappedPipe(&ParentHandles[1], &ChildHandles[1], &PipeAttributes, 0,
|
||||||
|
FILE_FLAG_OVERLAPPED, 0))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
ChildHandles[2] = GetStdHandle(STD_ERROR_HANDLE);
|
||||||
|
|
||||||
|
Size = 0;
|
||||||
|
if (!InitializeProcThreadAttributeList(0, 1, 0, &Size) &&
|
||||||
|
ERROR_INSUFFICIENT_BUFFER != GetLastError())
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
AttrList = MemAlloc(Size);
|
||||||
|
if (0 == AttrList)
|
||||||
|
{
|
||||||
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!InitializeProcThreadAttributeList(AttrList, 1, 0, &Size))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* only the child ends of stdin/stdout are actually inherited */
|
||||||
|
if (!UpdateProcThreadAttribute(AttrList, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
|
||||||
|
ChildHandles, sizeof ChildHandles, 0, 0))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
StartupInfoEx.StartupInfo.cb = sizeof StartupInfoEx;
|
||||||
|
StartupInfoEx.lpAttributeList = AttrList;
|
||||||
|
StartupInfoEx.StartupInfo.dwFlags = STARTF_USESTDHANDLES;
|
||||||
|
StartupInfoEx.StartupInfo.hStdInput = ChildHandles[0];
|
||||||
|
StartupInfoEx.StartupInfo.hStdOutput = ChildHandles[1];
|
||||||
|
StartupInfoEx.StartupInfo.hStdError = ChildHandles[2];
|
||||||
|
|
||||||
|
if (!CreateProcessW(Executable, CommandLine, 0, 0, TRUE,
|
||||||
|
CREATE_SUSPENDED | CREATE_NEW_PROCESS_GROUP | EXTENDED_STARTUPINFO_PRESENT, 0, 0,
|
||||||
|
&StartupInfoEx.StartupInfo, ProcessInfo))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!CreateProcessW(Executable, CommandLine, 0, 0, FALSE,
|
||||||
|
CREATE_SUSPENDED | CREATE_NEW_PROCESS_GROUP, 0, 0,
|
||||||
|
&StartupInfoEx.StartupInfo, ProcessInfo))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
if (INVALID_HANDLE_VALUE != ParentHandles[0])
|
||||||
|
CloseHandle(ParentHandles[0]);
|
||||||
|
if (INVALID_HANDLE_VALUE != ParentHandles[0])
|
||||||
|
CloseHandle(ParentHandles[1]);
|
||||||
|
}
|
||||||
|
else if (0 != StdioHandles)
|
||||||
|
{
|
||||||
|
StdioHandles[0] = ParentHandles[0];
|
||||||
|
StdioHandles[1] = ParentHandles[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (INVALID_HANDLE_VALUE != ChildHandles[0])
|
||||||
|
CloseHandle(ChildHandles[0]);
|
||||||
|
if (INVALID_HANDLE_VALUE != ChildHandles[1])
|
||||||
|
CloseHandle(ChildHandles[1]);
|
||||||
|
|
||||||
|
MemFree(AttrList);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
|
NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
|
||||||
PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWSTR *Argv0, HANDLE Job,
|
PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWSTR *Argv0, HANDLE Job,
|
||||||
|
BOOLEAN RedirectStdio,
|
||||||
SVC_INSTANCE **PSvcInstance)
|
SVC_INSTANCE **PSvcInstance)
|
||||||
{
|
{
|
||||||
SVC_INSTANCE *SvcInstance = 0;
|
SVC_INSTANCE *SvcInstance = 0;
|
||||||
@ -241,10 +414,9 @@ NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
|
|||||||
DWORD ClassNameSize, InstanceNameSize;
|
DWORD ClassNameSize, InstanceNameSize;
|
||||||
WCHAR Executable[MAX_PATH], CommandLineBuf[512], SecurityBuf[512];
|
WCHAR Executable[MAX_PATH], CommandLineBuf[512], SecurityBuf[512];
|
||||||
PWSTR CommandLine, Security;
|
PWSTR CommandLine, Security;
|
||||||
DWORD JobControl;
|
DWORD JobControl, Credentials;
|
||||||
PSECURITY_DESCRIPTOR SecurityDescriptor = 0;
|
PSECURITY_DESCRIPTOR SecurityDescriptor = 0;
|
||||||
PWSTR Argv[10];
|
PWSTR Argv[10];
|
||||||
STARTUPINFOW StartupInfo;
|
|
||||||
PROCESS_INFORMATION ProcessInfo;
|
PROCESS_INFORMATION ProcessInfo;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
@ -259,7 +431,6 @@ NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
|
|||||||
Argv[0] = 0;
|
Argv[0] = 0;
|
||||||
Argc++;
|
Argc++;
|
||||||
|
|
||||||
memset(&StartupInfo, 0, sizeof StartupInfo);
|
|
||||||
memset(&ProcessInfo, 0, sizeof ProcessInfo);
|
memset(&ProcessInfo, 0, sizeof ProcessInfo);
|
||||||
|
|
||||||
EnterCriticalSection(&SvcInstanceLock);
|
EnterCriticalSection(&SvcInstanceLock);
|
||||||
@ -277,6 +448,22 @@ NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RegSize = sizeof Credentials;
|
||||||
|
Credentials = 0;
|
||||||
|
RegResult = RegGetValueW(RegKey, ClassName, L"Credentials", RRF_RT_REG_DWORD, 0,
|
||||||
|
&Credentials, &RegSize);
|
||||||
|
if (ERROR_SUCCESS != RegResult && ERROR_FILE_NOT_FOUND != RegResult)
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(RegResult);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if ((!RedirectStdio && 0 != Credentials) ||
|
||||||
|
( RedirectStdio && 0 == Credentials))
|
||||||
|
{
|
||||||
|
Result = STATUS_DEVICE_CONFIGURATION_ERROR;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
RegSize = sizeof Executable;
|
RegSize = sizeof Executable;
|
||||||
Executable[0] = L'\0';
|
Executable[0] = L'\0';
|
||||||
RegResult = RegGetValueW(RegKey, ClassName, L"Executable", RRF_RT_REG_SZ, 0,
|
RegResult = RegGetValueW(RegKey, ClassName, L"Executable", RRF_RT_REG_SZ, 0,
|
||||||
@ -336,7 +523,7 @@ NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
FspDebugLogSD(__FUNCTION__ ": SDDL = %s\n", SecurityDescriptor);
|
//FspDebugLogSD(__FUNCTION__ ": SDDL = %s\n", SecurityDescriptor);
|
||||||
|
|
||||||
Result = SvcInstanceAccessCheck(ClientToken, SERVICE_START, SecurityDescriptor);
|
Result = SvcInstanceAccessCheck(ClientToken, SERVICE_START, SecurityDescriptor);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
@ -353,23 +540,23 @@ NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
|
|||||||
}
|
}
|
||||||
|
|
||||||
memset(SvcInstance, 0, sizeof *SvcInstance);
|
memset(SvcInstance, 0, sizeof *SvcInstance);
|
||||||
|
SvcInstance->RefCount = 2;
|
||||||
memcpy(SvcInstance->Buffer, ClassName, ClassNameSize);
|
memcpy(SvcInstance->Buffer, ClassName, ClassNameSize);
|
||||||
memcpy(SvcInstance->Buffer + ClassNameSize / sizeof(WCHAR), InstanceName, InstanceNameSize);
|
memcpy(SvcInstance->Buffer + ClassNameSize / sizeof(WCHAR), InstanceName, InstanceNameSize);
|
||||||
SvcInstance->ClassName = SvcInstance->Buffer;
|
SvcInstance->ClassName = SvcInstance->Buffer;
|
||||||
SvcInstance->InstanceName = SvcInstance->Buffer + ClassNameSize / sizeof(WCHAR);
|
SvcInstance->InstanceName = SvcInstance->Buffer + ClassNameSize / sizeof(WCHAR);
|
||||||
SvcInstance->SecurityDescriptor = SecurityDescriptor;
|
SvcInstance->SecurityDescriptor = SecurityDescriptor;
|
||||||
|
SvcInstance->StdioHandles[0] = INVALID_HANDLE_VALUE;
|
||||||
|
SvcInstance->StdioHandles[1] = INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
Result = SvcInstanceReplaceArguments(CommandLine, Argc, Argv, &SvcInstance->CommandLine);
|
Result = SvcInstanceReplaceArguments(CommandLine, Argc, Argv, &SvcInstance->CommandLine);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
StartupInfo.cb = sizeof StartupInfo;
|
Result = SvcInstanceCreateProcess(Executable, SvcInstance->CommandLine,
|
||||||
if (!CreateProcessW(Executable, SvcInstance->CommandLine, 0, 0, FALSE,
|
RedirectStdio ? SvcInstance->StdioHandles : 0, &ProcessInfo);
|
||||||
CREATE_SUSPENDED | CREATE_NEW_PROCESS_GROUP, 0, 0, &StartupInfo, &ProcessInfo))
|
if (!NT_SUCCESS(Result))
|
||||||
{
|
|
||||||
Result = FspNtStatusFromWin32(GetLastError());
|
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
|
||||||
|
|
||||||
SvcInstance->ProcessId = ProcessInfo.dwProcessId;
|
SvcInstance->ProcessId = ProcessInfo.dwProcessId;
|
||||||
SvcInstance->Process = ProcessInfo.hProcess;
|
SvcInstance->Process = ProcessInfo.hProcess;
|
||||||
@ -413,6 +600,11 @@ exit:
|
|||||||
|
|
||||||
if (0 != SvcInstance)
|
if (0 != SvcInstance)
|
||||||
{
|
{
|
||||||
|
if (INVALID_HANDLE_VALUE != SvcInstance->StdioHandles[0])
|
||||||
|
CloseHandle(SvcInstance->StdioHandles[0]);
|
||||||
|
if (INVALID_HANDLE_VALUE != SvcInstance->StdioHandles[1])
|
||||||
|
CloseHandle(SvcInstance->StdioHandles[1]);
|
||||||
|
|
||||||
if (0 != SvcInstance->ProcessWait)
|
if (0 != SvcInstance->ProcessWait)
|
||||||
UnregisterWaitEx(SvcInstance->ProcessWait, 0);
|
UnregisterWaitEx(SvcInstance->ProcessWait, 0);
|
||||||
|
|
||||||
@ -435,13 +627,21 @@ exit:
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID SvcInstanceDelete(SVC_INSTANCE *SvcInstance)
|
static VOID SvcInstanceRelease(SVC_INSTANCE *SvcInstance)
|
||||||
{
|
{
|
||||||
|
if (0 != InterlockedDecrement(&SvcInstance->RefCount))
|
||||||
|
return;
|
||||||
|
|
||||||
EnterCriticalSection(&SvcInstanceLock);
|
EnterCriticalSection(&SvcInstanceLock);
|
||||||
if (RemoveEntryList(&SvcInstance->ListEntry))
|
if (RemoveEntryList(&SvcInstance->ListEntry))
|
||||||
SetEvent(SvcInstanceEvent);
|
SetEvent(SvcInstanceEvent);
|
||||||
LeaveCriticalSection(&SvcInstanceLock);
|
LeaveCriticalSection(&SvcInstanceLock);
|
||||||
|
|
||||||
|
if (INVALID_HANDLE_VALUE != SvcInstance->StdioHandles[0])
|
||||||
|
CloseHandle(SvcInstance->StdioHandles[0]);
|
||||||
|
if (INVALID_HANDLE_VALUE != SvcInstance->StdioHandles[1])
|
||||||
|
CloseHandle(SvcInstance->StdioHandles[1]);
|
||||||
|
|
||||||
if (0 != SvcInstance->ProcessWait)
|
if (0 != SvcInstance->ProcessWait)
|
||||||
UnregisterWaitEx(SvcInstance->ProcessWait, 0);
|
UnregisterWaitEx(SvcInstance->ProcessWait, 0);
|
||||||
if (0 != SvcInstance->Process)
|
if (0 != SvcInstance->Process)
|
||||||
@ -457,15 +657,102 @@ static VOID CALLBACK SvcInstanceTerminated(PVOID Context, BOOLEAN Timeout)
|
|||||||
{
|
{
|
||||||
SVC_INSTANCE *SvcInstance = Context;
|
SVC_INSTANCE *SvcInstance = Context;
|
||||||
|
|
||||||
SvcInstanceDelete(SvcInstance);
|
SvcInstanceRelease(SvcInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS SvcInstanceStart(HANDLE ClientToken,
|
NTSTATUS SvcInstanceStart(HANDLE ClientToken,
|
||||||
PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWSTR *Argv, HANDLE Job)
|
PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWSTR *Argv, HANDLE Job,
|
||||||
|
BOOLEAN HasSecret)
|
||||||
{
|
{
|
||||||
SVC_INSTANCE *SvcInstance;
|
SVC_INSTANCE *SvcInstance;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
return SvcInstanceCreate(ClientToken, ClassName, InstanceName, Argc, Argv, Job, &SvcInstance);
|
if (HasSecret && (0 == Argc || L'\0' == Argv[Argc - 1][0]))
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
HasSecret = !!HasSecret;
|
||||||
|
|
||||||
|
Result = SvcInstanceCreate(ClientToken, ClassName, InstanceName,
|
||||||
|
Argc - HasSecret, Argv, Job, HasSecret,
|
||||||
|
&SvcInstance);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
return Result;
|
||||||
|
|
||||||
|
if (!HasSecret)
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PWSTR Secret = Argv[Argc - 1];
|
||||||
|
UINT8 ReqBuf[256];
|
||||||
|
UINT8 RspBuf[2];
|
||||||
|
DWORD BytesTransferred;
|
||||||
|
OVERLAPPED Overlapped;
|
||||||
|
DWORD WaitResult;
|
||||||
|
|
||||||
|
if (0 == (BytesTransferred =
|
||||||
|
WideCharToMultiByte(CP_UTF8, 0, Secret, lstrlenW(Secret), ReqBuf, sizeof ReqBuf, 0, 0)))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!WriteFile(SvcInstance->StdioHandles[0], ReqBuf, BytesTransferred, &BytesTransferred, 0))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseHandle(SvcInstance->StdioHandles[0]);
|
||||||
|
SvcInstance->StdioHandles[0] = INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
|
memset(&Overlapped, 0, sizeof Overlapped);
|
||||||
|
if (!ReadFile(SvcInstance->StdioHandles[1], RspBuf, sizeof RspBuf, 0, &Overlapped) &&
|
||||||
|
ERROR_IO_PENDING != GetLastError())
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We need to perform a GetOverlappedResult with a timeout. GetOverlappedResultEx would
|
||||||
|
* be perfect except that it is a Windows 8 and above API. We will therefore replace with
|
||||||
|
* WaitForSingleObject followed by GetOverlappedResult on success.
|
||||||
|
*/
|
||||||
|
WaitResult = WaitForSingleObject(SvcInstance->StdioHandles[1],
|
||||||
|
LAUNCHER_START_WITH_SECRET_TIMEOUT);
|
||||||
|
if (WAIT_OBJECT_0 == WaitResult)
|
||||||
|
Result = GetOverlappedResult(SvcInstance->StdioHandles[1], &Overlapped, &BytesTransferred, TRUE) ?
|
||||||
|
STATUS_SUCCESS : FspNtStatusFromWin32(GetLastError());
|
||||||
|
else if (WAIT_TIMEOUT == WaitResult)
|
||||||
|
Result = STATUS_TIMEOUT;
|
||||||
|
else
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
if (!NT_SUCCESS(Result) || STATUS_TIMEOUT == Result)
|
||||||
|
{
|
||||||
|
CancelIoEx(SvcInstance->StdioHandles[1], &Overlapped);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sizeof RspBuf <= BytesTransferred && 'O' == RspBuf[0] && 'K' == RspBuf[1])
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
else
|
||||||
|
Result = STATUS_ACCESS_DENIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (INVALID_HANDLE_VALUE != SvcInstance->StdioHandles[0])
|
||||||
|
{
|
||||||
|
CloseHandle(SvcInstance->StdioHandles[0]);
|
||||||
|
SvcInstance->StdioHandles[0] = INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
if (INVALID_HANDLE_VALUE != SvcInstance->StdioHandles[1])
|
||||||
|
{
|
||||||
|
CloseHandle(SvcInstance->StdioHandles[1]);
|
||||||
|
SvcInstance->StdioHandles[1] = INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
SvcInstanceRelease(SvcInstance);
|
||||||
|
|
||||||
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS SvcInstanceStop(HANDLE ClientToken,
|
NTSTATUS SvcInstanceStop(HANDLE ClientToken,
|
||||||
@ -625,7 +912,7 @@ static NTSTATUS SvcStart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
|||||||
&SecurityAttributes.lpSecurityDescriptor, 0))
|
&SecurityAttributes.lpSecurityDescriptor, 0))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
FspDebugLogSD(__FUNCTION__ ": SDDL = %s\n", SecurityAttributes.lpSecurityDescriptor);
|
//FspDebugLogSD(__FUNCTION__ ": SDDL = %s\n", SecurityAttributes.lpSecurityDescriptor);
|
||||||
|
|
||||||
SvcInstanceEvent = CreateEventW(0, TRUE, TRUE, 0);
|
SvcInstanceEvent = CreateEventW(0, TRUE, TRUE, 0);
|
||||||
if (0 == SvcInstanceEvent)
|
if (0 == SvcInstanceEvent)
|
||||||
@ -909,12 +1196,16 @@ static VOID SvcPipeTransact(HANDLE ClientToken, PWSTR PipeBuf, PULONG PSize)
|
|||||||
PWSTR P = PipeBuf, PipeBufEnd = PipeBuf + *PSize / sizeof(WCHAR);
|
PWSTR P = PipeBuf, PipeBufEnd = PipeBuf + *PSize / sizeof(WCHAR);
|
||||||
PWSTR ClassName, InstanceName;
|
PWSTR ClassName, InstanceName;
|
||||||
ULONG Argc; PWSTR Argv[9];
|
ULONG Argc; PWSTR Argv[9];
|
||||||
|
BOOLEAN HasSecret = FALSE;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
*PSize = 0;
|
*PSize = 0;
|
||||||
|
|
||||||
switch (*P++)
|
switch (*P++)
|
||||||
{
|
{
|
||||||
|
case LauncherSvcInstanceStartWithSecret:
|
||||||
|
HasSecret = TRUE;
|
||||||
|
/* fall through! */
|
||||||
case LauncherSvcInstanceStart:
|
case LauncherSvcInstanceStart:
|
||||||
ClassName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
ClassName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
||||||
InstanceName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
InstanceName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
||||||
@ -924,7 +1215,8 @@ static VOID SvcPipeTransact(HANDLE ClientToken, PWSTR PipeBuf, PULONG PSize)
|
|||||||
|
|
||||||
Result = STATUS_INVALID_PARAMETER;
|
Result = STATUS_INVALID_PARAMETER;
|
||||||
if (0 != ClassName && 0 != InstanceName)
|
if (0 != ClassName && 0 != InstanceName)
|
||||||
Result = SvcInstanceStart(ClientToken, ClassName, InstanceName, Argc, Argv, SvcJob);
|
Result = SvcInstanceStart(ClientToken, ClassName, InstanceName, Argc, Argv, SvcJob,
|
||||||
|
HasSecret);
|
||||||
|
|
||||||
SvcPipeTransactResult(Result, PipeBuf, PSize);
|
SvcPipeTransactResult(Result, PipeBuf, PSize);
|
||||||
break;
|
break;
|
||||||
|
@ -21,13 +21,17 @@
|
|||||||
#include <winfsp/winfsp.h>
|
#include <winfsp/winfsp.h>
|
||||||
#include <shared/minimal.h>
|
#include <shared/minimal.h>
|
||||||
|
|
||||||
|
#define LAUNCHER_REGKEY "SYSTEM\\CurrentControlSet\\Services\\WinFsp.Launcher\\Services"
|
||||||
|
|
||||||
#define LAUNCHER_STOP_TIMEOUT 5500
|
#define LAUNCHER_STOP_TIMEOUT 5500
|
||||||
#define LAUNCHER_KILL_TIMEOUT 5000
|
#define LAUNCHER_KILL_TIMEOUT 5000
|
||||||
|
|
||||||
#define LAUNCHER_PIPE_NAME "\\\\.\\pipe\\WinFsp.{14E7137D-22B4-437A-B0C1-D21D1BDF3767}"
|
#define LAUNCHER_PIPE_NAME "\\\\.\\pipe\\WinFsp.{14E7137D-22B4-437A-B0C1-D21D1BDF3767}"
|
||||||
#define LAUNCHER_PIPE_BUFFER_SIZE 2048
|
#define LAUNCHER_PIPE_BUFFER_SIZE 4096
|
||||||
#define LAUNCHER_PIPE_DEFAULT_TIMEOUT 3000
|
#define LAUNCHER_PIPE_DEFAULT_TIMEOUT 3000
|
||||||
|
|
||||||
|
#define LAUNCHER_START_WITH_SECRET_TIMEOUT 15000
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The launcher named pipe SDDL gives full access to LocalSystem and Administrators and
|
* The launcher named pipe SDDL gives full access to LocalSystem and Administrators and
|
||||||
* GENERIC_READ and FILE_WRITE_DATA access to Everyone. We are careful not to give the
|
* GENERIC_READ and FILE_WRITE_DATA access to Everyone. We are careful not to give the
|
||||||
@ -53,6 +57,7 @@
|
|||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
LauncherSvcInstanceStart = 'S', /* requires: SERVICE_START */
|
LauncherSvcInstanceStart = 'S', /* requires: SERVICE_START */
|
||||||
|
LauncherSvcInstanceStartWithSecret = 'X', /* requires: SERVICE_START */
|
||||||
LauncherSvcInstanceStop = 'T', /* requires: SERVICE_STOP */
|
LauncherSvcInstanceStop = 'T', /* requires: SERVICE_STOP */
|
||||||
LauncherSvcInstanceInfo = 'I', /* requires: SERVICE_QUERY_STATUS */
|
LauncherSvcInstanceInfo = 'I', /* requires: SERVICE_QUERY_STATUS */
|
||||||
LauncherSvcInstanceList = 'L', /* requires: none*/
|
LauncherSvcInstanceList = 'L', /* requires: none*/
|
||||||
|
@ -655,13 +655,14 @@ enum
|
|||||||
#define FspIopPostWorkRequestBestEffort(D, R)\
|
#define FspIopPostWorkRequestBestEffort(D, R)\
|
||||||
FspIopPostWorkRequestFunnel(D, R, TRUE)
|
FspIopPostWorkRequestFunnel(D, R, TRUE)
|
||||||
#define FspIopCompleteIrp(I, R) FspIopCompleteIrpEx(I, R, TRUE)
|
#define FspIopCompleteIrp(I, R) FspIopCompleteIrpEx(I, R, TRUE)
|
||||||
|
#define REQ_ALIGN_SIZE 16
|
||||||
typedef VOID FSP_IOP_REQUEST_FINI(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[4]);
|
typedef VOID FSP_IOP_REQUEST_FINI(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[4]);
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
FSP_IOP_REQUEST_FINI *RequestFini;
|
FSP_IOP_REQUEST_FINI *RequestFini;
|
||||||
PVOID Context[4];
|
PVOID Context[4];
|
||||||
FSP_FSCTL_TRANSACT_RSP *Response;
|
FSP_FSCTL_TRANSACT_RSP *Response;
|
||||||
__declspec(align(MEMORY_ALLOCATION_ALIGNMENT)) UINT8 RequestBuf[];
|
__declspec(align(REQ_ALIGN_SIZE)) UINT8 RequestBuf[];
|
||||||
} FSP_FSCTL_TRANSACT_REQ_HEADER;
|
} FSP_FSCTL_TRANSACT_REQ_HEADER;
|
||||||
static inline
|
static inline
|
||||||
PVOID *FspIopRequestContextAddress(FSP_FSCTL_TRANSACT_REQ *Request, ULONG I)
|
PVOID *FspIopRequestContextAddress(FSP_FSCTL_TRANSACT_REQ *Request, ULONG I)
|
||||||
@ -1034,4 +1035,26 @@ extern WCHAR FspFileDescDirectoryPatternMatchAll[];
|
|||||||
extern FSP_MV_CcCoherencyFlushAndPurgeCache *FspMvCcCoherencyFlushAndPurgeCache;
|
extern FSP_MV_CcCoherencyFlushAndPurgeCache *FspMvCcCoherencyFlushAndPurgeCache;
|
||||||
extern ULONG FspMvMdlMappingNoWrite;
|
extern ULONG FspMvMdlMappingNoWrite;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fixes
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ObCloseHandle: add missing prototype */
|
||||||
|
#if (NTDDI_VERSION < NTDDI_WIN7)
|
||||||
|
NTKERNELAPI
|
||||||
|
NTSTATUS
|
||||||
|
ObCloseHandle(
|
||||||
|
_In_ HANDLE Handle,
|
||||||
|
_In_ KPROCESSOR_MODE PreviousMode
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* RtlEqualMemory: this is defined as memcmp, which does not exist on Win7 x86! */
|
||||||
|
#undef RtlEqualMemory
|
||||||
|
static inline
|
||||||
|
LOGICAL RtlEqualMemory(const VOID *Source1, const VOID *Source2, SIZE_T Length)
|
||||||
|
{
|
||||||
|
return Length == RtlCompareMemory(Source1, Source2, Length);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
150
src/sys/ioctl.i
150
src/sys/ioctl.i
@ -89,82 +89,82 @@ SYM(FSCTL_DFSR_SET_GHOST_HANDLE_STATE)
|
|||||||
SYM(FSCTL_TXFS_LIST_TRANSACTIONS)
|
SYM(FSCTL_TXFS_LIST_TRANSACTIONS)
|
||||||
SYM(FSCTL_QUERY_PAGEFILE_ENCRYPTION)
|
SYM(FSCTL_QUERY_PAGEFILE_ENCRYPTION)
|
||||||
SYM(FSCTL_RESET_VOLUME_ALLOCATION_HINTS)
|
SYM(FSCTL_RESET_VOLUME_ALLOCATION_HINTS)
|
||||||
SYM(FSCTL_QUERY_DEPENDENT_VOLUME)
|
//SYM(FSCTL_QUERY_DEPENDENT_VOLUME)
|
||||||
SYM(FSCTL_SD_GLOBAL_CHANGE)
|
//SYM(FSCTL_SD_GLOBAL_CHANGE)
|
||||||
SYM(FSCTL_TXFS_READ_BACKUP_INFORMATION2)
|
SYM(FSCTL_TXFS_READ_BACKUP_INFORMATION2)
|
||||||
SYM(FSCTL_LOOKUP_STREAM_FROM_CLUSTER)
|
//SYM(FSCTL_LOOKUP_STREAM_FROM_CLUSTER)
|
||||||
SYM(FSCTL_TXFS_WRITE_BACKUP_INFORMATION2)
|
//SYM(FSCTL_TXFS_WRITE_BACKUP_INFORMATION2)
|
||||||
SYM(FSCTL_FILE_TYPE_NOTIFICATION)
|
//SYM(FSCTL_FILE_TYPE_NOTIFICATION)
|
||||||
SYM(FSCTL_FILE_LEVEL_TRIM)
|
//SYM(FSCTL_FILE_LEVEL_TRIM)
|
||||||
SYM(FSCTL_GET_BOOT_AREA_INFO)
|
//SYM(FSCTL_GET_BOOT_AREA_INFO)
|
||||||
SYM(FSCTL_GET_RETRIEVAL_POINTER_BASE)
|
//SYM(FSCTL_GET_RETRIEVAL_POINTER_BASE)
|
||||||
SYM(FSCTL_SET_PERSISTENT_VOLUME_STATE)
|
//SYM(FSCTL_SET_PERSISTENT_VOLUME_STATE)
|
||||||
SYM(FSCTL_QUERY_PERSISTENT_VOLUME_STATE)
|
//SYM(FSCTL_QUERY_PERSISTENT_VOLUME_STATE)
|
||||||
SYM(FSCTL_REQUEST_OPLOCK)
|
//SYM(FSCTL_REQUEST_OPLOCK)
|
||||||
SYM(FSCTL_CSV_TUNNEL_REQUEST)
|
//SYM(FSCTL_CSV_TUNNEL_REQUEST)
|
||||||
SYM(FSCTL_IS_CSV_FILE)
|
//SYM(FSCTL_IS_CSV_FILE)
|
||||||
SYM(FSCTL_QUERY_FILE_SYSTEM_RECOGNITION)
|
//SYM(FSCTL_QUERY_FILE_SYSTEM_RECOGNITION)
|
||||||
SYM(FSCTL_CSV_GET_VOLUME_PATH_NAME)
|
//SYM(FSCTL_CSV_GET_VOLUME_PATH_NAME)
|
||||||
SYM(FSCTL_CSV_GET_VOLUME_NAME_FOR_VOLUME_MOUNT_POINT)
|
//SYM(FSCTL_CSV_GET_VOLUME_NAME_FOR_VOLUME_MOUNT_POINT)
|
||||||
SYM(FSCTL_CSV_GET_VOLUME_PATH_NAMES_FOR_VOLUME_NAME)
|
//SYM(FSCTL_CSV_GET_VOLUME_PATH_NAMES_FOR_VOLUME_NAME)
|
||||||
SYM(FSCTL_IS_FILE_ON_CSV_VOLUME)
|
//SYM(FSCTL_IS_FILE_ON_CSV_VOLUME)
|
||||||
SYM(FSCTL_CORRUPTION_HANDLING)
|
//SYM(FSCTL_CORRUPTION_HANDLING)
|
||||||
SYM(FSCTL_OFFLOAD_READ)
|
//SYM(FSCTL_OFFLOAD_READ)
|
||||||
SYM(FSCTL_OFFLOAD_WRITE)
|
//SYM(FSCTL_OFFLOAD_WRITE)
|
||||||
SYM(FSCTL_CSV_INTERNAL)
|
//SYM(FSCTL_CSV_INTERNAL)
|
||||||
SYM(FSCTL_SET_PURGE_FAILURE_MODE)
|
//SYM(FSCTL_SET_PURGE_FAILURE_MODE)
|
||||||
SYM(FSCTL_QUERY_FILE_LAYOUT)
|
//SYM(FSCTL_QUERY_FILE_LAYOUT)
|
||||||
SYM(FSCTL_IS_VOLUME_OWNED_BYCSVFS)
|
//SYM(FSCTL_IS_VOLUME_OWNED_BYCSVFS)
|
||||||
SYM(FSCTL_GET_INTEGRITY_INFORMATION)
|
//SYM(FSCTL_GET_INTEGRITY_INFORMATION)
|
||||||
SYM(FSCTL_SET_INTEGRITY_INFORMATION)
|
//SYM(FSCTL_SET_INTEGRITY_INFORMATION)
|
||||||
SYM(FSCTL_QUERY_FILE_REGIONS)
|
//SYM(FSCTL_QUERY_FILE_REGIONS)
|
||||||
SYM(FSCTL_DEDUP_FILE)
|
//SYM(FSCTL_DEDUP_FILE)
|
||||||
SYM(FSCTL_DEDUP_QUERY_FILE_HASHES)
|
//SYM(FSCTL_DEDUP_QUERY_FILE_HASHES)
|
||||||
SYM(FSCTL_DEDUP_QUERY_RANGE_STATE)
|
//SYM(FSCTL_DEDUP_QUERY_RANGE_STATE)
|
||||||
SYM(FSCTL_DEDUP_QUERY_REPARSE_INFO)
|
//SYM(FSCTL_DEDUP_QUERY_REPARSE_INFO)
|
||||||
SYM(FSCTL_RKF_INTERNAL)
|
//SYM(FSCTL_RKF_INTERNAL)
|
||||||
SYM(FSCTL_SCRUB_DATA)
|
//SYM(FSCTL_SCRUB_DATA)
|
||||||
SYM(FSCTL_REPAIR_COPIES)
|
//SYM(FSCTL_REPAIR_COPIES)
|
||||||
SYM(FSCTL_DISABLE_LOCAL_BUFFERING)
|
//SYM(FSCTL_DISABLE_LOCAL_BUFFERING)
|
||||||
SYM(FSCTL_CSV_MGMT_LOCK)
|
//SYM(FSCTL_CSV_MGMT_LOCK)
|
||||||
SYM(FSCTL_CSV_QUERY_DOWN_LEVEL_FILE_SYSTEM_CHARACTERISTICS)
|
//SYM(FSCTL_CSV_QUERY_DOWN_LEVEL_FILE_SYSTEM_CHARACTERISTICS)
|
||||||
SYM(FSCTL_ADVANCE_FILE_ID)
|
//SYM(FSCTL_ADVANCE_FILE_ID)
|
||||||
SYM(FSCTL_CSV_SYNC_TUNNEL_REQUEST)
|
//SYM(FSCTL_CSV_SYNC_TUNNEL_REQUEST)
|
||||||
SYM(FSCTL_CSV_QUERY_VETO_FILE_DIRECT_IO)
|
//SYM(FSCTL_CSV_QUERY_VETO_FILE_DIRECT_IO)
|
||||||
SYM(FSCTL_WRITE_USN_REASON)
|
//SYM(FSCTL_WRITE_USN_REASON)
|
||||||
SYM(FSCTL_CSV_CONTROL)
|
//SYM(FSCTL_CSV_CONTROL)
|
||||||
SYM(FSCTL_GET_REFS_VOLUME_DATA)
|
//SYM(FSCTL_GET_REFS_VOLUME_DATA)
|
||||||
SYM(FSCTL_CSV_H_BREAKING_SYNC_TUNNEL_REQUEST)
|
//SYM(FSCTL_CSV_H_BREAKING_SYNC_TUNNEL_REQUEST)
|
||||||
SYM(FSCTL_QUERY_STORAGE_CLASSES)
|
//SYM(FSCTL_QUERY_STORAGE_CLASSES)
|
||||||
SYM(FSCTL_QUERY_REGION_INFO)
|
//SYM(FSCTL_QUERY_REGION_INFO)
|
||||||
SYM(FSCTL_USN_TRACK_MODIFIED_RANGES)
|
//SYM(FSCTL_USN_TRACK_MODIFIED_RANGES)
|
||||||
SYM(FSCTL_QUERY_SHARED_VIRTUAL_DISK_SUPPORT)
|
//SYM(FSCTL_QUERY_SHARED_VIRTUAL_DISK_SUPPORT)
|
||||||
SYM(FSCTL_SVHDX_SYNC_TUNNEL_REQUEST)
|
//SYM(FSCTL_SVHDX_SYNC_TUNNEL_REQUEST)
|
||||||
SYM(FSCTL_SVHDX_SET_INITIATOR_INFORMATION)
|
//SYM(FSCTL_SVHDX_SET_INITIATOR_INFORMATION)
|
||||||
SYM(FSCTL_SET_EXTERNAL_BACKING)
|
//SYM(FSCTL_SET_EXTERNAL_BACKING)
|
||||||
SYM(FSCTL_GET_EXTERNAL_BACKING)
|
//SYM(FSCTL_GET_EXTERNAL_BACKING)
|
||||||
SYM(FSCTL_DELETE_EXTERNAL_BACKING)
|
//SYM(FSCTL_DELETE_EXTERNAL_BACKING)
|
||||||
SYM(FSCTL_ENUM_EXTERNAL_BACKING)
|
//SYM(FSCTL_ENUM_EXTERNAL_BACKING)
|
||||||
SYM(FSCTL_ENUM_OVERLAY)
|
//SYM(FSCTL_ENUM_OVERLAY)
|
||||||
SYM(FSCTL_ADD_OVERLAY)
|
//SYM(FSCTL_ADD_OVERLAY)
|
||||||
SYM(FSCTL_REMOVE_OVERLAY)
|
//SYM(FSCTL_REMOVE_OVERLAY)
|
||||||
SYM(FSCTL_UPDATE_OVERLAY)
|
//SYM(FSCTL_UPDATE_OVERLAY)
|
||||||
SYM(FSCTL_DUPLICATE_EXTENTS_TO_FILE)
|
//SYM(FSCTL_DUPLICATE_EXTENTS_TO_FILE)
|
||||||
SYM(FSCTL_SPARSE_OVERALLOCATE)
|
//SYM(FSCTL_SPARSE_OVERALLOCATE)
|
||||||
SYM(FSCTL_STORAGE_QOS_CONTROL)
|
//SYM(FSCTL_STORAGE_QOS_CONTROL)
|
||||||
SYM(FSCTL_INITIATE_FILE_METADATA_OPTIMIZATION)
|
//SYM(FSCTL_INITIATE_FILE_METADATA_OPTIMIZATION)
|
||||||
SYM(FSCTL_QUERY_FILE_METADATA_OPTIMIZATION)
|
//SYM(FSCTL_QUERY_FILE_METADATA_OPTIMIZATION)
|
||||||
SYM(FSCTL_SVHDX_ASYNC_TUNNEL_REQUEST)
|
//SYM(FSCTL_SVHDX_ASYNC_TUNNEL_REQUEST)
|
||||||
SYM(FSCTL_GET_WOF_VERSION)
|
//SYM(FSCTL_GET_WOF_VERSION)
|
||||||
SYM(FSCTL_HCS_SYNC_TUNNEL_REQUEST)
|
//SYM(FSCTL_HCS_SYNC_TUNNEL_REQUEST)
|
||||||
SYM(FSCTL_HCS_ASYNC_TUNNEL_REQUEST)
|
//SYM(FSCTL_HCS_ASYNC_TUNNEL_REQUEST)
|
||||||
SYM(FSCTL_QUERY_EXTENT_READ_CACHE_INFO)
|
//SYM(FSCTL_QUERY_EXTENT_READ_CACHE_INFO)
|
||||||
SYM(FSCTL_QUERY_REFS_VOLUME_COUNTER_INFO)
|
//SYM(FSCTL_QUERY_REFS_VOLUME_COUNTER_INFO)
|
||||||
SYM(FSCTL_CLEAN_VOLUME_METADATA)
|
//SYM(FSCTL_CLEAN_VOLUME_METADATA)
|
||||||
SYM(FSCTL_SET_INTEGRITY_INFORMATION_EX)
|
//SYM(FSCTL_SET_INTEGRITY_INFORMATION_EX)
|
||||||
SYM(FSCTL_SUSPEND_OVERLAY)
|
//SYM(FSCTL_SUSPEND_OVERLAY)
|
||||||
SYM(FSCTL_VIRTUAL_STORAGE_QUERY_PROPERTY)
|
//SYM(FSCTL_VIRTUAL_STORAGE_QUERY_PROPERTY)
|
||||||
SYM(FSCTL_FILESYSTEM_GET_STATISTICS_EX)
|
//SYM(FSCTL_FILESYSTEM_GET_STATISTICS_EX)
|
||||||
SYM(FSCTL_LMR_GET_LINK_TRACKING_INFORMATION)
|
SYM(FSCTL_LMR_GET_LINK_TRACKING_INFORMATION)
|
||||||
SYM(FSCTL_LMR_SET_LINK_TRACKING_INFORMATION)
|
SYM(FSCTL_LMR_SET_LINK_TRACKING_INFORMATION)
|
||||||
SYM(IOCTL_LMR_ARE_FILE_OBJECTS_ON_SAME_SERVER)
|
SYM(IOCTL_LMR_ARE_FILE_OBJECTS_ON_SAME_SERVER)
|
||||||
|
@ -48,10 +48,12 @@ NTSTATUS FspIopDispatchComplete(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Requests (and RequestHeaders) must be 16-byte aligned, because we use the low 4 bits for flags */
|
/* Requests (and RequestHeaders) must be 16-byte aligned, because we use the low 4 bits for flags */
|
||||||
#if 16 != MEMORY_ALLOCATION_ALIGNMENT
|
#if REQ_ALIGN_SIZE <= MEMORY_ALLOCATION_ALIGNMENT
|
||||||
#define REQ_HEADER_ALIGNMASK 15
|
#define REQ_HEADER_ALIGN_MASK 0
|
||||||
|
#define REQ_HEADER_ALIGN_OVERHEAD 0
|
||||||
#else
|
#else
|
||||||
#define REQ_HEADER_ALIGNMASK 0
|
#define REQ_HEADER_ALIGN_MASK (REQ_ALIGN_SIZE - 1)
|
||||||
|
#define REQ_HEADER_ALIGN_OVERHEAD (sizeof(PVOID) + REQ_HEADER_ALIGN_MASK)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NTSTATUS FspIopCreateRequestFunnel(
|
NTSTATUS FspIopCreateRequestFunnel(
|
||||||
@ -74,20 +76,23 @@ NTSTATUS FspIopCreateRequestFunnel(
|
|||||||
if (FlagOn(Flags, FspIopRequestMustSucceed))
|
if (FlagOn(Flags, FspIopRequestMustSucceed))
|
||||||
RequestHeader = FspAllocatePoolMustSucceed(
|
RequestHeader = FspAllocatePoolMustSucceed(
|
||||||
FlagOn(Flags, FspIopRequestNonPaged) ? NonPagedPool : PagedPool,
|
FlagOn(Flags, FspIopRequestNonPaged) ? NonPagedPool : PagedPool,
|
||||||
sizeof *RequestHeader + sizeof *Request + ExtraSize + REQ_HEADER_ALIGNMASK,
|
sizeof *RequestHeader + sizeof *Request + ExtraSize + REQ_HEADER_ALIGN_OVERHEAD,
|
||||||
FSP_ALLOC_INTERNAL_TAG);
|
FSP_ALLOC_INTERNAL_TAG);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RequestHeader = ExAllocatePoolWithTag(
|
RequestHeader = ExAllocatePoolWithTag(
|
||||||
FlagOn(Flags, FspIopRequestNonPaged) ? NonPagedPool : PagedPool,
|
FlagOn(Flags, FspIopRequestNonPaged) ? NonPagedPool : PagedPool,
|
||||||
sizeof *RequestHeader + sizeof *Request + ExtraSize + REQ_HEADER_ALIGNMASK,
|
sizeof *RequestHeader + sizeof *Request + ExtraSize + REQ_HEADER_ALIGN_OVERHEAD,
|
||||||
FSP_ALLOC_INTERNAL_TAG);
|
FSP_ALLOC_INTERNAL_TAG);
|
||||||
if (0 == RequestHeader)
|
if (0 == RequestHeader)
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 != REQ_HEADER_ALIGNMASK
|
#if 0 != REQ_HEADER_ALIGN_MASK
|
||||||
RequestHeader = (PVOID)(((UINT_PTR)RequestHeader + REQ_HEADER_ALIGNMASK) & REQ_HEADER_ALIGNMASK);
|
PVOID Allocation = RequestHeader;
|
||||||
|
RequestHeader = (PVOID)(((UINT_PTR)RequestHeader + REQ_HEADER_ALIGN_OVERHEAD) &
|
||||||
|
~REQ_HEADER_ALIGN_MASK);
|
||||||
|
((PVOID *)RequestHeader)[-1] = Allocation;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
RtlZeroMemory(RequestHeader, sizeof *RequestHeader + sizeof *Request + ExtraSize);
|
RtlZeroMemory(RequestHeader, sizeof *RequestHeader + sizeof *Request + ExtraSize);
|
||||||
@ -127,6 +132,10 @@ VOID FspIopDeleteRequest(FSP_FSCTL_TRANSACT_REQ *Request)
|
|||||||
if (0 != RequestHeader->Response)
|
if (0 != RequestHeader->Response)
|
||||||
FspFree(RequestHeader->Response);
|
FspFree(RequestHeader->Response);
|
||||||
|
|
||||||
|
#if 0 != REQ_HEADER_ALIGN_MASK
|
||||||
|
RequestHeader = ((PVOID *)RequestHeader)[-1];
|
||||||
|
#endif
|
||||||
|
|
||||||
FspFree(RequestHeader);
|
FspFree(RequestHeader);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include <sddl.h>
|
#include <sddl.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <VersionHelpers.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Define the DEBUG_BUFFER_CHECK macro on Windows 8 or above. This includes
|
* Define the DEBUG_BUFFER_CHECK macro on Windows 8 or above. This includes
|
||||||
@ -539,7 +540,8 @@ static NTSTATUS Write(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
__try
|
__try
|
||||||
{
|
{
|
||||||
*P = *P | 0;
|
*P = *P | 0;
|
||||||
assert(0);
|
assert(!IsWindows8OrGreater());
|
||||||
|
/* only on Windows 8 we can make the buffer read-only! */
|
||||||
}
|
}
|
||||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||||
{
|
{
|
||||||
|
32
tst/secret/secret.c
Normal file
32
tst/secret/secret.c
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Compile:
|
||||||
|
* - cl secret.c
|
||||||
|
*
|
||||||
|
* Register:
|
||||||
|
* - secret.reg (fix Executable path first)
|
||||||
|
*
|
||||||
|
* Run:
|
||||||
|
* - launchctl-x64 startWithSecret secret 1 nopass
|
||||||
|
* - launchctl-x64 startWithSecret secret 1 foobar
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
char pass[256];
|
||||||
|
|
||||||
|
gets(pass);
|
||||||
|
if (0 == strcmp("foobar", pass))
|
||||||
|
{
|
||||||
|
puts("OK");
|
||||||
|
fprintf(stderr, "OK secret=\"%s\"\n", pass);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
puts("KO");
|
||||||
|
fprintf(stderr, "KO secret=\"%s\"\n", pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
BIN
tst/secret/secret.reg
Normal file
BIN
tst/secret/secret.reg
Normal file
Binary file not shown.
@ -10,6 +10,7 @@ void posix_map_sid_test(void)
|
|||||||
UINT32 Uid;
|
UINT32 Uid;
|
||||||
} map[] =
|
} map[] =
|
||||||
{
|
{
|
||||||
|
{ L"S-1-0-65534", 65534 },
|
||||||
{ L"S-1-0-0", 0x10000 },
|
{ L"S-1-0-0", 0x10000 },
|
||||||
{ L"S-1-1-0", 0x10100 },
|
{ L"S-1-1-0", 0x10100 },
|
||||||
{ L"S-1-2-0", 0x10200 },
|
{ L"S-1-2-0", 0x10200 },
|
||||||
|
Reference in New Issue
Block a user