mirror of
https://github.com/winfsp/winfsp.git
synced 2025-07-03 01:12:58 -05:00
Compare commits
110 Commits
Author | SHA1 | Date | |
---|---|---|---|
f7adbaba92 | |||
fea92c4ae0 | |||
1e2f0930a2 | |||
ab11ff2b39 | |||
1e1b9cdda3 | |||
00ee25f904 | |||
cf29bd5a58 | |||
597dd43f23 | |||
1c3fc530f6 | |||
67c6cd453a | |||
7eec1649a4 | |||
9971472be7 | |||
c1985bef6c | |||
e4e2465bcb | |||
22d1f86ac1 | |||
1a7d3b8f9e | |||
768a393342 | |||
08a02d7b35 | |||
3035ba2847 | |||
147c90be9f | |||
0822458238 | |||
c322a4b14a | |||
0c6300b97c | |||
be952729c9 | |||
1802ac8878 | |||
5491187e1d | |||
ec2494433b | |||
0756649572 | |||
8ccd44a1f7 | |||
2c51251cb7 | |||
35d2b3f626 | |||
26a9bb714b | |||
13f2517a31 | |||
da85f2aa08 | |||
22c324de69 | |||
c42e2a5958 | |||
1c587dbcb7 | |||
bc2e87763e | |||
724d177d0b | |||
6971f4d6ae | |||
ceef2bf55e | |||
a81a766bbe | |||
da839e39b8 | |||
ec21e830f1 | |||
9ae28a5529 | |||
1a14971911 | |||
ab48beb4ba | |||
528cbd3295 | |||
c32d05c3b6 | |||
e82b06ae49 | |||
457e151fa5 | |||
dc4109fc22 | |||
2a69ad6710 | |||
d3ff12bf60 | |||
713ee8a917 | |||
f4744258a7 | |||
7e57edf72e | |||
89e4e8a96c | |||
0c18b82cc2 | |||
57f9db6cc0 | |||
6da81be792 | |||
b77a749f93 | |||
bb946d5a3a | |||
27a16e5c54 | |||
789222af68 | |||
587fee93e9 | |||
077bbb0d65 | |||
3d2a2dd90d | |||
0b1bba36f8 | |||
8dd5a03b51 | |||
ac2e9f9882 | |||
1017e7fda7 | |||
125b612c9f | |||
9addfa5899 | |||
12db7cf9dc | |||
e53e915a72 | |||
d7a6f33d26 | |||
de973fa5ab | |||
4a4fba4670 | |||
e45ac30b65 | |||
cbb7d943bd | |||
df5d2d6e87 | |||
b1b31b9017 | |||
ff0b8bc3fe | |||
a99e8ac9d2 | |||
3f7ebe7996 | |||
030ef84c2e | |||
ba5c670034 | |||
690e7662d6 | |||
500db7b1cd | |||
e43c5091e4 | |||
9ffc3f03ed | |||
14366f76c5 | |||
b089b98afc | |||
26aadb0b72 | |||
9c11ca5bda | |||
8ae2bb3bfc | |||
b0a2e4ff40 | |||
0c75b58810 | |||
b12e0aad47 | |||
1264cae110 | |||
5a7c7bb4f2 | |||
acfd02c31d | |||
efa200aac4 | |||
3a1cba2442 | |||
59698f5517 | |||
1176114528 | |||
e0dde7349e | |||
1bdfc8a579 | |||
2659effafb |
83
build/VStudio/installer/CustomActions/CustomActions.cpp
Normal file
83
build/VStudio/installer/CustomActions/CustomActions.cpp
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/**
|
||||||
|
* @file CustomActions.cpp
|
||||||
|
*
|
||||||
|
* @copyright 2015-2016 Bill Zissimopoulos
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* This file is part of WinFsp.
|
||||||
|
*
|
||||||
|
* You can redistribute it and/or modify it under the terms of the
|
||||||
|
* GNU Affero General Public License version 3 as published by the
|
||||||
|
* Free Software Foundation.
|
||||||
|
*
|
||||||
|
* Licensees holding a valid commercial license may use this file in
|
||||||
|
* accordance with the commercial license agreement provided with the
|
||||||
|
* software.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
#include <msiquery.h>
|
||||||
|
#include <wcautil.h>
|
||||||
|
#include <strutil.h>
|
||||||
|
|
||||||
|
UINT __stdcall ServiceRunning(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 ServiceName = 0;
|
||||||
|
SC_HANDLE ScmHandle = 0;
|
||||||
|
SC_HANDLE SvcHandle = 0;
|
||||||
|
SERVICE_STATUS ServiceStatus;
|
||||||
|
int Result = 0;
|
||||||
|
|
||||||
|
hr = WcaInitialize(MsiHandle, __FUNCTION__);
|
||||||
|
ExitOnFailure(hr, "Failed to initialize");
|
||||||
|
|
||||||
|
WcaGetProperty(L"" __FUNCTION__, &ServiceName);
|
||||||
|
ExitOnFailure(hr, "Failed to get ServiceName");
|
||||||
|
|
||||||
|
WcaLog(LOGMSG_STANDARD, "Initialized: \"%S\"", ServiceName);
|
||||||
|
|
||||||
|
ScmHandle = OpenSCManagerW(0, 0, 0);
|
||||||
|
ExitOnNullWithLastError(ScmHandle, hr, "Failed to open SCM");
|
||||||
|
|
||||||
|
SvcHandle = OpenServiceW(ScmHandle, ServiceName, SERVICE_QUERY_STATUS);
|
||||||
|
if (0 != SvcHandle && QueryServiceStatus(SvcHandle, &ServiceStatus))
|
||||||
|
Result = SERVICE_STOPPED != ServiceStatus.dwCurrentState;
|
||||||
|
|
||||||
|
WcaSetIntProperty(L"" __FUNCTION__, Result);
|
||||||
|
|
||||||
|
LExit:
|
||||||
|
if (0 != SvcHandle)
|
||||||
|
CloseServiceHandle(SvcHandle);
|
||||||
|
if (0 != ScmHandle)
|
||||||
|
CloseServiceHandle(ScmHandle);
|
||||||
|
|
||||||
|
ReleaseStr(ServiceName);
|
||||||
|
|
||||||
|
err = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
|
||||||
|
return WcaFinalize(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
BOOL WINAPI DllMain(HINSTANCE Instance, DWORD Reason, PVOID Reserved)
|
||||||
|
{
|
||||||
|
switch(Reason)
|
||||||
|
{
|
||||||
|
case DLL_PROCESS_ATTACH:
|
||||||
|
WcaGlobalInitialize(Instance);
|
||||||
|
break;
|
||||||
|
case DLL_PROCESS_DETACH:
|
||||||
|
WcaGlobalFinalize();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
2
build/VStudio/installer/CustomActions/CustomActions.def
Normal file
2
build/VStudio/installer/CustomActions/CustomActions.def
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
EXPORTS
|
||||||
|
ServiceRunning
|
112
build/VStudio/installer/CustomActions/CustomActions.vcxproj
Normal file
112
build/VStudio/installer/CustomActions/CustomActions.vcxproj
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>{95C223E6-B5F1-4FD0-9376-41CDBC824445}</ProjectGuid>
|
||||||
|
<RootNamespace>CustomActions</RootNamespace>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<PlatformToolset>v140</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<PlatformToolset>v140</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<_ProjectFileVersion>14.0.25123.0</_ProjectFileVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<OutDir>$(SolutionDir)build\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>$(SolutionDir)build\$(ProjectName).build\$(Configuration)\$(PlatformTarget)\</IntDir>
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<OutDir>$(SolutionDir)build\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>$(SolutionDir)build\$(ProjectName).build\$(Configuration)\$(PlatformTarget)\</IntDir>
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<AdditionalIncludeDirectories>$(WIX)sdk\VS2015\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;CUSTOMACTIONTEST_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<MinimalRebuild>true</MinimalRebuild>
|
||||||
|
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||||
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<AdditionalDependencies>msi.lib;dutil.lib;wcautil.lib;Version.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<AdditionalLibraryDirectories>$(WIX)sdk\VS2015\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
|
<ModuleDefinitionFile>CustomActions.def</ModuleDefinitionFile>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<TargetMachine>MachineX86</TargetMachine>
|
||||||
|
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||||
|
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<AdditionalIncludeDirectories>$(WIX)sdk\VS2015\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;CUSTOMACTIONTEST_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||||
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<AdditionalDependencies>msi.lib;dutil.lib;wcautil.lib;Version.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<AdditionalLibraryDirectories>$(WIX)sdk\VS2015\lib\x86;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
|
<ModuleDefinitionFile>CustomActions.def</ModuleDefinitionFile>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<SubSystem>Windows</SubSystem>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<TargetMachine>MachineX86</TargetMachine>
|
||||||
|
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="CustomActions.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="CustomActions.def" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Source">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="CustomActions.cpp">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="CustomActions.def">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
330
build/VStudio/installer/Product.wxs
Normal file
330
build/VStudio/installer/Product.wxs
Normal file
@ -0,0 +1,330 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
|
||||||
|
<Product
|
||||||
|
Id="*"
|
||||||
|
Name="$(var.MyProductName)"
|
||||||
|
Manufacturer="$(var.MyCompanyName)"
|
||||||
|
Version="$(var.MyVersion)"
|
||||||
|
Language="1033"
|
||||||
|
UpgradeCode="82F812D9-4083-4EF1-8BC8-0F1EDA05B46B">
|
||||||
|
|
||||||
|
<Package
|
||||||
|
Description="$(var.MyProductName) - $(var.MyDescription)"
|
||||||
|
InstallerVersion="200"
|
||||||
|
Compressed="yes"
|
||||||
|
InstallScope="perMachine" />
|
||||||
|
<MajorUpgrade
|
||||||
|
Disallow="yes"
|
||||||
|
AllowDowngrades="no"
|
||||||
|
AllowSameVersionUpgrades="no"
|
||||||
|
DisallowUpgradeErrorMessage="An older version of [ProductName] is already installed. You must uninstall it before you can install this version."
|
||||||
|
DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
|
||||||
|
<Media Id="1" Cabinet="WinFsp.cab" EmbedCab="yes" />
|
||||||
|
|
||||||
|
<Property Id="P.LauncherName">$(var.MyProductName).Launcher</Property>
|
||||||
|
<Property Id="P.LauncherRegistryKey">SYSTEM\\CurrentControlSet\\Services\\$(var.MyProductName).Launcher\\Services</Property>
|
||||||
|
<Property Id="P.RegistryKey">Software\$(var.MyProductName)</Property>
|
||||||
|
<Property Id="INSTALLDIR">
|
||||||
|
<RegistrySearch
|
||||||
|
Id="R.INSTALLDIR"
|
||||||
|
Root="HKLM"
|
||||||
|
Key="[P.RegistryKey]"
|
||||||
|
Name="InstallDir"
|
||||||
|
Type="raw" />
|
||||||
|
</Property>
|
||||||
|
|
||||||
|
<Directory Id="TARGETDIR" Name="SourceDir">
|
||||||
|
<Directory Id="ProgramFilesFolder">
|
||||||
|
<Directory Id="INSTALLDIR" Name="WinFsp">
|
||||||
|
<Directory Id="BINDIR" Name="bin" />
|
||||||
|
<Directory Id="INCDIR" Name="inc" />
|
||||||
|
<Directory Id="LIBDIR" Name="lib" />
|
||||||
|
<Directory Id="SMPDIR" Name="samples" />
|
||||||
|
</Directory>
|
||||||
|
</Directory>
|
||||||
|
</Directory>
|
||||||
|
|
||||||
|
<DirectoryRef Id="INSTALLDIR">
|
||||||
|
<Component Id="C.INSTALLDIR">
|
||||||
|
<RegistryValue
|
||||||
|
Root="HKLM"
|
||||||
|
Key="[P.RegistryKey]"
|
||||||
|
Name="InstallDir"
|
||||||
|
Type="string"
|
||||||
|
Value="[INSTALLDIR]" />
|
||||||
|
</Component>
|
||||||
|
</DirectoryRef>
|
||||||
|
<DirectoryRef Id="BINDIR" FileSource="..\build\$(var.Configuration)">
|
||||||
|
<Component Id="C.winfsp_x64.sys">
|
||||||
|
<File Name="winfsp-x64.sys" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.winfsp_x86.sys">
|
||||||
|
<File Name="winfsp-x86.sys" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
|
||||||
|
<!-- On Win64 register winfsp-x64.dll -->
|
||||||
|
<Component Id="C.winfsp_x64.dll.selfreg" Guid="F0A67746-1A9C-4976-8EC0-882E9407FA6D">
|
||||||
|
<File Id="FILE.winfsp_x64.dll.selfreg" Name="winfsp-x64.dll" KeyPath="yes" SelfRegCost="1" />
|
||||||
|
<Condition>VersionNT64</Condition>
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.winfsp_x86.dll" Guid="950492FB-12F7-4E27-9124-8325A2BC9927">
|
||||||
|
<File Name="winfsp-x86.dll" KeyPath="yes" />
|
||||||
|
<Condition>VersionNT64</Condition>
|
||||||
|
</Component>
|
||||||
|
|
||||||
|
<!-- On Win32 register winfsp-x86.dll -->
|
||||||
|
<Component Id="C.winfsp_x64.dll" Guid="4D6E7A8E-0CA6-49BE-B312-1EDADE725756">
|
||||||
|
<File Name="winfsp-x64.dll" KeyPath="yes" />
|
||||||
|
<Condition>NOT VersionNT64</Condition>
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.winfsp_x86.dll.selfreg" Guid="F0DEF7A6-AF55-419F-A58A-DF4018C6FA73">
|
||||||
|
<File Id="FILE.winfsp_x86.dll.selfreg" Name="winfsp-x86.dll" KeyPath="yes" SelfRegCost="1" />
|
||||||
|
<Condition>NOT VersionNT64</Condition>
|
||||||
|
</Component>
|
||||||
|
|
||||||
|
<!-- On Win64 ServiceInstall launcher-x64.exe -->
|
||||||
|
<Component Id="C.launcher_x64.exe.svcinst">
|
||||||
|
<File Id="launcher_x64.exe.svcinst" Name="launcher-x64.exe" KeyPath="yes" />
|
||||||
|
<ServiceInstall
|
||||||
|
Id="launcher_x64.exe.svcinst"
|
||||||
|
Name="[P.LauncherName]"
|
||||||
|
Description="$(var.MyDescription)"
|
||||||
|
Type="ownProcess"
|
||||||
|
Start="auto"
|
||||||
|
ErrorControl="ignore" />
|
||||||
|
<ServiceControl
|
||||||
|
Id="launcher_x64.exe.svcinst"
|
||||||
|
Name="[P.LauncherName]"
|
||||||
|
Start="install"
|
||||||
|
Stop="both"
|
||||||
|
Remove="uninstall" />
|
||||||
|
<Condition>VersionNT64</Condition>
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.launcher_x86.exe">
|
||||||
|
<File Name="launcher-x86.exe" KeyPath="yes" />
|
||||||
|
<Condition>VersionNT64</Condition>
|
||||||
|
</Component>
|
||||||
|
|
||||||
|
<!-- On Win32 ServiceInstall launcher-x86.exe -->
|
||||||
|
<Component Id="C.launcher_x64.exe" Guid="88CDBE92-8B67-485A-838F-FA4AD37F306F">
|
||||||
|
<File Name="launcher-x64.exe" KeyPath="yes" />
|
||||||
|
<Condition>NOT VersionNT64</Condition>
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.launcher_x86.exe.svcinst" Guid="E995D906-0273-4758-9B26-99A3A8CD143A">
|
||||||
|
<File Id="launcher_x86.exe.svcinst" Name="launcher-x86.exe" KeyPath="yes" />
|
||||||
|
<ServiceInstall
|
||||||
|
Id="launcher_x86.exe.svcinst"
|
||||||
|
Name="[P.LauncherName]"
|
||||||
|
Description="$(var.MyDescription)"
|
||||||
|
Type="ownProcess"
|
||||||
|
Start="auto"
|
||||||
|
ErrorControl="ignore" />
|
||||||
|
<ServiceControl
|
||||||
|
Id="launcher_x86.exe.svcinst"
|
||||||
|
Name="[P.LauncherName]"
|
||||||
|
Start="install"
|
||||||
|
Stop="both"
|
||||||
|
Remove="uninstall" />
|
||||||
|
<Condition>NOT VersionNT64</Condition>
|
||||||
|
</Component>
|
||||||
|
|
||||||
|
<Component Id="C.launchctl_x64.exe" Guid="2753623B-66F1-4514-B9C7-F879178DFF49">
|
||||||
|
<File Name="launchctl-x64.exe" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.launchctl_x86.exe" Guid="EBDEC4FB-07BB-47CA-BFFF-EB854CA2D22D">
|
||||||
|
<File Name="launchctl-x86.exe" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
|
||||||
|
<Component Id="C.memfs_x64.exe">
|
||||||
|
<File Name="memfs-x64.exe" KeyPath="yes" />
|
||||||
|
<RegistryKey
|
||||||
|
Root="HKLM"
|
||||||
|
Key="[P.LauncherRegistryKey]">
|
||||||
|
<RegistryKey
|
||||||
|
Key="memfs64">
|
||||||
|
<RegistryValue
|
||||||
|
Type="string"
|
||||||
|
Name="Executable"
|
||||||
|
Value="[BINDIR]memfs-x64.exe" />
|
||||||
|
<RegistryValue
|
||||||
|
Type="string"
|
||||||
|
Name="CommandLine"
|
||||||
|
Value="-u %1 -m %2" />
|
||||||
|
<RegistryValue
|
||||||
|
Type="string"
|
||||||
|
Name="Security"
|
||||||
|
Value="D:P(A;;RPWPLC;;;WD)" />
|
||||||
|
<RegistryValue
|
||||||
|
Type="integer"
|
||||||
|
Name="JobControl"
|
||||||
|
Value="1" />
|
||||||
|
</RegistryKey>
|
||||||
|
</RegistryKey>
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.memfs_x86.exe">
|
||||||
|
<File Name="memfs-x86.exe" KeyPath="yes" />
|
||||||
|
<RegistryKey
|
||||||
|
Root="HKLM"
|
||||||
|
Key="[P.LauncherRegistryKey]">
|
||||||
|
<RegistryKey
|
||||||
|
Key="memfs32">
|
||||||
|
<RegistryValue
|
||||||
|
Type="string"
|
||||||
|
Name="Executable"
|
||||||
|
Value="[BINDIR]memfs-x86.exe" />
|
||||||
|
<RegistryValue
|
||||||
|
Type="string"
|
||||||
|
Name="CommandLine"
|
||||||
|
Value="-u %1 -m %2" />
|
||||||
|
<RegistryValue
|
||||||
|
Type="string"
|
||||||
|
Name="Security"
|
||||||
|
Value="D:P(A;;RPWPLC;;;WD)" />
|
||||||
|
<RegistryValue
|
||||||
|
Type="integer"
|
||||||
|
Name="JobControl"
|
||||||
|
Value="1" />
|
||||||
|
</RegistryKey>
|
||||||
|
</RegistryKey>
|
||||||
|
</Component>
|
||||||
|
</DirectoryRef>
|
||||||
|
<DirectoryRef Id="INCDIR" FileSource="..\..\..\inc">
|
||||||
|
<Directory Id="INCDIR.winfsp" Name="winfsp">
|
||||||
|
<Component Id="C.fsctl.h">
|
||||||
|
<File Name="fsctl.h" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.winfsp.h">
|
||||||
|
<File Name="winfsp.h" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
</Directory>
|
||||||
|
</DirectoryRef>
|
||||||
|
<DirectoryRef Id="LIBDIR" FileSource="..\build\$(var.Configuration)">
|
||||||
|
<Component Id="C.winfsp_x64.lib">
|
||||||
|
<File Name="winfsp-x64.lib" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.winfsp_x86.lib">
|
||||||
|
<File Name="winfsp-x86.lib" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
</DirectoryRef>
|
||||||
|
<DirectoryRef Id="SMPDIR" FileSource="..\..\..\tst">
|
||||||
|
<Directory Id="SMPDIR.memfs" Name="memfs">
|
||||||
|
<Component Id="C.memfs.h">
|
||||||
|
<File Name="memfs.h" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.memfs.cpp">
|
||||||
|
<File Name="memfs.cpp" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
<Component Id="C.memfs_main.c">
|
||||||
|
<File Name="memfs-main.c" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
</Directory>
|
||||||
|
</DirectoryRef>
|
||||||
|
|
||||||
|
<ComponentGroup Id="C.WinFsp.bin">
|
||||||
|
<ComponentRef Id="C.winfsp_x64.sys" />
|
||||||
|
<ComponentRef Id="C.winfsp_x86.sys" />
|
||||||
|
<ComponentRef Id="C.winfsp_x64.dll.selfreg" />
|
||||||
|
<ComponentRef Id="C.winfsp_x86.dll" />
|
||||||
|
<ComponentRef Id="C.winfsp_x64.dll" />
|
||||||
|
<ComponentRef Id="C.winfsp_x86.dll.selfreg" />
|
||||||
|
<ComponentRef Id="C.launcher_x64.exe.svcinst" />
|
||||||
|
<ComponentRef Id="C.launcher_x86.exe" />
|
||||||
|
<ComponentRef Id="C.launcher_x64.exe" />
|
||||||
|
<ComponentRef Id="C.launcher_x86.exe.svcinst" />
|
||||||
|
<ComponentRef Id="C.launchctl_x64.exe" />
|
||||||
|
<ComponentRef Id="C.launchctl_x86.exe" />
|
||||||
|
</ComponentGroup>
|
||||||
|
<ComponentGroup Id="C.WinFsp.inc">
|
||||||
|
<ComponentRef Id="C.fsctl.h" />
|
||||||
|
<ComponentRef Id="C.winfsp.h" />
|
||||||
|
</ComponentGroup>
|
||||||
|
<ComponentGroup Id="C.WinFsp.lib">
|
||||||
|
<ComponentRef Id="C.winfsp_x64.lib" />
|
||||||
|
<ComponentRef Id="C.winfsp_x86.lib" />
|
||||||
|
</ComponentGroup>
|
||||||
|
<ComponentGroup Id="C.WinFsp.smp">
|
||||||
|
<ComponentRef Id="C.memfs_x64.exe" />
|
||||||
|
<ComponentRef Id="C.memfs_x86.exe" />
|
||||||
|
<ComponentRef Id="C.memfs.h" />
|
||||||
|
<ComponentRef Id="C.memfs.cpp" />
|
||||||
|
<ComponentRef Id="C.memfs_main.c" />
|
||||||
|
</ComponentGroup>
|
||||||
|
|
||||||
|
<Feature
|
||||||
|
Id="F.Main"
|
||||||
|
Level="1"
|
||||||
|
Title="$(var.MyProductName) $(var.MyVersion)"
|
||||||
|
Description="$(var.MyDescription)"
|
||||||
|
Display="expand"
|
||||||
|
ConfigurableDirectory="INSTALLDIR"
|
||||||
|
AllowAdvertise="no"
|
||||||
|
InstallDefault="local"
|
||||||
|
Absent="disallow">
|
||||||
|
<ComponentRef Id="C.INSTALLDIR" />
|
||||||
|
<Feature
|
||||||
|
Id="F.User"
|
||||||
|
Level="1"
|
||||||
|
Title="Core"
|
||||||
|
Description="The core $(var.MyProductName) files."
|
||||||
|
AllowAdvertise="no"
|
||||||
|
InstallDefault="local"
|
||||||
|
Absent="disallow">
|
||||||
|
<ComponentGroupRef Id="C.WinFsp.bin" />
|
||||||
|
</Feature>
|
||||||
|
<Feature
|
||||||
|
Id="F.Developer"
|
||||||
|
Level="1000"
|
||||||
|
Title="Developer"
|
||||||
|
Description="Additional files needed for development. Please note that the memfs sample requires the VC++ 2015 redistributable to be installed."
|
||||||
|
AllowAdvertise="no"
|
||||||
|
InstallDefault="local"
|
||||||
|
Absent="allow">
|
||||||
|
<ComponentGroupRef Id="C.WinFsp.inc" />
|
||||||
|
<ComponentGroupRef Id="C.WinFsp.lib" />
|
||||||
|
<ComponentGroupRef Id="C.WinFsp.smp" />
|
||||||
|
</Feature>
|
||||||
|
</Feature>
|
||||||
|
|
||||||
|
<UI Id="FeatureTree">
|
||||||
|
<UIRef Id="WixUI_FeatureTree" />
|
||||||
|
<!-- skip the license agreement dialog; higher Order takes priority (weird) -->
|
||||||
|
<Publish
|
||||||
|
Dialog="WelcomeDlg"
|
||||||
|
Control="Next"
|
||||||
|
Event="NewDialog"
|
||||||
|
Value="CustomizeDlg"
|
||||||
|
Order="10">NOT Installed</Publish>
|
||||||
|
<Publish
|
||||||
|
Dialog="CustomizeDlg"
|
||||||
|
Control="Back"
|
||||||
|
Event="NewDialog"
|
||||||
|
Value="WelcomeDlg"
|
||||||
|
Order="10">NOT Installed</Publish>
|
||||||
|
</UI>
|
||||||
|
|
||||||
|
<Binary Id="CustomActions" SourceFile="..\build\$(var.Configuration)\CustomActions.dll" />
|
||||||
|
<CustomAction
|
||||||
|
Id="Params.ServiceRunning"
|
||||||
|
Property="ServiceRunning"
|
||||||
|
Value="$(var.MyProductName)" />
|
||||||
|
<CustomAction
|
||||||
|
Id="Action.ServiceRunning"
|
||||||
|
BinaryKey="CustomActions"
|
||||||
|
DllEntry="ServiceRunning"
|
||||||
|
Execute="immediate"
|
||||||
|
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." />
|
||||||
|
<InstallExecuteSequence>
|
||||||
|
<Custom Action="Params.ServiceRunning" Before="Action.ServiceRunning" />
|
||||||
|
<Custom Action="Action.ServiceRunning" Before="LaunchConditions" />
|
||||||
|
<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>
|
||||||
|
</Product>
|
||||||
|
</Wix>
|
52
build/VStudio/installer/winfsp_msi.wixproj
Normal file
52
build/VStudio/installer/winfsp_msi.wixproj
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="..\version.properties" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||||
|
<ProductVersion>3.10</ProductVersion>
|
||||||
|
<ProjectGuid>d53aac39-4c57-4ca5-a4f3-c2b24888c594</ProjectGuid>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
<OutputName>winfsp-$(MyVersion)</OutputName>
|
||||||
|
<OutputType>Package</OutputType>
|
||||||
|
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' AND '$(MSBuildExtensionsPath32)' != '' ">$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
|
||||||
|
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' ">$(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
|
||||||
|
<Name>winfsp.msi</Name>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||||
|
<OutputPath>$(SolutionDir)build\$(Configuration)\</OutputPath>
|
||||||
|
<IntermediateOutputPath>$(SolutionDir)build\$(Name).build\$(Configuration)\$(Platform)\</IntermediateOutputPath>
|
||||||
|
<DefineConstants>Debug;MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyVersion=$(MyVersion)</DefineConstants>
|
||||||
|
<SuppressAllWarnings>False</SuppressAllWarnings>
|
||||||
|
<Pedantic>True</Pedantic>
|
||||||
|
<SuppressPdbOutput>True</SuppressPdbOutput>
|
||||||
|
<SuppressIces>ICE30</SuppressIces>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||||
|
<OutputPath>$(SolutionDir)build\$(Configuration)\</OutputPath>
|
||||||
|
<IntermediateOutputPath>$(SolutionDir)build\$(Name).build\$(Configuration)\$(Platform)\</IntermediateOutputPath>
|
||||||
|
<DefineConstants>MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyVersion=$(MyVersion)</DefineConstants>
|
||||||
|
<SuppressAllWarnings>False</SuppressAllWarnings>
|
||||||
|
<Pedantic>True</Pedantic>
|
||||||
|
<SuppressPdbOutput>True</SuppressPdbOutput>
|
||||||
|
<SuppressIces>ICE30</SuppressIces>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Product.wxs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<WixExtension Include="WixUIExtension">
|
||||||
|
<HintPath>$(WixExtDir)\WixUIExtension.dll</HintPath>
|
||||||
|
<Name>WixUIExtension</Name>
|
||||||
|
</WixExtension>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(WixTargetsPath)" />
|
||||||
|
<!--
|
||||||
|
To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
Other similar extension points exist, see Wix.targets.
|
||||||
|
<Target Name="BeforeBuild">
|
||||||
|
</Target>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
</Target>
|
||||||
|
-->
|
||||||
|
</Project>
|
194
build/VStudio/launcher/launchctl.vcxproj
Normal file
194
build/VStudio/launcher/launchctl.vcxproj
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="..\version.properties" />
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>{73EAAEDA-557B-48D5-A137-328934720FB4}</ProjectGuid>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<RootNamespace>launchctl</RootNamespace>
|
||||||
|
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v140</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v140</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v140</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v140</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="Shared">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<OutDir>$(SolutionDir)build\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>$(SolutionDir)build\$(ProjectName).build\$(Configuration)\$(PlatformTarget)\</IntDir>
|
||||||
|
<TargetName>$(ProjectName)-$(PlatformTarget)</TargetName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<OutDir>$(SolutionDir)build\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>$(SolutionDir)build\$(ProjectName).build\$(Configuration)\$(PlatformTarget)\</IntDir>
|
||||||
|
<TargetName>$(ProjectName)-$(PlatformTarget)</TargetName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<OutDir>$(SolutionDir)build\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>$(SolutionDir)build\$(ProjectName).build\$(Configuration)\$(PlatformTarget)\</IntDir>
|
||||||
|
<TargetName>$(ProjectName)-$(PlatformTarget)</TargetName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<OutDir>$(SolutionDir)build\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>$(SolutionDir)build\$(ProjectName).build\$(Configuration)\$(PlatformTarget)\</IntDir>
|
||||||
|
<TargetName>$(ProjectName)-$(PlatformTarget)</TargetName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<AdditionalIncludeDirectories>..\..\..\src;..\..\..\inc</AdditionalIncludeDirectories>
|
||||||
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
|
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<AdditionalIncludeDirectories>..\..\..\src;..\..\..\inc</AdditionalIncludeDirectories>
|
||||||
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
|
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<AdditionalIncludeDirectories>..\..\..\src;..\..\..\inc</AdditionalIncludeDirectories>
|
||||||
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<AdditionalIncludeDirectories>..\..\..\src;..\..\..\inc</AdditionalIncludeDirectories>
|
||||||
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\..\..\src\launcher\launcher.h" />
|
||||||
|
<ClInclude Include="..\..\..\src\shared\minimal.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\..\..\src\launcher\launchctl.c" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="..\..\..\src\launcher\launchctl-version.rc">
|
||||||
|
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">_UNICODE;UNICODE;%(PreprocessorDefinitions);MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas)</PreprocessorDefinitions>
|
||||||
|
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">_UNICODE;UNICODE;%(PreprocessorDefinitions);MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas)</PreprocessorDefinitions>
|
||||||
|
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">_UNICODE;UNICODE;%(PreprocessorDefinitions);MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas)</PreprocessorDefinitions>
|
||||||
|
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_UNICODE;UNICODE;%(PreprocessorDefinitions);MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas)</PreprocessorDefinitions>
|
||||||
|
</ResourceCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\winfsp_dll.vcxproj">
|
||||||
|
<Project>{4a7c0b21-9e10-4c81-92de-1493efcf24eb}</Project>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
33
build/VStudio/launcher/launchctl.vcxproj.filters
Normal file
33
build/VStudio/launcher/launchctl.vcxproj.filters
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Source">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Include">
|
||||||
|
<UniqueIdentifier>{e650819b-355e-455c-81c9-10dc7debe109}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Include\shared">
|
||||||
|
<UniqueIdentifier>{744edf89-567a-40b7-b6f2-ee2bc7b9f0d9}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\..\..\src\shared\minimal.h">
|
||||||
|
<Filter>Include\shared</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\src\launcher\launcher.h">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\..\..\src\launcher\launchctl.c">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="..\..\..\src\launcher\launchctl-version.rc">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ResourceCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
194
build/VStudio/launcher/launcher.vcxproj
Normal file
194
build/VStudio/launcher/launcher.vcxproj
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="..\version.properties" />
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>{A5EFD487-0140-4184-8C54-FFAEC2F85E35}</ProjectGuid>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<RootNamespace>launcher</RootNamespace>
|
||||||
|
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v140</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v140</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v140</PlatformToolset>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v140</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="Shared">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<OutDir>$(SolutionDir)build\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>$(SolutionDir)build\$(ProjectName).build\$(Configuration)\$(PlatformTarget)\</IntDir>
|
||||||
|
<TargetName>$(ProjectName)-$(PlatformTarget)</TargetName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
<OutDir>$(SolutionDir)build\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>$(SolutionDir)build\$(ProjectName).build\$(Configuration)\$(PlatformTarget)\</IntDir>
|
||||||
|
<TargetName>$(ProjectName)-$(PlatformTarget)</TargetName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<OutDir>$(SolutionDir)build\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>$(SolutionDir)build\$(ProjectName).build\$(Configuration)\$(PlatformTarget)\</IntDir>
|
||||||
|
<TargetName>$(ProjectName)-$(PlatformTarget)</TargetName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<OutDir>$(SolutionDir)build\$(Configuration)\</OutDir>
|
||||||
|
<IntDir>$(SolutionDir)build\$(ProjectName).build\$(Configuration)\$(PlatformTarget)\</IntDir>
|
||||||
|
<TargetName>$(ProjectName)-$(PlatformTarget)</TargetName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<AdditionalIncludeDirectories>..\..\..\src;..\..\..\inc</AdditionalIncludeDirectories>
|
||||||
|
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||||
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<AdditionalIncludeDirectories>..\..\..\src;..\..\..\inc</AdditionalIncludeDirectories>
|
||||||
|
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
|
||||||
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<AdditionalIncludeDirectories>..\..\..\src;..\..\..\inc</AdditionalIncludeDirectories>
|
||||||
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<AdditionalIncludeDirectories>..\..\..\src;..\..\..\inc</AdditionalIncludeDirectories>
|
||||||
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\..\..\src\launcher\launcher.c" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\winfsp_dll.vcxproj">
|
||||||
|
<Project>{4a7c0b21-9e10-4c81-92de-1493efcf24eb}</Project>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\..\..\src\launcher\launcher.h" />
|
||||||
|
<ClInclude Include="..\..\..\src\shared\minimal.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="..\..\..\src\launcher\launcher-version.rc">
|
||||||
|
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">_UNICODE;UNICODE;%(PreprocessorDefinitions);MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas)</PreprocessorDefinitions>
|
||||||
|
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">_UNICODE;UNICODE;%(PreprocessorDefinitions);MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas)</PreprocessorDefinitions>
|
||||||
|
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">_UNICODE;UNICODE;%(PreprocessorDefinitions);MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas)</PreprocessorDefinitions>
|
||||||
|
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_UNICODE;UNICODE;%(PreprocessorDefinitions);MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas)</PreprocessorDefinitions>
|
||||||
|
</ResourceCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
33
build/VStudio/launcher/launcher.vcxproj.filters
Normal file
33
build/VStudio/launcher/launcher.vcxproj.filters
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Source">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Include">
|
||||||
|
<UniqueIdentifier>{11e7c0f2-7782-43ee-84fa-9e56efbe39de}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Include\shared">
|
||||||
|
<UniqueIdentifier>{d83ea433-d9f7-494c-90b9-3a8997483cd9}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\..\..\src\launcher\launcher.c">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="..\..\..\src\shared\minimal.h">
|
||||||
|
<Filter>Include\shared</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\..\src\launcher\launcher.h">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="..\..\..\src\launcher\launcher-version.rc">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ResourceCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
@ -183,6 +183,7 @@
|
|||||||
<ClCompile Include="..\..\..\tst\memfs\memfs.cpp" />
|
<ClCompile Include="..\..\..\tst\memfs\memfs.cpp" />
|
||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\create-test.c" />
|
<ClCompile Include="..\..\..\tst\winfsp-tests\create-test.c" />
|
||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\dirctl-test.c" />
|
<ClCompile Include="..\..\..\tst\winfsp-tests\dirctl-test.c" />
|
||||||
|
<ClCompile Include="..\..\..\tst\winfsp-tests\eventlog-test.c" />
|
||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\flush-test.c" />
|
<ClCompile Include="..\..\..\tst\winfsp-tests\flush-test.c" />
|
||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\info-test.c" />
|
<ClCompile Include="..\..\..\tst\winfsp-tests\info-test.c" />
|
||||||
<ClCompile Include="..\..\..\tst\winfsp-tests\lock-test.c" />
|
<ClCompile Include="..\..\..\tst\winfsp-tests\lock-test.c" />
|
||||||
|
@ -52,6 +52,9 @@
|
|||||||
<ClCompile Include="..\..\..\tst\memfs\memfs.cpp">
|
<ClCompile Include="..\..\..\tst\memfs\memfs.cpp">
|
||||||
<Filter>Source</Filter>
|
<Filter>Source</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\..\tst\winfsp-tests\eventlog-test.c">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\..\ext\tlib\testsuite.h">
|
<ClInclude Include="..\..\..\ext\tlib\testsuite.h">
|
||||||
|
13
build/VStudio/version.properties
Normal file
13
build/VStudio/version.properties
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<MyProductName>WinFsp</MyProductName>
|
||||||
|
<MyDescription>Windows File System Proxy</MyDescription>
|
||||||
|
<MyCompanyName>Navimatics Corporation</MyCompanyName>
|
||||||
|
<MyCopyright>2015-2016 Bill Zissimopoulos</MyCopyright>
|
||||||
|
<!-- 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>
|
||||||
|
<MyVersion>0.11.$(MyBuildNumber)</MyVersion>
|
||||||
|
<MyVersionWithCommas>$(MyVersion.Replace('.',',')),0</MyVersionWithCommas>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 14
|
# Visual Studio 14
|
||||||
VisualStudioVersion = 14.0.23107.0
|
VisualStudioVersion = 14.0.25123.0
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "winfsp.dll", "winfsp_dll.vcxproj", "{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "winfsp.dll", "winfsp_dll.vcxproj", "{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}"
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
@ -23,10 +23,36 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "memfs", "testing\memfs.vcxp
|
|||||||
{C85C26BA-8C22-4D30-83DA-46C3548E6332} = {C85C26BA-8C22-4D30-83DA-46C3548E6332}
|
{C85C26BA-8C22-4D30-83DA-46C3548E6332} = {C85C26BA-8C22-4D30-83DA-46C3548E6332}
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "installer", "installer", "{B464EF06-42AE-4674-81BB-FDDE80204822}"
|
||||||
|
EndProject
|
||||||
|
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "winfsp_msi", "installer\winfsp_msi.wixproj", "{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}"
|
||||||
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
{95C223E6-B5F1-4FD0-9376-41CDBC824445} = {95C223E6-B5F1-4FD0-9376-41CDBC824445}
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CustomActions", "installer\CustomActions\CustomActions.vcxproj", "{95C223E6-B5F1-4FD0-9376-41CDBC824445}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "launcher", "launcher", "{FD28A504-431E-49B9-BB8C-DCA0E7019F66}"
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "launcher", "launcher\launcher.vcxproj", "{A5EFD487-0140-4184-8C54-FFAEC2F85E35}"
|
||||||
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB} = {4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}
|
||||||
|
{C85C26BA-8C22-4D30-83DA-46C3548E6332} = {C85C26BA-8C22-4D30-83DA-46C3548E6332}
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "launchctl", "launcher\launchctl.vcxproj", "{73EAAEDA-557B-48D5-A137-328934720FB4}"
|
||||||
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
{A5EFD487-0140-4184-8C54-FFAEC2F85E35} = {A5EFD487-0140-4184-8C54-FFAEC2F85E35}
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|x64 = Debug|x64
|
Debug|x64 = Debug|x64
|
||||||
Debug|x86 = Debug|x86
|
Debug|x86 = Debug|x86
|
||||||
|
Installer.Debug|x64 = Installer.Debug|x64
|
||||||
|
Installer.Debug|x86 = Installer.Debug|x86
|
||||||
|
Installer.Release|x64 = Installer.Release|x64
|
||||||
|
Installer.Release|x86 = Installer.Release|x86
|
||||||
Release|x64 = Release|x64
|
Release|x64 = Release|x64
|
||||||
Release|x86 = Release|x86
|
Release|x86 = Release|x86
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
@ -35,6 +61,10 @@ Global
|
|||||||
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Debug|x64.Build.0 = Debug|x64
|
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Debug|x64.Build.0 = Debug|x64
|
||||||
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Debug|x86.ActiveCfg = Debug|Win32
|
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Debug|x86.Build.0 = Debug|Win32
|
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Installer.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Installer.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Installer.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Installer.Release|x86.ActiveCfg = Release|Win32
|
||||||
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Release|x64.ActiveCfg = Release|x64
|
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Release|x64.ActiveCfg = Release|x64
|
||||||
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Release|x64.Build.0 = Release|x64
|
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Release|x64.Build.0 = Release|x64
|
||||||
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Release|x86.ActiveCfg = Release|Win32
|
{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}.Release|x86.ActiveCfg = Release|Win32
|
||||||
@ -43,6 +73,10 @@ Global
|
|||||||
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Debug|x64.Build.0 = Debug|x64
|
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Debug|x64.Build.0 = Debug|x64
|
||||||
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Debug|x86.ActiveCfg = Debug|Win32
|
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Debug|x86.Build.0 = Debug|Win32
|
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Installer.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Installer.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Installer.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Installer.Release|x86.ActiveCfg = Release|Win32
|
||||||
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Release|x64.ActiveCfg = Release|x64
|
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Release|x64.ActiveCfg = Release|x64
|
||||||
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Release|x64.Build.0 = Release|x64
|
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Release|x64.Build.0 = Release|x64
|
||||||
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Release|x86.ActiveCfg = Release|Win32
|
{C85C26BA-8C22-4D30-83DA-46C3548E6332}.Release|x86.ActiveCfg = Release|Win32
|
||||||
@ -51,6 +85,10 @@ Global
|
|||||||
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Debug|x64.Build.0 = Debug|x64
|
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Debug|x64.Build.0 = Debug|x64
|
||||||
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Debug|x86.ActiveCfg = Debug|Win32
|
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Debug|x86.Build.0 = Debug|Win32
|
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Installer.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Installer.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Installer.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Installer.Release|x86.ActiveCfg = Release|Win32
|
||||||
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Release|x64.ActiveCfg = Release|x64
|
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Release|x64.ActiveCfg = Release|x64
|
||||||
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Release|x64.Build.0 = Release|x64
|
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Release|x64.Build.0 = Release|x64
|
||||||
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Release|x86.ActiveCfg = Release|Win32
|
{262DF8CC-E7A8-4460-A22C-683CBA322C32}.Release|x86.ActiveCfg = Release|Win32
|
||||||
@ -59,10 +97,62 @@ Global
|
|||||||
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Debug|x64.Build.0 = Debug|x64
|
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Debug|x64.Build.0 = Debug|x64
|
||||||
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Debug|x86.ActiveCfg = Debug|Win32
|
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Debug|x86.Build.0 = Debug|Win32
|
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Installer.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Installer.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Installer.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Installer.Release|x86.ActiveCfg = Release|Win32
|
||||||
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Release|x64.ActiveCfg = Release|x64
|
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Release|x64.ActiveCfg = Release|x64
|
||||||
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Release|x64.Build.0 = Release|x64
|
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Release|x64.Build.0 = Release|x64
|
||||||
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Release|x86.ActiveCfg = Release|Win32
|
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Release|x86.ActiveCfg = Release|Win32
|
||||||
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Release|x86.Build.0 = Release|Win32
|
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1}.Release|x86.Build.0 = Release|Win32
|
||||||
|
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Debug|x64.ActiveCfg = Debug|x86
|
||||||
|
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Debug|x86.ActiveCfg = Debug|x86
|
||||||
|
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Debug|x64.ActiveCfg = Release|x86
|
||||||
|
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Debug|x64.Build.0 = Release|x86
|
||||||
|
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Debug|x86.ActiveCfg = Debug|x86
|
||||||
|
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Debug|x86.Build.0 = Debug|x86
|
||||||
|
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Release|x64.ActiveCfg = Release|x86
|
||||||
|
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Release|x64.Build.0 = Release|x86
|
||||||
|
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Release|x86.ActiveCfg = Release|x86
|
||||||
|
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Installer.Release|x86.Build.0 = Release|x86
|
||||||
|
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Release|x64.ActiveCfg = Release|x86
|
||||||
|
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594}.Release|x86.ActiveCfg = Release|x86
|
||||||
|
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Debug|x64.ActiveCfg = Debug|Win32
|
||||||
|
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Debug|x64.ActiveCfg = Release|Win32
|
||||||
|
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Debug|x64.Build.0 = Release|Win32
|
||||||
|
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Release|x64.ActiveCfg = Release|Win32
|
||||||
|
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Release|x64.Build.0 = Release|Win32
|
||||||
|
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Installer.Release|x86.Build.0 = Release|Win32
|
||||||
|
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Release|x64.ActiveCfg = Release|Win32
|
||||||
|
{95C223E6-B5F1-4FD0-9376-41CDBC824445}.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Installer.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Installer.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Installer.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Installer.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Release|x64.Build.0 = Release|x64
|
||||||
|
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{A5EFD487-0140-4184-8C54-FFAEC2F85E35}.Release|x86.Build.0 = Release|Win32
|
||||||
|
{73EAAEDA-557B-48D5-A137-328934720FB4}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{73EAAEDA-557B-48D5-A137-328934720FB4}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{73EAAEDA-557B-48D5-A137-328934720FB4}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{73EAAEDA-557B-48D5-A137-328934720FB4}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{73EAAEDA-557B-48D5-A137-328934720FB4}.Installer.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{73EAAEDA-557B-48D5-A137-328934720FB4}.Installer.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{73EAAEDA-557B-48D5-A137-328934720FB4}.Installer.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{73EAAEDA-557B-48D5-A137-328934720FB4}.Installer.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{73EAAEDA-557B-48D5-A137-328934720FB4}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{73EAAEDA-557B-48D5-A137-328934720FB4}.Release|x64.Build.0 = Release|x64
|
||||||
|
{73EAAEDA-557B-48D5-A137-328934720FB4}.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{73EAAEDA-557B-48D5-A137-328934720FB4}.Release|x86.Build.0 = Release|Win32
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@ -70,5 +160,9 @@ Global
|
|||||||
GlobalSection(NestedProjects) = preSolution
|
GlobalSection(NestedProjects) = preSolution
|
||||||
{262DF8CC-E7A8-4460-A22C-683CBA322C32} = {69439FD1-C07D-4BF1-98DC-3CCFECE53A49}
|
{262DF8CC-E7A8-4460-A22C-683CBA322C32} = {69439FD1-C07D-4BF1-98DC-3CCFECE53A49}
|
||||||
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1} = {69439FD1-C07D-4BF1-98DC-3CCFECE53A49}
|
{AA7190E8-877F-4827-8CDD-E0D85F83C8C1} = {69439FD1-C07D-4BF1-98DC-3CCFECE53A49}
|
||||||
|
{D53AAC39-4C57-4CA5-A4F3-C2B24888C594} = {B464EF06-42AE-4674-81BB-FDDE80204822}
|
||||||
|
{95C223E6-B5F1-4FD0-9376-41CDBC824445} = {B464EF06-42AE-4674-81BB-FDDE80204822}
|
||||||
|
{A5EFD487-0140-4184-8C54-FFAEC2F85E35} = {FD28A504-431E-49B9-BB8C-DCA0E7019F66}
|
||||||
|
{73EAAEDA-557B-48D5-A137-328934720FB4} = {FD28A504-431E-49B9-BB8C-DCA0E7019F66}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="version.properties" />
|
||||||
<ItemGroup Label="ProjectConfigurations">
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
<ProjectConfiguration Include="Debug|Win32">
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
<Configuration>Debug</Configuration>
|
<Configuration>Debug</Configuration>
|
||||||
@ -22,8 +23,10 @@
|
|||||||
<ClInclude Include="..\..\inc\winfsp\fsctl.h" />
|
<ClInclude Include="..\..\inc\winfsp\fsctl.h" />
|
||||||
<ClInclude Include="..\..\inc\winfsp\winfsp.h" />
|
<ClInclude Include="..\..\inc\winfsp\winfsp.h" />
|
||||||
<ClInclude Include="..\..\src\dll\library.h" />
|
<ClInclude Include="..\..\src\dll\library.h" />
|
||||||
|
<ClInclude Include="..\..\src\shared\minimal.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClCompile Include="..\..\src\dll\eventlog.c" />
|
||||||
<ClCompile Include="..\..\src\dll\np.c" />
|
<ClCompile Include="..\..\src\dll\np.c" />
|
||||||
<ClCompile Include="..\..\src\dll\security.c" />
|
<ClCompile Include="..\..\src\dll\security.c" />
|
||||||
<ClCompile Include="..\..\src\dll\debug.c" />
|
<ClCompile Include="..\..\src\dll\debug.c" />
|
||||||
@ -33,11 +36,21 @@
|
|||||||
<ClCompile Include="..\..\src\dll\fs.c" />
|
<ClCompile Include="..\..\src\dll\fs.c" />
|
||||||
<ClCompile Include="..\..\src\dll\ntstatus.c" />
|
<ClCompile Include="..\..\src\dll\ntstatus.c" />
|
||||||
<ClCompile Include="..\..\src\dll\path.c" />
|
<ClCompile Include="..\..\src\dll\path.c" />
|
||||||
|
<ClCompile Include="..\..\src\dll\service.c" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="..\..\src\dll\library.def" />
|
<None Include="..\..\src\dll\library.def" />
|
||||||
<None Include="..\..\src\dll\ntstatus.i" />
|
<None Include="..\..\src\dll\ntstatus.i" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="..\..\src\dll\eventlog\eventlog.rc" />
|
||||||
|
<ResourceCompile Include="..\..\src\dll\version.rc">
|
||||||
|
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">_UNICODE;UNICODE;%(PreprocessorDefinitions);MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas)</PreprocessorDefinitions>
|
||||||
|
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">_UNICODE;UNICODE;%(PreprocessorDefinitions);MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas)</PreprocessorDefinitions>
|
||||||
|
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">_UNICODE;UNICODE;%(PreprocessorDefinitions);MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas)</PreprocessorDefinitions>
|
||||||
|
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_UNICODE;UNICODE;%(PreprocessorDefinitions);MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas)</PreprocessorDefinitions>
|
||||||
|
</ResourceCompile>
|
||||||
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Globals">
|
<PropertyGroup Label="Globals">
|
||||||
<ProjectGuid>{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}</ProjectGuid>
|
<ProjectGuid>{4A7C0B21-9E10-4C81-92DE-1493EFCF24EB}</ProjectGuid>
|
||||||
<Keyword>Win32Proj</Keyword>
|
<Keyword>Win32Proj</Keyword>
|
||||||
@ -136,6 +149,7 @@
|
|||||||
<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>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
@ -160,6 +174,7 @@
|
|||||||
<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>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
@ -187,6 +202,7 @@
|
|||||||
<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>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
@ -214,6 +230,7 @@
|
|||||||
<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>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
@ -12,6 +12,9 @@
|
|||||||
<Filter Include="Include\winfsp">
|
<Filter Include="Include\winfsp">
|
||||||
<UniqueIdentifier>{1d6501f4-cebd-4a00-a774-deb782b59fb5}</UniqueIdentifier>
|
<UniqueIdentifier>{1d6501f4-cebd-4a00-a774-deb782b59fb5}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter Include="Include\shared">
|
||||||
|
<UniqueIdentifier>{c7b83307-0aa0-4593-b2d4-26ff2f1edfc6}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\inc\winfsp\fsctl.h">
|
<ClInclude Include="..\..\inc\winfsp\fsctl.h">
|
||||||
@ -23,6 +26,9 @@
|
|||||||
<ClInclude Include="..\..\src\dll\library.h">
|
<ClInclude Include="..\..\src\dll\library.h">
|
||||||
<Filter>Source</Filter>
|
<Filter>Source</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\..\src\shared\minimal.h">
|
||||||
|
<Filter>Include\shared</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\..\src\dll\library.c">
|
<ClCompile Include="..\..\src\dll\library.c">
|
||||||
@ -52,6 +58,12 @@
|
|||||||
<ClCompile Include="..\..\src\dll\np.c">
|
<ClCompile Include="..\..\src\dll\np.c">
|
||||||
<Filter>Source</Filter>
|
<Filter>Source</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\dll\service.c">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\src\dll\eventlog.c">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="..\..\src\dll\ntstatus.i">
|
<None Include="..\..\src\dll\ntstatus.i">
|
||||||
@ -61,4 +73,12 @@
|
|||||||
<Filter>Source</Filter>
|
<Filter>Source</Filter>
|
||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="..\..\src\dll\version.rc">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ResourceCompile>
|
||||||
|
<ResourceCompile Include="..\..\src\dll\eventlog\eventlog.rc">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ResourceCompile>
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@ -1,5 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="version.properties" />
|
||||||
<ItemGroup Label="ProjectConfigurations">
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
<ProjectConfiguration Include="Debug|Win32">
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
<Configuration>Debug</Configuration>
|
<Configuration>Debug</Configuration>
|
||||||
@ -177,6 +178,14 @@
|
|||||||
<ClInclude Include="..\..\inc\winfsp\fsctl.h" />
|
<ClInclude Include="..\..\inc\winfsp\fsctl.h" />
|
||||||
<ClInclude Include="..\..\src\sys\driver.h" />
|
<ClInclude Include="..\..\src\sys\driver.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="..\..\src\sys\version.rc">
|
||||||
|
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">_X86_=1;i386=1;STD_CALL;%(PreprocessorDefinitions);MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas)</PreprocessorDefinitions>
|
||||||
|
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">_X86_=1;i386=1;STD_CALL;%(PreprocessorDefinitions);MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas)</PreprocessorDefinitions>
|
||||||
|
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">_WIN64;_AMD64_=1;AMD64;%(PreprocessorDefinitions);MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas)</PreprocessorDefinitions>
|
||||||
|
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">_WIN64;_AMD64_=1;AMD64;%(PreprocessorDefinitions);MyProductName=$(MyProductName);MyDescription=$(MyDescription);MyCompanyName=$(MyCompanyName);MyCopyright=$(MyCopyright);MyVersion=$(MyVersion);MyVersionWithCommas=$(MyVersionWithCommas)</PreprocessorDefinitions>
|
||||||
|
</ResourceCompile>
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
|
@ -101,4 +101,9 @@
|
|||||||
<Filter>Include\winfsp</Filter>
|
<Filter>Include\winfsp</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="..\..\src\sys\version.rc">
|
||||||
|
<Filter>Source</Filter>
|
||||||
|
</ResourceCompile>
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
@ -1,9 +1,13 @@
|
|||||||
web: web/winfsp-design.html web/winfsp.h.html
|
web: web/winfsp-design.html web/service-architecture.html web/winfsp.h.html
|
||||||
|
|
||||||
web/winfsp-design.html:
|
web/winfsp-design.html:
|
||||||
mkdir -p web
|
mkdir -p web
|
||||||
asciidoc -b html4 -a hr= -s -o $@ winfsp-design.adoc
|
asciidoc -b html4 -a hr= -s -o $@ winfsp-design.adoc
|
||||||
|
|
||||||
|
web/service-architecture.html:
|
||||||
|
mkdir -p web
|
||||||
|
asciidoc -b html4 -a hr= -s -o $@ service-architecture.adoc
|
||||||
|
|
||||||
web/winfsp.h.html:
|
web/winfsp.h.html:
|
||||||
mkdir -p web
|
mkdir -p web
|
||||||
prettydoc -H-O -o web ../inc/winfsp/winfsp.h
|
prettydoc -H-O -o web ../inc/winfsp/winfsp.h
|
||||||
|
47
doc/service-architecture.adoc
Normal file
47
doc/service-architecture.adoc
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
= WinFsp Service Architecture
|
||||||
|
|
||||||
|
This document discusses an architecture for writing user mode file systems as Windows services.
|
||||||
|
|
||||||
|
== Overview
|
||||||
|
|
||||||
|
There are a variety of reasons that user mode file systems should be written as Windows services. Chief among those are that a Windows service runs independently from user sessions. Therefore a user mode file system can provide its services to all processes in the system rather than those of the current user session. Furthermore a Windows service (usually) runs under an account with elevated privileges, which may be a requirement for some user mode file systems.
|
||||||
|
|
||||||
|
The Windows Service Control Manager provides a clean protocol for installing, configuring and controlling services. Unfortunately it also has a major deficiency in that it only allows a single instance of a particular service to be launched. The technique usually employed to work around this deficiency is to create multiple named instances of the same service (e.g. ServiceName #1, ServiceName #2). This technique assumes that there is a finite and well known set of instances, which may not always be the case.
|
||||||
|
|
||||||
|
Consider, for example, a network file system NETFS which can be used to provide a network based file system. NETFS connects to a particular server and uses its proprietary protocol to access files on that server, which it then presents to Windows as native files. Clearly there may be a very large number of NETFS servers, which makes the idea of creating separate named service instances for each server unworkable. One alternative for the NETFS developer is to create a service that manages multiple NETFS instances. Another one is to use the WinFsp service architecture described in this document.
|
||||||
|
|
||||||
|
== WinFsp Launcher
|
||||||
|
|
||||||
|
In order to overcome the issue with launching multiple instances of a particular service, WinFsp provides a generic launcher named WinFsp.Launcher. The WinFsp.Launcher is itself a Windows service that can be used to launch and control other services, provided that they fulfill the following requirements:
|
||||||
|
|
||||||
|
* That they are marked as console executables.
|
||||||
|
* That they can be parameterized using the command line.
|
||||||
|
* That they respond to the CTRL-BREAK console control event and terminate timely.
|
||||||
|
|
||||||
|
Services that wish to be controlled by the WinFsp.Launcher must add themselves under the following registry key:
|
||||||
|
|
||||||
|
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\WinFsp.Launcher\Services
|
||||||
|
|
||||||
|
For example, the MEMFS sample adds the following registry entries under this key:
|
||||||
|
|
||||||
|
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\WinFsp.Launcher\Services\memfs32]
|
||||||
|
"Executable"="C:\\Program Files (x86)\\WinFsp\\bin\\memfs-x86.exe"
|
||||||
|
"CommandLine"="-u %1 -m %2"
|
||||||
|
"Security"="D:P(A;;RPWPLC;;;WD)"
|
||||||
|
"JobControl"=dword:00000001
|
||||||
|
|
||||||
|
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\WinFsp.Launcher\Services\memfs64]
|
||||||
|
"Executable"="C:\\Program Files (x86)\\WinFsp\\bin\\memfs-x64.exe"
|
||||||
|
"CommandLine"="-u %1 -m %2"
|
||||||
|
"Security"="D:P(A;;RPWPLC;;;WD)"
|
||||||
|
"JobControl"=dword:00000001
|
||||||
|
|
||||||
|
When the WinFsp.Launcher starts up it creates a named pipe that applications can use to start, stop, get information about and list service instances. A small command line utility (`launchctl`) can be used to issue those commands. The CallNamedPipeW API can be used as well.
|
||||||
|
|
||||||
|
One final note regarding security. Notice the `Security` registry value in the example above. This registry value uses SDDL syntax to instruct WinFsp.Launcher to allow Everyone (`WD`) to start (`RP`), stop (`WP`) and get information (`LC`) about the service instance. If the `Security` registry value is missing the default is to allow only LocalSystem and Administrators to control the service instance.
|
||||||
|
|
||||||
|
== WinFsp Network Provider
|
||||||
|
|
||||||
|
WinFsp includes a Network Provider that integrates with Windows and can be used to start and stop user mode file systems from the Windows shell. To achieve this the Network Provider (implemented as part of the WinFsp DLL) works closely with the WinFsp.Launcher service.
|
||||||
|
|
||||||
|
For example, if a user uses the Windows Explorer to map `\\memfs64\share` to the `Z:` drive, the Network Provider will instruct the WinFsp.Launcher to start an instance of the memfs64 service with command line `-u \\memfs64\share -m Z:`. When the user disconnects the `Z:` drive, the Network Provider will instruct the WinFsp.Launcher to stop the previously started instance of the memfs64 service.
|
@ -24,6 +24,7 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define FSP_FSCTL_DRIVER_NAME "WinFsp"
|
||||||
#define FSP_FSCTL_DISK_DEVICE_NAME "WinFsp.Disk"
|
#define FSP_FSCTL_DISK_DEVICE_NAME "WinFsp.Disk"
|
||||||
#define FSP_FSCTL_NET_DEVICE_NAME "WinFsp.Net"
|
#define FSP_FSCTL_NET_DEVICE_NAME "WinFsp.Net"
|
||||||
|
|
||||||
@ -311,7 +312,7 @@ typedef struct
|
|||||||
UINT64 Hint;
|
UINT64 Hint;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
UINT64 Information;
|
UINT32 Information;
|
||||||
UINT32 Status;
|
UINT32 Status;
|
||||||
} IoStatus;
|
} IoStatus;
|
||||||
union
|
union
|
||||||
|
@ -1,12 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @file winfsp/winfsp.h
|
* @file winfsp/winfsp.h
|
||||||
* WinFsp user mode API.
|
* WinFsp User Mode API.
|
||||||
*
|
|
||||||
* A user mode file system is a program that uses the WinFsp API to expose a file system to
|
|
||||||
* Windows. The user mode file system must implement the operations in FSP_FILE_SYSTEM_INTERFACE,
|
|
||||||
* create a file system object using FspFileSystemCreate and start its dispatcher using
|
|
||||||
* FspFileSystemStartDispatcher. At that point it will start receing file system requests on the
|
|
||||||
* FSP_FILE_SYSTEM_INTERFACE operations.
|
|
||||||
*
|
*
|
||||||
* In order to use the WinFsp API the user mode file system must include <winfsp/winfsp.h>
|
* In order to use the WinFsp API the user mode file system must include <winfsp/winfsp.h>
|
||||||
* and link with the winfsp_x64.dll (or winfsp_x86.dll) library.
|
* and link with the winfsp_x64.dll (or winfsp_x86.dll) library.
|
||||||
@ -46,8 +40,14 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* File System
|
* @group File System
|
||||||
|
*
|
||||||
|
* A user mode file system is a program that uses the WinFsp API to expose a file system to
|
||||||
|
* Windows. The user mode file system must implement the operations in FSP_FILE_SYSTEM_INTERFACE,
|
||||||
|
* create a file system object using FspFileSystemCreate and start its dispatcher using
|
||||||
|
* FspFileSystemStartDispatcher. At that point it will start receing file system requests on the
|
||||||
|
* FSP_FILE_SYSTEM_INTERFACE operations.
|
||||||
*/
|
*/
|
||||||
typedef struct _FSP_FILE_SYSTEM FSP_FILE_SYSTEM;
|
typedef struct _FSP_FILE_SYSTEM FSP_FILE_SYSTEM;
|
||||||
typedef VOID FSP_FILE_SYSTEM_OPERATION_GUARD(FSP_FILE_SYSTEM *,
|
typedef VOID FSP_FILE_SYSTEM_OPERATION_GUARD(FSP_FILE_SYSTEM *,
|
||||||
@ -838,13 +838,206 @@ FSP_API VOID FspPathPrefix(PWSTR Path, PWSTR *PPrefix, PWSTR *PRemain, PWSTR Roo
|
|||||||
FSP_API VOID FspPathSuffix(PWSTR Path, PWSTR *PRemain, PWSTR *PSuffix, PWSTR Root);
|
FSP_API VOID FspPathSuffix(PWSTR Path, PWSTR *PRemain, PWSTR *PSuffix, PWSTR Root);
|
||||||
FSP_API VOID FspPathCombine(PWSTR Prefix, PWSTR Suffix);
|
FSP_API VOID FspPathCombine(PWSTR Prefix, PWSTR Suffix);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group Service Framework
|
||||||
|
*
|
||||||
|
* User mode file systems typically are run as Windows services. WinFsp provides an API to make
|
||||||
|
* the creation of Windows services easier. This API is provided for convenience and is not
|
||||||
|
* necessary to expose a user mode file system to Windows.
|
||||||
|
*/
|
||||||
|
typedef struct _FSP_SERVICE FSP_SERVICE;
|
||||||
|
typedef NTSTATUS FSP_SERVICE_START(FSP_SERVICE *, ULONG, PWSTR *);
|
||||||
|
typedef NTSTATUS FSP_SERVICE_STOP(FSP_SERVICE *);
|
||||||
|
typedef NTSTATUS FSP_SERVICE_CONTROL(FSP_SERVICE *, ULONG, ULONG, PVOID);
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable:4200) /* zero-sized array in struct/union */
|
||||||
|
typedef struct _FSP_SERVICE
|
||||||
|
{
|
||||||
|
UINT16 Version;
|
||||||
|
PVOID UserContext;
|
||||||
|
FSP_SERVICE_START *OnStart;
|
||||||
|
FSP_SERVICE_STOP *OnStop;
|
||||||
|
FSP_SERVICE_CONTROL *OnControl;
|
||||||
|
ULONG AcceptControl;
|
||||||
|
ULONG ExitCode;
|
||||||
|
SERVICE_STATUS_HANDLE StatusHandle;
|
||||||
|
SERVICE_STATUS ServiceStatus;
|
||||||
|
CRITICAL_SECTION ServiceStatusGuard;
|
||||||
|
CRITICAL_SECTION ServiceStopGuard;
|
||||||
|
BOOLEAN AllowConsoleMode;
|
||||||
|
WCHAR ServiceName[];
|
||||||
|
} FSP_SERVICE;
|
||||||
|
#pragma warning(pop)
|
||||||
|
/**
|
||||||
|
* Run a service.
|
||||||
|
*
|
||||||
|
* This function wraps calls to FspServiceCreate, FspServiceLoop and FspServiceDelete to create,
|
||||||
|
* run and delete a service. It is intended to be used from a service's main/wmain function.
|
||||||
|
*
|
||||||
|
* This function runs a service with console mode allowed.
|
||||||
|
*
|
||||||
|
* @param ServiceName
|
||||||
|
* The name of the service.
|
||||||
|
* @param OnStart
|
||||||
|
* Function to call when the service starts.
|
||||||
|
* @param OnStop
|
||||||
|
* Function to call when the service stops.
|
||||||
|
* @param OnControl
|
||||||
|
* Function to call when the service receives a service control code.
|
||||||
|
* @return
|
||||||
|
* Service process exit code.
|
||||||
|
*/
|
||||||
|
FSP_API ULONG FspServiceRun(PWSTR ServiceName,
|
||||||
|
FSP_SERVICE_START *OnStart,
|
||||||
|
FSP_SERVICE_STOP *OnStop,
|
||||||
|
FSP_SERVICE_CONTROL *OnControl);
|
||||||
|
/**
|
||||||
|
* Create a service object.
|
||||||
|
*
|
||||||
|
* @param ServiceName
|
||||||
|
* The name of the service.
|
||||||
|
* @param OnStart
|
||||||
|
* Function to call when the service starts.
|
||||||
|
* @param OnStop
|
||||||
|
* Function to call when the service stops.
|
||||||
|
* @param OnControl
|
||||||
|
* Function to call when the service receives a service control code.
|
||||||
|
* @param PService [out]
|
||||||
|
* Pointer that will receive the service object created on successful return from this
|
||||||
|
* call.
|
||||||
|
* @return
|
||||||
|
* STATUS_SUCCESS on error code.
|
||||||
|
*/
|
||||||
|
FSP_API NTSTATUS FspServiceCreate(PWSTR ServiceName,
|
||||||
|
FSP_SERVICE_START *OnStart,
|
||||||
|
FSP_SERVICE_STOP *OnStop,
|
||||||
|
FSP_SERVICE_CONTROL *OnControl,
|
||||||
|
FSP_SERVICE **PService);
|
||||||
|
/**
|
||||||
|
* Delete a service object.
|
||||||
|
*
|
||||||
|
* @param Service
|
||||||
|
* The service object.
|
||||||
|
*/
|
||||||
|
FSP_API VOID FspServiceDelete(FSP_SERVICE *Service);
|
||||||
|
/**
|
||||||
|
* Allow a service to run in console mode.
|
||||||
|
*
|
||||||
|
* A service that is run in console mode runs with a console attached and outside the control of
|
||||||
|
* the Service Control Manager. This is useful for debugging and testing a service during
|
||||||
|
* development.
|
||||||
|
*
|
||||||
|
* User mode file systems that wish to use the WinFsp Launcher functionality must also use this
|
||||||
|
* call. The WinFsp Launcher is a Windows service that can be configured to launch and manage
|
||||||
|
* multiple instances of a user mode file system.
|
||||||
|
*
|
||||||
|
* @param Service
|
||||||
|
* The service object.
|
||||||
|
*/
|
||||||
|
FSP_API VOID FspServiceAllowConsoleMode(FSP_SERVICE *Service);
|
||||||
|
/**
|
||||||
|
* Configure the control codes that a service accepts.
|
||||||
|
*
|
||||||
|
* This API should be used prior to Start operations.
|
||||||
|
*
|
||||||
|
* @param Service
|
||||||
|
* The service object.
|
||||||
|
* @param Control
|
||||||
|
* The control codes to accept. Note that the SERVICE_ACCEPT_PAUSE_CONTINUE code is silently
|
||||||
|
* ignored.
|
||||||
|
*/
|
||||||
|
FSP_API VOID FspServiceAcceptControl(FSP_SERVICE *Service, ULONG Control);
|
||||||
|
/**
|
||||||
|
* Request additional time from the Service Control Manager.
|
||||||
|
*
|
||||||
|
* This API should be used during Start and Stop operations only.
|
||||||
|
*
|
||||||
|
* @param Service
|
||||||
|
* The service object.
|
||||||
|
* @param Time
|
||||||
|
* Additional time (in milliseconds).
|
||||||
|
*/
|
||||||
|
FSP_API VOID FspServiceRequestTime(FSP_SERVICE *Service, ULONG Time);
|
||||||
|
/**
|
||||||
|
* Set the service process exit code.
|
||||||
|
*
|
||||||
|
* @param Service
|
||||||
|
* The service object.
|
||||||
|
* @param ExitCode
|
||||||
|
* Service process exit code.
|
||||||
|
*/
|
||||||
|
FSP_API VOID FspServiceSetExitCode(FSP_SERVICE *Service, ULONG ExitCode);
|
||||||
|
/**
|
||||||
|
* Get the service process exit code.
|
||||||
|
*
|
||||||
|
* @param Service
|
||||||
|
* The service object.
|
||||||
|
* @return
|
||||||
|
* Service process exit code.
|
||||||
|
*/
|
||||||
|
FSP_API ULONG FspServiceGetExitCode(FSP_SERVICE *Service);
|
||||||
|
/**
|
||||||
|
* Run a service main loop.
|
||||||
|
*
|
||||||
|
* This function starts and runs a service. It executes the Windows StartServiceCtrlDispatcher API
|
||||||
|
* to connect the service process to the Service Control Manager. If the Service Control Manager is
|
||||||
|
* not available (and console mode is allowed) it will enter console mode.
|
||||||
|
*
|
||||||
|
* @param Service
|
||||||
|
* The service object.
|
||||||
|
* @return
|
||||||
|
* STATUS_SUCCESS on error code.
|
||||||
|
*/
|
||||||
|
FSP_API NTSTATUS FspServiceLoop(FSP_SERVICE *Service);
|
||||||
|
/**
|
||||||
|
* Stops a running service.
|
||||||
|
*
|
||||||
|
* Stopping a service usually happens when the Service Control Manager instructs the service to
|
||||||
|
* stop. In some situations (e.g. fatal errors) the service may wish to stop itself. It can do so
|
||||||
|
* in a clean manner by calling this function.
|
||||||
|
*
|
||||||
|
* @param Service
|
||||||
|
* The service object.
|
||||||
|
* @return
|
||||||
|
* STATUS_SUCCESS on error code.
|
||||||
|
*/
|
||||||
|
FSP_API VOID FspServiceStop(FSP_SERVICE *Service);
|
||||||
|
/**
|
||||||
|
* Determine if the current process is running in user interactive mode.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* TRUE if the process is running in running user interactive mode.
|
||||||
|
*/
|
||||||
|
FSP_API BOOLEAN FspServiceIsInteractive(VOID);
|
||||||
|
/**
|
||||||
|
* Log a service message.
|
||||||
|
*
|
||||||
|
* This function can be used to log an arbitrary message to the Windows Event Log or to the current
|
||||||
|
* console if running in user interactive mode.
|
||||||
|
*
|
||||||
|
* @param Type
|
||||||
|
* One of EVENTLOG_INFORMATION_TYPE, EVENTLOG_WARNING_TYPE, EVENTLOG_ERROR_TYPE.
|
||||||
|
* @param Format
|
||||||
|
* Format specification. This function uses the Windows wsprintf API for formatting. Refer to
|
||||||
|
* that API's documentation for details on the format specification.
|
||||||
|
*/
|
||||||
|
FSP_API VOID FspServiceLog(ULONG Type, PWSTR Format, ...);
|
||||||
|
FSP_API VOID FspServiceLogV(ULONG Type, PWSTR Format, va_list ap);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Utility
|
* Utility
|
||||||
*/
|
*/
|
||||||
FSP_API NTSTATUS FspNtStatusFromWin32(DWORD Error);
|
FSP_API NTSTATUS FspNtStatusFromWin32(DWORD Error);
|
||||||
|
FSP_API DWORD FspWin32FromNtStatus(NTSTATUS Status);
|
||||||
|
FSP_API VOID FspEventLog(ULONG Type, PWSTR Format, ...);
|
||||||
|
FSP_API VOID FspEventLogV(ULONG Type, PWSTR Format, va_list ap);
|
||||||
FSP_API VOID FspDebugLog(const char *format, ...);
|
FSP_API VOID FspDebugLog(const char *format, ...);
|
||||||
FSP_API VOID FspDebugLogSD(const char *format, PSECURITY_DESCRIPTOR SecurityDescriptor);
|
FSP_API VOID FspDebugLogSD(const char *format, PSECURITY_DESCRIPTOR SecurityDescriptor);
|
||||||
FSP_API VOID FspDebugLogFT(const char *format, PFILETIME FileTime);
|
FSP_API VOID FspDebugLogFT(const char *format, PFILETIME FileTime);
|
||||||
|
FSP_API NTSTATUS FspCallNamedPipeSecurely(PWSTR PipeName,
|
||||||
|
PVOID InBuffer, ULONG InBufferSize, PVOID OutBuffer, ULONG OutBufferSize,
|
||||||
|
PULONG PBytesTransferred, ULONG Timeout,
|
||||||
|
PSID Sid);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
141
src/dll/eventlog.c
Normal file
141
src/dll/eventlog.c
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
/**
|
||||||
|
* @file dll/eventlog.c
|
||||||
|
*
|
||||||
|
* @copyright 2015-2016 Bill Zissimopoulos
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* This file is part of WinFsp.
|
||||||
|
*
|
||||||
|
* You can redistribute it and/or modify it under the terms of the
|
||||||
|
* GNU Affero General Public License version 3 as published by the
|
||||||
|
* Free Software Foundation.
|
||||||
|
*
|
||||||
|
* Licensees holding a valid commercial license may use this file in
|
||||||
|
* accordance with the commercial license agreement provided with the
|
||||||
|
* software.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <dll/library.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include "eventlog/eventlog.h"
|
||||||
|
|
||||||
|
#define FSP_EVENTLOG_NAME LIBRARY_NAME
|
||||||
|
|
||||||
|
static HANDLE FspEventLogHandle;
|
||||||
|
static INIT_ONCE FspEventLogInitOnce = INIT_ONCE_STATIC_INIT;
|
||||||
|
static BOOL WINAPI FspEventLogRegisterEventSource(
|
||||||
|
PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context);
|
||||||
|
|
||||||
|
VOID FspEventLogInitialize(BOOLEAN Dynamic)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID FspEventLogFinalize(BOOLEAN Dynamic)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This function is called during DLL_PROCESS_DETACH. We must therefore keep
|
||||||
|
* finalization tasks to a minimum.
|
||||||
|
*
|
||||||
|
* We must deregister our event source (if any). We only do so if the library
|
||||||
|
* is being explicitly unloaded (rather than the process exiting).
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (Dynamic && 0 != FspEventLogHandle)
|
||||||
|
DeregisterEventSource(FspEventLogHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API VOID FspEventLog(ULONG Type, PWSTR Format, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, Format);
|
||||||
|
FspEventLogV(Type, Format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API VOID FspEventLogV(ULONG Type, PWSTR Format, va_list ap)
|
||||||
|
{
|
||||||
|
InitOnceExecuteOnce(&FspEventLogInitOnce, FspEventLogRegisterEventSource, 0, 0);
|
||||||
|
if (0 == FspEventLogHandle)
|
||||||
|
return;
|
||||||
|
|
||||||
|
WCHAR Buf[1024], *Strings[1];
|
||||||
|
/* wvsprintfW is only safe with a 1024 WCHAR buffer */
|
||||||
|
DWORD EventId;
|
||||||
|
|
||||||
|
wvsprintfW(Buf, Format, ap);
|
||||||
|
Buf[(sizeof Buf / sizeof Buf[0]) - 1] = L'\0';
|
||||||
|
Strings[0] = Buf;
|
||||||
|
|
||||||
|
switch (Type)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
case EVENTLOG_INFORMATION_TYPE:
|
||||||
|
case EVENTLOG_SUCCESS:
|
||||||
|
EventId = FSP_EVENTLOG_INFORMATION;
|
||||||
|
break;
|
||||||
|
case EVENTLOG_WARNING_TYPE:
|
||||||
|
EventId = FSP_EVENTLOG_WARNING;
|
||||||
|
break;
|
||||||
|
case EVENTLOG_ERROR_TYPE:
|
||||||
|
EventId = FSP_EVENTLOG_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReportEventW(FspEventLogHandle, (WORD)Type, 0, EventId, 0, 1, 0, Strings, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL WINAPI FspEventLogRegisterEventSource(
|
||||||
|
PINIT_ONCE InitOnce, PVOID Parameter, PVOID *Context)
|
||||||
|
{
|
||||||
|
FspEventLogHandle = RegisterEventSourceW(0, L"" FSP_EVENTLOG_NAME);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS FspEventLogRegister(VOID)
|
||||||
|
{
|
||||||
|
extern HINSTANCE DllInstance;
|
||||||
|
WCHAR Path[MAX_PATH];
|
||||||
|
DWORD RegResult, DwordValue;
|
||||||
|
HKEY RegKey;
|
||||||
|
|
||||||
|
if (0 == GetModuleFileNameW(DllInstance, Path, MAX_PATH))
|
||||||
|
return FspNtStatusFromWin32(GetLastError());
|
||||||
|
|
||||||
|
RegResult = RegCreateKeyExW(
|
||||||
|
HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\System\\" FSP_EVENTLOG_NAME,
|
||||||
|
0, 0, 0, KEY_ALL_ACCESS, 0, &RegKey, 0);
|
||||||
|
if (ERROR_SUCCESS != RegResult)
|
||||||
|
return FspNtStatusFromWin32(RegResult);
|
||||||
|
|
||||||
|
RegResult = RegSetValueExW(RegKey,
|
||||||
|
L"EventMessageFile", 0, REG_SZ, (PVOID)Path, (lstrlenW(Path) + 1) * sizeof(WCHAR));
|
||||||
|
if (ERROR_SUCCESS != RegResult)
|
||||||
|
goto close_and_exit;
|
||||||
|
|
||||||
|
DwordValue = EVENTLOG_INFORMATION_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_ERROR_TYPE;
|
||||||
|
RegResult = RegSetValueExW(RegKey,
|
||||||
|
L"TypesSupported", 0, REG_DWORD, (PVOID)&DwordValue, sizeof DwordValue);
|
||||||
|
if (ERROR_SUCCESS != RegResult)
|
||||||
|
goto close_and_exit;
|
||||||
|
|
||||||
|
RegCloseKey(RegKey);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
|
close_and_exit:
|
||||||
|
RegCloseKey(RegKey);
|
||||||
|
return FspNtStatusFromWin32(RegResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS FspEventLogUnregister(VOID)
|
||||||
|
{
|
||||||
|
DWORD RegResult;
|
||||||
|
|
||||||
|
RegResult = RegDeleteTreeW(
|
||||||
|
HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\System\\" FSP_EVENTLOG_NAME);
|
||||||
|
if (ERROR_SUCCESS != RegResult && ERROR_FILE_NOT_FOUND != RegResult)
|
||||||
|
return FspNtStatusFromWin32(RegResult);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
63
src/dll/eventlog/eventlog.h
Normal file
63
src/dll/eventlog/eventlog.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
//
|
||||||
|
// Values are 32 bit values laid out as follows:
|
||||||
|
//
|
||||||
|
// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
|
||||||
|
// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
|
||||||
|
// +---+-+-+-----------------------+-------------------------------+
|
||||||
|
// |Sev|C|R| Facility | Code |
|
||||||
|
// +---+-+-+-----------------------+-------------------------------+
|
||||||
|
//
|
||||||
|
// where
|
||||||
|
//
|
||||||
|
// Sev - is the severity code
|
||||||
|
//
|
||||||
|
// 00 - Success
|
||||||
|
// 01 - Informational
|
||||||
|
// 10 - Warning
|
||||||
|
// 11 - Error
|
||||||
|
//
|
||||||
|
// C - is the Customer code flag
|
||||||
|
//
|
||||||
|
// R - is a reserved bit
|
||||||
|
//
|
||||||
|
// Facility - is the facility code
|
||||||
|
//
|
||||||
|
// Code - is the facility's status code
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Define the facility codes
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Define the severity codes
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// MessageId: FSP_EVENTLOG_INFORMATION
|
||||||
|
//
|
||||||
|
// MessageText:
|
||||||
|
//
|
||||||
|
// %1
|
||||||
|
//
|
||||||
|
#define FSP_EVENTLOG_INFORMATION 0x60000001L
|
||||||
|
|
||||||
|
//
|
||||||
|
// MessageId: FSP_EVENTLOG_WARNING
|
||||||
|
//
|
||||||
|
// MessageText:
|
||||||
|
//
|
||||||
|
// %1
|
||||||
|
//
|
||||||
|
#define FSP_EVENTLOG_WARNING 0xA0000001L
|
||||||
|
|
||||||
|
//
|
||||||
|
// MessageId: FSP_EVENTLOG_ERROR
|
||||||
|
//
|
||||||
|
// MessageText:
|
||||||
|
//
|
||||||
|
// %1
|
||||||
|
//
|
||||||
|
#define FSP_EVENTLOG_ERROR 0xE0000001L
|
||||||
|
|
20
src/dll/eventlog/eventlog.mc
Normal file
20
src/dll/eventlog/eventlog.mc
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
MessageId=1
|
||||||
|
Severity=Informational
|
||||||
|
SymbolicName=FSP_EVENTLOG_INFORMATION
|
||||||
|
Language=English
|
||||||
|
%1
|
||||||
|
.
|
||||||
|
|
||||||
|
MessageId=1
|
||||||
|
Severity=Warning
|
||||||
|
SymbolicName=FSP_EVENTLOG_WARNING
|
||||||
|
Language=English
|
||||||
|
%1
|
||||||
|
.
|
||||||
|
|
||||||
|
MessageId=1
|
||||||
|
Severity=Error
|
||||||
|
SymbolicName=FSP_EVENTLOG_ERROR
|
||||||
|
Language=English
|
||||||
|
%1
|
||||||
|
.
|
2
src/dll/eventlog/eventlog.rc
Normal file
2
src/dll/eventlog/eventlog.rc
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
LANGUAGE 0x9,0x1
|
||||||
|
1 11 "eventlog_MSG00001.bin"
|
BIN
src/dll/eventlog/eventlog_MSG00001.bin
Normal file
BIN
src/dll/eventlog/eventlog_MSG00001.bin
Normal file
Binary file not shown.
5
src/dll/eventlog/runmc.bat
Normal file
5
src/dll/eventlog/runmc.bat
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
call "%VS140COMNTOOLS%\..\..\VC\vcvarsall.bat"
|
||||||
|
|
||||||
|
mc -b -c eventlog.mc
|
23
src/dll/fs.c
23
src/dll/fs.c
@ -27,11 +27,11 @@ static FSP_FILE_SYSTEM_INTERFACE FspFileSystemNullInterface;
|
|||||||
static CRITICAL_SECTION FspFileSystemMountListGuard;
|
static CRITICAL_SECTION FspFileSystemMountListGuard;
|
||||||
static LIST_ENTRY FspFileSystemMountList = { &FspFileSystemMountList, &FspFileSystemMountList };
|
static LIST_ENTRY FspFileSystemMountList = { &FspFileSystemMountList, &FspFileSystemMountList };
|
||||||
|
|
||||||
VOID FspFileSystemInitialize(VOID)
|
VOID FspFileSystemInitialize(BOOLEAN Dynamic)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* This function is called during DLL_PROCESS_ATTACH. We must therefore keep initialization
|
* This function is called during DLL_PROCESS_ATTACH. We must therefore keep
|
||||||
* tasks to a minimum.
|
* initialization tasks to a minimum.
|
||||||
*
|
*
|
||||||
* Initialization of synchronization objects is allowed! See:
|
* Initialization of synchronization objects is allowed! See:
|
||||||
* https://msdn.microsoft.com/en-us/library/windows/desktop/dn633971(v=vs.85).aspx
|
* https://msdn.microsoft.com/en-us/library/windows/desktop/dn633971(v=vs.85).aspx
|
||||||
@ -40,16 +40,11 @@ VOID FspFileSystemInitialize(VOID)
|
|||||||
InitializeCriticalSection(&FspFileSystemMountListGuard);
|
InitializeCriticalSection(&FspFileSystemMountListGuard);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID FspFileSystemFinalize(VOID)
|
VOID FspFileSystemFinalize(BOOLEAN Dynamic)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* This function is called during DLL_PROCESS_DETACH. We must therefore keep finalization
|
* This function is called during DLL_PROCESS_DETACH. We must therefore keep
|
||||||
* tasks to a minimum.
|
* finalization tasks to a minimum.
|
||||||
*
|
|
||||||
* Very few things can be safely done during DLL_PROCESS_DETACH. See:
|
|
||||||
* https://msdn.microsoft.com/en-us/library/windows/desktop/dn633971(v=vs.85).aspx
|
|
||||||
* https://blogs.msdn.microsoft.com/oldnewthing/20070503-00/?p=27003/
|
|
||||||
* https://blogs.msdn.microsoft.com/oldnewthing/20100122-00/?p=15193/
|
|
||||||
*
|
*
|
||||||
* We enter our FspFileSystemMountListGuard critical section here and then attempt to cleanup
|
* We enter our FspFileSystemMountListGuard critical section here and then attempt to cleanup
|
||||||
* our mount points using DefineDosDeviceW. On Vista and later orphaned critical sections
|
* our mount points using DefineDosDeviceW. On Vista and later orphaned critical sections
|
||||||
@ -60,6 +55,9 @@ VOID FspFileSystemFinalize(VOID)
|
|||||||
* out to CSRSS, which is probably not the safest thing to do when in DllMain! There is also
|
* out to CSRSS, which is probably not the safest thing to do when in DllMain! There is also
|
||||||
* some evidence that it may attempt to load DLL's under some circumstances, which is a
|
* some evidence that it may attempt to load DLL's under some circumstances, which is a
|
||||||
* definite no-no as we are under the loader lock!
|
* definite no-no as we are under the loader lock!
|
||||||
|
*
|
||||||
|
* We only delete the criticaly section when being dynamically unloaded. On process exit the
|
||||||
|
* OS will clean it up for us.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
FSP_FILE_SYSTEM *FileSystem;
|
FSP_FILE_SYSTEM *FileSystem;
|
||||||
@ -79,6 +77,9 @@ VOID FspFileSystemFinalize(VOID)
|
|||||||
}
|
}
|
||||||
|
|
||||||
LeaveCriticalSection(&FspFileSystemMountListGuard);
|
LeaveCriticalSection(&FspFileSystemMountListGuard);
|
||||||
|
|
||||||
|
if (Dynamic)
|
||||||
|
DeleteCriticalSection(&FspFileSystemMountListGuard);
|
||||||
}
|
}
|
||||||
|
|
||||||
FSP_API NTSTATUS FspFileSystemCreate(PWSTR DevicePath,
|
FSP_API NTSTATUS FspFileSystemCreate(PWSTR DevicePath,
|
||||||
|
324
src/dll/fsctl.c
324
src/dll/fsctl.c
@ -16,11 +16,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <dll/library.h>
|
#include <dll/library.h>
|
||||||
|
#include <aclapi.h>
|
||||||
|
|
||||||
#define GLOBALROOT L"\\\\?\\GLOBALROOT"
|
#define GLOBALROOT L"\\\\?\\GLOBALROOT"
|
||||||
#define PREFIXW L"" FSP_FSCTL_VOLUME_PARAMS_PREFIX
|
#define PREFIXW L"" FSP_FSCTL_VOLUME_PARAMS_PREFIX
|
||||||
#define PREFIXW_SIZE (sizeof PREFIXW - sizeof(WCHAR))
|
#define PREFIXW_SIZE (sizeof PREFIXW - sizeof(WCHAR))
|
||||||
|
|
||||||
|
static NTSTATUS FspFsctlStartService(VOID);
|
||||||
|
|
||||||
FSP_API NTSTATUS FspFsctlCreateVolume(PWSTR DevicePath,
|
FSP_API NTSTATUS FspFsctlCreateVolume(PWSTR DevicePath,
|
||||||
const FSP_FSCTL_VOLUME_PARAMS *VolumeParams,
|
const FSP_FSCTL_VOLUME_PARAMS *VolumeParams,
|
||||||
PWCHAR VolumeNameBuf, SIZE_T VolumeNameSize,
|
PWCHAR VolumeNameBuf, SIZE_T VolumeNameSize,
|
||||||
@ -62,6 +65,10 @@ FSP_API NTSTATUS FspFsctlCreateVolume(PWSTR DevicePath,
|
|||||||
}
|
}
|
||||||
*DevicePathPtr = L'\0';
|
*DevicePathPtr = L'\0';
|
||||||
|
|
||||||
|
Result = FspFsctlStartService();
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
return Result;
|
||||||
|
|
||||||
VolumeHandle = CreateFileW(DevicePathBuf,
|
VolumeHandle = CreateFileW(DevicePathBuf,
|
||||||
0, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
|
0, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
|
||||||
if (INVALID_HANDLE_VALUE == VolumeHandle)
|
if (INVALID_HANDLE_VALUE == VolumeHandle)
|
||||||
@ -185,3 +192,320 @@ exit:
|
|||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NTSTATUS FspFsctlStartService(VOID)
|
||||||
|
{
|
||||||
|
PWSTR DriverName = L"" FSP_FSCTL_DRIVER_NAME;
|
||||||
|
SC_HANDLE ScmHandle = 0;
|
||||||
|
SC_HANDLE SvcHandle = 0;
|
||||||
|
SERVICE_STATUS ServiceStatus;
|
||||||
|
DWORD LastError;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
ScmHandle = OpenSCManagerW(0, 0, 0);
|
||||||
|
if (0 == ScmHandle)
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
SvcHandle = OpenServiceW(ScmHandle, DriverName, SERVICE_QUERY_STATUS | SERVICE_START);
|
||||||
|
if (0 == SvcHandle)
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!StartServiceW(SvcHandle, 0, 0))
|
||||||
|
{
|
||||||
|
LastError = GetLastError();
|
||||||
|
if (ERROR_SERVICE_ALREADY_RUNNING != LastError)
|
||||||
|
Result = FspNtStatusFromWin32(LastError);
|
||||||
|
else
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Poll until the service is running! Yes, that's the best we can do! */
|
||||||
|
Result = STATUS_DRIVER_UNABLE_TO_LOAD;
|
||||||
|
for (DWORD Timeout = 500, N = 20, I = 0; N > I; I++)
|
||||||
|
/* wait up to 500ms * 20 = 10000ms = 10s */
|
||||||
|
{
|
||||||
|
if (!QueryServiceStatus(SvcHandle, &ServiceStatus))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SERVICE_RUNNING == ServiceStatus.dwCurrentState)
|
||||||
|
{
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Sleep(Timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (0 != SvcHandle)
|
||||||
|
CloseServiceHandle(SvcHandle);
|
||||||
|
if (0 != ScmHandle)
|
||||||
|
CloseServiceHandle(ScmHandle);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS FspFsctlFixServiceSecurity(HANDLE SvcHandle)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This function adds an ACE that allows Everyone to start a service.
|
||||||
|
*/
|
||||||
|
|
||||||
|
PSID WorldSid = 0;
|
||||||
|
PSECURITY_DESCRIPTOR SecurityDescriptor = 0;
|
||||||
|
PSECURITY_DESCRIPTOR NewSecurityDescriptor = 0;
|
||||||
|
EXPLICIT_ACCESSW AccessEntry;
|
||||||
|
ACCESS_MASK AccessRights;
|
||||||
|
PACL Dacl;
|
||||||
|
BOOL DaclPresent, DaclDefaulted;
|
||||||
|
DWORD Size;
|
||||||
|
DWORD LastError;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
/* get the Everyone (World) SID */
|
||||||
|
Size = SECURITY_MAX_SID_SIZE;
|
||||||
|
WorldSid = MemAlloc(Size);
|
||||||
|
if (0 == WorldSid)
|
||||||
|
{
|
||||||
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (!CreateWellKnownSid(WinWorldSid, 0, WorldSid, &Size))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the service security descriptor DACL */
|
||||||
|
Size = 0;
|
||||||
|
if (!QueryServiceObjectSecurity(SvcHandle, DACL_SECURITY_INFORMATION, SecurityDescriptor, Size, &Size))
|
||||||
|
{
|
||||||
|
LastError = GetLastError();
|
||||||
|
if (ERROR_INSUFFICIENT_BUFFER != LastError)
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(LastError);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SecurityDescriptor = MemAlloc(Size);
|
||||||
|
if (0 == SecurityDescriptor)
|
||||||
|
{
|
||||||
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (!QueryServiceObjectSecurity(SvcHandle, DACL_SECURITY_INFORMATION, SecurityDescriptor, Size, &Size))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* extract the DACL */
|
||||||
|
if (!GetSecurityDescriptorDacl(SecurityDescriptor, &DaclPresent, &Dacl, &DaclDefaulted))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
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;
|
||||||
|
|
||||||
|
/* get the effective rights for Everyone */
|
||||||
|
AccessRights = 0;
|
||||||
|
if (DaclPresent && 0 != Dacl)
|
||||||
|
{
|
||||||
|
LastError = GetEffectiveRightsFromAclW(Dacl, &AccessEntry.Trustee, &AccessRights);
|
||||||
|
if (0 != LastError)
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(LastError);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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,
|
||||||
|
&Size, &NewSecurityDescriptor);
|
||||||
|
if (0 != LastError)
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(LastError);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set the new service security descriptor DACL */
|
||||||
|
if (!SetServiceObjectSecurity(SvcHandle, DACL_SECURITY_INFORMATION, NewSecurityDescriptor))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
LocalFree(NewSecurityDescriptor);
|
||||||
|
MemFree(SecurityDescriptor);
|
||||||
|
MemFree(WorldSid);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS FspFsctlRegister(VOID)
|
||||||
|
{
|
||||||
|
extern HINSTANCE DllInstance;
|
||||||
|
PWSTR DriverName = L"" FSP_FSCTL_DRIVER_NAME;
|
||||||
|
WCHAR DriverPath[MAX_PATH];
|
||||||
|
DWORD Size;
|
||||||
|
SC_HANDLE ScmHandle = 0;
|
||||||
|
SC_HANDLE SvcHandle = 0;
|
||||||
|
PVOID VersionInfo = 0;
|
||||||
|
SERVICE_DESCRIPTION ServiceDescription;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
if (0 == GetModuleFileNameW(DllInstance, DriverPath, MAX_PATH))
|
||||||
|
return FspNtStatusFromWin32(GetLastError());
|
||||||
|
|
||||||
|
Size = lstrlenW(DriverPath);
|
||||||
|
if (4 < Size &&
|
||||||
|
(L'.' == DriverPath[Size - 4]) &&
|
||||||
|
(L'D' == DriverPath[Size - 3] || L'd' == DriverPath[Size - 3]) &&
|
||||||
|
(L'L' == DriverPath[Size - 2] || L'l' == DriverPath[Size - 2]) &&
|
||||||
|
(L'L' == DriverPath[Size - 1] || L'l' == DriverPath[Size - 1]) &&
|
||||||
|
(L'\0' == DriverPath[Size]))
|
||||||
|
{
|
||||||
|
DriverPath[Size - 3] = L's';
|
||||||
|
DriverPath[Size - 2] = L'y';
|
||||||
|
DriverPath[Size - 1] = L's';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* should not happen! */
|
||||||
|
return STATUS_NO_SUCH_DEVICE;
|
||||||
|
|
||||||
|
ScmHandle = OpenSCManagerW(0, 0, SC_MANAGER_CREATE_SERVICE);
|
||||||
|
if (0 == ScmHandle)
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
SvcHandle = OpenServiceW(ScmHandle, DriverName, SERVICE_CHANGE_CONFIG | READ_CONTROL | WRITE_DAC);
|
||||||
|
if (0 != SvcHandle)
|
||||||
|
{
|
||||||
|
if (!ChangeServiceConfigW(SvcHandle,
|
||||||
|
SERVICE_FILE_SYSTEM_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, DriverPath,
|
||||||
|
0, 0, 0, 0, 0, DriverName))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SvcHandle = CreateServiceW(ScmHandle, DriverName, DriverName,
|
||||||
|
SERVICE_CHANGE_CONFIG | READ_CONTROL | WRITE_DAC,
|
||||||
|
SERVICE_FILE_SYSTEM_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, DriverPath,
|
||||||
|
0, 0, 0, 0, 0);
|
||||||
|
if (0 == SvcHandle)
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Size = GetFileVersionInfoSizeW(DriverPath, &Size/*dummy*/);
|
||||||
|
if (0 < Size)
|
||||||
|
{
|
||||||
|
VersionInfo = MemAlloc(Size);
|
||||||
|
if (0 != VersionInfo &&
|
||||||
|
GetFileVersionInfoW(DriverPath, 0, Size, VersionInfo) &&
|
||||||
|
VerQueryValueW(VersionInfo, L"\\StringFileInfo\\040904b0\\FileDescription",
|
||||||
|
&ServiceDescription.lpDescription, &Size))
|
||||||
|
{
|
||||||
|
ChangeServiceConfig2W(SvcHandle, SERVICE_CONFIG_DESCRIPTION, &ServiceDescription);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = FspFsctlFixServiceSecurity(SvcHandle);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
MemFree(VersionInfo);
|
||||||
|
if (0 != SvcHandle)
|
||||||
|
CloseServiceHandle(SvcHandle);
|
||||||
|
if (0 != ScmHandle)
|
||||||
|
CloseServiceHandle(ScmHandle);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS FspFsctlUnregister(VOID)
|
||||||
|
{
|
||||||
|
PWSTR DriverName = L"" FSP_FSCTL_DRIVER_NAME;
|
||||||
|
SC_HANDLE ScmHandle = 0;
|
||||||
|
SC_HANDLE SvcHandle = 0;
|
||||||
|
DWORD LastError;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
ScmHandle = OpenSCManagerW(0, 0, SC_MANAGER_CREATE_SERVICE);
|
||||||
|
/*
|
||||||
|
* The SC_MANAGER_CREATE_SERVICE access right is not strictly needed here,
|
||||||
|
* but we use it to enforce admin rights.
|
||||||
|
*/
|
||||||
|
if (0 == ScmHandle)
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
SvcHandle = OpenServiceW(ScmHandle, DriverName, DELETE);
|
||||||
|
if (0 == SvcHandle)
|
||||||
|
{
|
||||||
|
LastError = GetLastError();
|
||||||
|
if (ERROR_SERVICE_DOES_NOT_EXIST != LastError)
|
||||||
|
Result = FspNtStatusFromWin32(LastError);
|
||||||
|
else
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!DeleteService(SvcHandle))
|
||||||
|
{
|
||||||
|
LastError = GetLastError();
|
||||||
|
if (ERROR_SERVICE_MARKED_FOR_DELETE != LastError)
|
||||||
|
Result = FspNtStatusFromWin32(LastError);
|
||||||
|
else
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (0 != SvcHandle)
|
||||||
|
CloseServiceHandle(SvcHandle);
|
||||||
|
if (0 != ScmHandle)
|
||||||
|
CloseServiceHandle(ScmHandle);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
@ -304,7 +304,7 @@ static NTSTATUS FspFileSystemOpCreate_FileOpenTargetDirectory(FSP_FILE_SYSTEM *F
|
|||||||
UINT32 GrantedAccess;
|
UINT32 GrantedAccess;
|
||||||
PVOID FileNode;
|
PVOID FileNode;
|
||||||
FSP_FSCTL_FILE_INFO FileInfo;
|
FSP_FSCTL_FILE_INFO FileInfo;
|
||||||
UINT_PTR Information;
|
UINT32 Information;
|
||||||
|
|
||||||
Result = FspAccessCheck(FileSystem, Request, TRUE, TRUE,
|
Result = FspAccessCheck(FileSystem, Request, TRUE, TRUE,
|
||||||
Request->Req.Create.DesiredAccess, &GrantedAccess);
|
Request->Req.Create.DesiredAccess, &GrantedAccess);
|
||||||
|
@ -22,6 +22,8 @@ HANDLE ProcessHeap;
|
|||||||
|
|
||||||
BOOL WINAPI DllMain(HINSTANCE Instance, DWORD Reason, PVOID Reserved)
|
BOOL WINAPI DllMain(HINSTANCE Instance, DWORD Reason, PVOID Reserved)
|
||||||
{
|
{
|
||||||
|
BOOLEAN Dynamic;
|
||||||
|
|
||||||
switch (Reason)
|
switch (Reason)
|
||||||
{
|
{
|
||||||
case DLL_PROCESS_ATTACH:
|
case DLL_PROCESS_ATTACH:
|
||||||
@ -29,30 +31,68 @@ BOOL WINAPI DllMain(HINSTANCE Instance, DWORD Reason, PVOID Reserved)
|
|||||||
ProcessHeap = GetProcessHeap();
|
ProcessHeap = GetProcessHeap();
|
||||||
if (0 == ProcessHeap)
|
if (0 == ProcessHeap)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
FspFileSystemInitialize();
|
|
||||||
|
/*
|
||||||
|
* These functions are called during DLL_PROCESS_ATTACH. We must therefore keep
|
||||||
|
* initialization tasks to a minimum.
|
||||||
|
*
|
||||||
|
* See the DLL best practices document:
|
||||||
|
* https://msdn.microsoft.com/en-us/library/windows/desktop/dn633971(v=vs.85).aspx
|
||||||
|
*/
|
||||||
|
Dynamic = 0 == Reserved;
|
||||||
|
FspNtStatusInitialize(Dynamic);
|
||||||
|
FspEventLogInitialize(Dynamic);
|
||||||
|
FspFileSystemInitialize(Dynamic);
|
||||||
|
FspServiceInitialize(Dynamic);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DLL_PROCESS_DETACH:
|
case DLL_PROCESS_DETACH:
|
||||||
FspFileSystemFinalize();
|
/*
|
||||||
|
* These functions are called during DLL_PROCESS_DETACH. We must therefore keep
|
||||||
|
* finalization tasks to a minimum.
|
||||||
|
*
|
||||||
|
* See the following documents:
|
||||||
|
* https://msdn.microsoft.com/en-us/library/windows/desktop/dn633971(v=vs.85).aspx
|
||||||
|
* https://blogs.msdn.microsoft.com/oldnewthing/20070503-00/?p=27003/
|
||||||
|
* https://blogs.msdn.microsoft.com/oldnewthing/20100122-00/?p=15193/
|
||||||
|
*/
|
||||||
|
Dynamic = 0 == Reserved;
|
||||||
|
FspServiceFinalize(Dynamic);
|
||||||
|
FspFileSystemFinalize(Dynamic);
|
||||||
|
FspEventLogFinalize(Dynamic);
|
||||||
|
FspNtStatusFinalize(Dynamic);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* see comments in library.h */
|
/* see comments in shared/minimal.h */
|
||||||
#if defined(WINFSP_DLL_NODEFAULTLIB)
|
|
||||||
BOOL WINAPI _DllMainCRTStartup(HINSTANCE Instance, DWORD Reason, PVOID Reserved)
|
BOOL WINAPI _DllMainCRTStartup(HINSTANCE Instance, DWORD Reason, PVOID Reserved)
|
||||||
{
|
{
|
||||||
return DllMain(Instance, Reason, Reserved);
|
return DllMain(Instance, Reason, Reserved);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
HRESULT WINAPI DllRegisterServer(VOID)
|
HRESULT WINAPI DllRegisterServer(VOID)
|
||||||
{
|
{
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
Result = FspNpRegister();
|
Result = FspFsctlRegister();
|
||||||
|
FspDebugLog("FspFsctlRegister = %lx\n", Result);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
/* ignore errors below; these are non-critical */
|
||||||
|
|
||||||
|
Result = FspNpRegister();
|
||||||
|
FspDebugLog("FspNpRegister = %lx\n", Result);
|
||||||
|
|
||||||
|
Result = FspEventLogRegister();
|
||||||
|
FspDebugLog("FspEventLogRegister = %lx\n", Result);
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
return NT_SUCCESS(Result) ? S_OK : 0x80040201/*SELFREG_E_CLASS*/;
|
return NT_SUCCESS(Result) ? S_OK : 0x80040201/*SELFREG_E_CLASS*/;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,7 +100,21 @@ HRESULT WINAPI DllUnregisterServer(VOID)
|
|||||||
{
|
{
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
|
|
||||||
Result = FspNpUnregister();
|
Result = FspFsctlUnregister();
|
||||||
|
FspDebugLog("FspFsctlUnregister = %lx\n", Result);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
/* ignore errors below; these are non-critical */
|
||||||
|
|
||||||
|
Result = FspNpUnregister();
|
||||||
|
FspDebugLog("FspNpUnregister = %lx\n", Result);
|
||||||
|
|
||||||
|
Result = FspEventLogUnregister();
|
||||||
|
FspDebugLog("FspEventLogUnregister = %lx\n", Result);
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
return NT_SUCCESS(Result) ? S_OK : 0x80040201/*SELFREG_E_CLASS*/;
|
return NT_SUCCESS(Result) ? S_OK : 0x80040201/*SELFREG_E_CLASS*/;
|
||||||
}
|
}
|
||||||
|
@ -3,3 +3,9 @@ EXPORTS
|
|||||||
DllUnregisterServer PRIVATE
|
DllUnregisterServer PRIVATE
|
||||||
NPGetCaps PRIVATE
|
NPGetCaps PRIVATE
|
||||||
NPGetConnection PRIVATE
|
NPGetConnection PRIVATE
|
||||||
|
NPAddConnection PRIVATE
|
||||||
|
NPAddConnection3 PRIVATE
|
||||||
|
NPCancelConnection PRIVATE
|
||||||
|
NPOpenEnum PRIVATE
|
||||||
|
NPEnumResource PRIVATE
|
||||||
|
NPCloseEnum PRIVATE
|
||||||
|
@ -19,8 +19,8 @@
|
|||||||
#define WINFSP_DLL_LIBRARY_H_INCLUDED
|
#define WINFSP_DLL_LIBRARY_H_INCLUDED
|
||||||
|
|
||||||
#define WINFSP_DLL_INTERNAL
|
#define WINFSP_DLL_INTERNAL
|
||||||
#define WINFSP_DLL_NODEFAULTLIB
|
|
||||||
#include <winfsp/winfsp.h>
|
#include <winfsp/winfsp.h>
|
||||||
|
#include <shared/minimal.h>
|
||||||
#include <strsafe.h>
|
#include <strsafe.h>
|
||||||
|
|
||||||
#define LIBRARY_NAME "WinFsp"
|
#define LIBRARY_NAME "WinFsp"
|
||||||
@ -36,77 +36,20 @@
|
|||||||
#define DEBUGLOGSD(fmt, SD) ((void)0)
|
#define DEBUGLOGSD(fmt, SD) ((void)0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static inline PVOID MemAlloc(SIZE_T Size)
|
VOID FspNtStatusInitialize(BOOLEAN Dynamic);
|
||||||
{
|
VOID FspNtStatusFinalize(BOOLEAN Dynamic);
|
||||||
extern HANDLE ProcessHeap;
|
VOID FspEventLogInitialize(BOOLEAN Dynamic);
|
||||||
return HeapAlloc(ProcessHeap, 0, Size);
|
VOID FspEventLogFinalize(BOOLEAN Dynamic);
|
||||||
}
|
VOID FspFileSystemInitialize(BOOLEAN Dynamic);
|
||||||
static inline VOID MemFree(PVOID Pointer)
|
VOID FspFileSystemFinalize(BOOLEAN Dynamic);
|
||||||
{
|
VOID FspServiceInitialize(BOOLEAN Dynamic);
|
||||||
extern HANDLE ProcessHeap;
|
VOID FspServiceFinalize(BOOLEAN Dynamic);
|
||||||
if (0 != Pointer)
|
|
||||||
HeapFree(ProcessHeap, 0, Pointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Define WINFSP_DLL_NODEFAULTLIB to eliminate dependency on the MSVCRT libraries.
|
|
||||||
*
|
|
||||||
* For this to work the following project settings must be set:
|
|
||||||
* - "C/C++ > General > SDL checks" must be empty (not "Yes" or "No").
|
|
||||||
* - "C/C++ > Code Generation > Basic Runtime Checks" must be set to "Default"
|
|
||||||
* - "C/C++ > Code Generation > Security Check" must be disabled (/GS-).
|
|
||||||
* - "Linker > Input > Ignore All Default Libraries" must be "Yes".
|
|
||||||
*/
|
|
||||||
#if defined(WINFSP_DLL_NODEFAULTLIB)
|
|
||||||
#undef RtlFillMemory
|
|
||||||
#undef RtlMoveMemory
|
|
||||||
NTSYSAPI VOID NTAPI RtlFillMemory(VOID *Destination, DWORD Length, BYTE Fill);
|
|
||||||
NTSYSAPI VOID NTAPI RtlMoveMemory(VOID *Destination, CONST VOID *Source, DWORD Length);
|
|
||||||
|
|
||||||
#pragma function(memcpy)
|
|
||||||
#pragma function(memset)
|
|
||||||
static inline
|
|
||||||
void *memcpy(void *dst, const void *src, size_t siz)
|
|
||||||
{
|
|
||||||
RtlMoveMemory(dst, src, (DWORD)siz);
|
|
||||||
return dst;
|
|
||||||
}
|
|
||||||
static inline
|
|
||||||
void *memset(void *dst, int val, size_t siz)
|
|
||||||
{
|
|
||||||
RtlFillMemory(dst, (DWORD)siz, val);
|
|
||||||
return dst;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static FORCEINLINE
|
|
||||||
VOID InsertTailList(PLIST_ENTRY ListHead, PLIST_ENTRY Entry)
|
|
||||||
{
|
|
||||||
PLIST_ENTRY Blink;
|
|
||||||
|
|
||||||
Blink = ListHead->Blink;
|
|
||||||
Entry->Flink = ListHead;
|
|
||||||
Entry->Blink = Blink;
|
|
||||||
Blink->Flink = Entry;
|
|
||||||
ListHead->Blink = Entry;
|
|
||||||
}
|
|
||||||
static FORCEINLINE
|
|
||||||
BOOLEAN RemoveEntryList(PLIST_ENTRY Entry)
|
|
||||||
{
|
|
||||||
PLIST_ENTRY Blink;
|
|
||||||
PLIST_ENTRY Flink;
|
|
||||||
|
|
||||||
Flink = Entry->Flink;
|
|
||||||
Blink = Entry->Blink;
|
|
||||||
Blink->Flink = Flink;
|
|
||||||
Flink->Blink = Blink;
|
|
||||||
return Flink == Blink;
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID FspFileSystemInitialize(VOID);
|
|
||||||
VOID FspFileSystemFinalize(VOID);
|
|
||||||
|
|
||||||
|
NTSTATUS FspFsctlRegister(VOID);
|
||||||
|
NTSTATUS FspFsctlUnregister(VOID);
|
||||||
NTSTATUS FspNpRegister(VOID);
|
NTSTATUS FspNpRegister(VOID);
|
||||||
NTSTATUS FspNpUnregister(VOID);
|
NTSTATUS FspNpUnregister(VOID);
|
||||||
|
NTSTATUS FspEventLogRegister(VOID);
|
||||||
|
NTSTATUS FspEventLogUnregister(VOID);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
617
src/dll/np.c
617
src/dll/np.c
@ -16,12 +16,118 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <dll/library.h>
|
#include <dll/library.h>
|
||||||
|
#include <launcher/launcher.h>
|
||||||
|
#include <aclapi.h>
|
||||||
#include <npapi.h>
|
#include <npapi.h>
|
||||||
|
|
||||||
#define FSP_NP_NAME "WinFsp.Np"
|
#define FSP_NP_NAME LIBRARY_NAME ".Np"
|
||||||
#define FSP_NP_DESC "File System Proxy"
|
|
||||||
#define FSP_NP_TYPE ' spF' /* pick a value hopefully not in use */
|
#define FSP_NP_TYPE ' spF' /* pick a value hopefully not in use */
|
||||||
|
|
||||||
|
FSP_API NTSTATUS FspCallNamedPipeSecurely(PWSTR PipeName,
|
||||||
|
PVOID InBuffer, ULONG InBufferSize, PVOID OutBuffer, ULONG OutBufferSize,
|
||||||
|
PULONG PBytesTransferred, ULONG Timeout,
|
||||||
|
PSID Sid)
|
||||||
|
{
|
||||||
|
NTSTATUS Result;
|
||||||
|
HANDLE Pipe = INVALID_HANDLE_VALUE;
|
||||||
|
DWORD PipeMode;
|
||||||
|
|
||||||
|
Pipe = CreateFileW(PipeName,
|
||||||
|
GENERIC_READ | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING,
|
||||||
|
SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION, 0);
|
||||||
|
if (INVALID_HANDLE_VALUE == Pipe)
|
||||||
|
{
|
||||||
|
if (ERROR_PIPE_BUSY != GetLastError())
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
WaitNamedPipeW(PipeName, Timeout);
|
||||||
|
|
||||||
|
Pipe = CreateFileW(PipeName,
|
||||||
|
GENERIC_READ | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES,
|
||||||
|
FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING,
|
||||||
|
SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION, 0);
|
||||||
|
if (INVALID_HANDLE_VALUE == Pipe)
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != Sid)
|
||||||
|
{
|
||||||
|
PSECURITY_DESCRIPTOR SecurityDescriptor = 0;
|
||||||
|
PSID OwnerSid, WellKnownSid = 0;
|
||||||
|
DWORD SidSize, LastError;
|
||||||
|
|
||||||
|
/* if it is a small number treat it like a well known SID */
|
||||||
|
if (1024 > (INT_PTR)Sid)
|
||||||
|
{
|
||||||
|
SidSize = SECURITY_MAX_SID_SIZE;
|
||||||
|
WellKnownSid = MemAlloc(SidSize);
|
||||||
|
if (0 == WellKnownSid)
|
||||||
|
{
|
||||||
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto sid_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CreateWellKnownSid((INT_PTR)Sid, 0, WellKnownSid, &SidSize))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto sid_exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LastError = GetSecurityInfo(Pipe, SE_FILE_OBJECT,
|
||||||
|
OWNER_SECURITY_INFORMATION, &OwnerSid, 0, 0, 0, &SecurityDescriptor);
|
||||||
|
if (0 != LastError)
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto sid_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!EqualSid(OwnerSid, WellKnownSid ? WellKnownSid : Sid))
|
||||||
|
{
|
||||||
|
Result = STATUS_ACCESS_DENIED;
|
||||||
|
goto sid_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
sid_exit:
|
||||||
|
MemFree(WellKnownSid);
|
||||||
|
LocalFree(SecurityDescriptor);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
PipeMode = PIPE_READMODE_MESSAGE | PIPE_WAIT;
|
||||||
|
if (!SetNamedPipeHandleState(Pipe, &PipeMode, 0, 0))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!TransactNamedPipe(Pipe, InBuffer, InBufferSize, OutBuffer, OutBufferSize,
|
||||||
|
PBytesTransferred, 0))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (INVALID_HANDLE_VALUE != Pipe)
|
||||||
|
CloseHandle(Pipe);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
DWORD APIENTRY NPGetCaps(DWORD Index)
|
DWORD APIENTRY NPGetCaps(DWORD Index)
|
||||||
{
|
{
|
||||||
switch (Index)
|
switch (Index)
|
||||||
@ -34,14 +140,17 @@ DWORD APIENTRY NPGetCaps(DWORD Index)
|
|||||||
return 0;
|
return 0;
|
||||||
case WNNC_CONNECTION:
|
case WNNC_CONNECTION:
|
||||||
/*
|
/*
|
||||||
* WNNC_CON_ADDCONECTION
|
* WNNC_CON_ADDCONNECTION
|
||||||
* WNNC_CON_CANCELCONNECTION
|
* WNNC_CON_CANCELCONNECTION
|
||||||
* WNNC_CON_GETCONNECTIONS
|
* WNNC_CON_GETCONNECTIONS
|
||||||
* WNNC_CON_ADDCONECTION3
|
* WNNC_CON_ADDCONNECTION3
|
||||||
* WNNC_CON_GETPERFORMANCE
|
* WNNC_CON_GETPERFORMANCE
|
||||||
* WNNC_CON_DEFER
|
* WNNC_CON_DEFER
|
||||||
*/
|
*/
|
||||||
return WNNC_CON_GETCONNECTIONS;
|
return
|
||||||
|
WNNC_CON_GETCONNECTIONS |
|
||||||
|
WNNC_CON_ADDCONNECTION | WNNC_CON_ADDCONNECTION3 |
|
||||||
|
WNNC_CON_CANCELCONNECTION;
|
||||||
case WNNC_DIALOG:
|
case WNNC_DIALOG:
|
||||||
/*
|
/*
|
||||||
* WNNC_DLG_DEVICEMODE
|
* WNNC_DLG_DEVICEMODE
|
||||||
@ -59,7 +168,7 @@ DWORD APIENTRY NPGetCaps(DWORD Index)
|
|||||||
* WNNC_ENUM_LOCAL
|
* WNNC_ENUM_LOCAL
|
||||||
* WNNC_ENUM_CONTEXT
|
* WNNC_ENUM_CONTEXT
|
||||||
*/
|
*/
|
||||||
return 0;
|
return WNNC_ENUM_LOCAL | WNNC_ENUM_CONTEXT;
|
||||||
case WNNC_NET_TYPE:
|
case WNNC_NET_TYPE:
|
||||||
return FSP_NP_TYPE;
|
return FSP_NP_TYPE;
|
||||||
case WNNC_SPEC_VERSION:
|
case WNNC_SPEC_VERSION:
|
||||||
@ -76,6 +185,91 @@ DWORD APIENTRY NPGetCaps(DWORD Index)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline BOOLEAN FspNpCheckLocalName(PWSTR LocalName)
|
||||||
|
{
|
||||||
|
return 0 != LocalName &&
|
||||||
|
(
|
||||||
|
(L'A' <= LocalName[0] && LocalName[0] <= L'Z') ||
|
||||||
|
(L'a' <= LocalName[0] && LocalName[0] <= L'z')
|
||||||
|
) &&
|
||||||
|
L':' == LocalName[1] || L'\0' == LocalName[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline BOOLEAN FspNpCheckRemoteName(PWSTR RemoteName)
|
||||||
|
{
|
||||||
|
return 0 != RemoteName && L'\\' == RemoteName[0] && L'\\' == RemoteName[1] &&
|
||||||
|
sizeof(((FSP_FSCTL_VOLUME_PARAMS *)0)->Prefix) / sizeof(WCHAR) >= lstrlenW(RemoteName);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline BOOLEAN FspNpParseRemoteName(PWSTR RemoteName,
|
||||||
|
PWSTR *PClassName, PULONG PClassNameLen,
|
||||||
|
PWSTR *PInstanceName, PULONG PInstanceNameLen)
|
||||||
|
{
|
||||||
|
PWSTR ClassName, InstanceName, P;
|
||||||
|
ULONG ClassNameLen, InstanceNameLen;
|
||||||
|
|
||||||
|
ClassName = RemoteName + 2; /* skip \\ */
|
||||||
|
for (P = ClassName; *P; P++)
|
||||||
|
if (L'\\' == *P)
|
||||||
|
break;
|
||||||
|
if (ClassName == P || L'\\' != *P)
|
||||||
|
return FALSE;
|
||||||
|
ClassNameLen = (ULONG)(P - ClassName);
|
||||||
|
|
||||||
|
InstanceName = P + 1;
|
||||||
|
for (P = InstanceName; *P; P++)
|
||||||
|
;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (InstanceName == P)
|
||||||
|
return FALSE;
|
||||||
|
if (L'\\' != P[-1])
|
||||||
|
break;
|
||||||
|
P--;
|
||||||
|
}
|
||||||
|
InstanceNameLen = (ULONG)(P - InstanceName);
|
||||||
|
|
||||||
|
*PClassName = ClassName; *PClassNameLen = ClassNameLen;
|
||||||
|
*PInstanceName = InstanceName; *PInstanceNameLen = InstanceNameLen;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline DWORD FspNpCallLauncherPipe(PWSTR PipeBuf, ULONG SendSize, ULONG RecvSize)
|
||||||
|
{
|
||||||
|
DWORD NpResult;
|
||||||
|
NTSTATUS Result;
|
||||||
|
DWORD BytesTransferred;
|
||||||
|
|
||||||
|
Result = FspCallNamedPipeSecurely(L"" LAUNCHER_PIPE_NAME, PipeBuf, SendSize, PipeBuf, RecvSize,
|
||||||
|
&BytesTransferred, NMPWAIT_USE_DEFAULT_WAIT, LAUNCHER_PIPE_OWNER);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
NpResult = WN_NO_NETWORK;
|
||||||
|
else if (sizeof(WCHAR) > BytesTransferred)
|
||||||
|
NpResult = WN_NO_NETWORK;
|
||||||
|
else if (LauncherSuccess == PipeBuf[0])
|
||||||
|
NpResult = WN_SUCCESS;
|
||||||
|
else if (LauncherFailure == PipeBuf[0])
|
||||||
|
{
|
||||||
|
NpResult = 0;
|
||||||
|
for (PWSTR P = PipeBuf + 1, EndP = PipeBuf + BytesTransferred / sizeof(WCHAR); EndP > P; P++)
|
||||||
|
{
|
||||||
|
if (L'0' > *P || *P > L'9')
|
||||||
|
break;
|
||||||
|
|
||||||
|
NpResult = 10 * NpResult + (*P - L'0');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == NpResult)
|
||||||
|
NpResult = WN_NO_NETWORK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
NpResult = WN_NO_NETWORK;
|
||||||
|
|
||||||
|
return NpResult;
|
||||||
|
}
|
||||||
|
|
||||||
static NTSTATUS FspNpGetVolumeList(
|
static NTSTATUS FspNpGetVolumeList(
|
||||||
PWCHAR *PVolumeListBuf, PSIZE_T PVolumeListSize)
|
PWCHAR *PVolumeListBuf, PSIZE_T PVolumeListSize)
|
||||||
{
|
{
|
||||||
@ -108,7 +302,37 @@ static NTSTATUS FspNpGetVolumeList(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD APIENTRY NPGetConnection(LPWSTR lpLocalName, LPWSTR lpRemoteName, LPDWORD lpnBufferLen)
|
static WCHAR FspNpGetDriveLetter(PDWORD PLogicalDrives, PWSTR VolumeName)
|
||||||
|
{
|
||||||
|
WCHAR VolumeNameBuf[MAX_PATH];
|
||||||
|
WCHAR LocalNameBuf[3];
|
||||||
|
WCHAR Drive;
|
||||||
|
|
||||||
|
if (0 == *PLogicalDrives)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
LocalNameBuf[1] = L':';
|
||||||
|
LocalNameBuf[2] = L'\0';
|
||||||
|
|
||||||
|
for (Drive = 'Z'; 'A' <= Drive; Drive--)
|
||||||
|
if (0 != (*PLogicalDrives & (1 << (Drive - 'A'))))
|
||||||
|
{
|
||||||
|
LocalNameBuf[0] = Drive;
|
||||||
|
if (QueryDosDeviceW(LocalNameBuf, VolumeNameBuf, sizeof VolumeNameBuf / sizeof(WCHAR)))
|
||||||
|
{
|
||||||
|
if (0 == lstrcmpW(VolumeNameBuf, VolumeName))
|
||||||
|
{
|
||||||
|
*PLogicalDrives &= ~(1 << (Drive - 'A'));
|
||||||
|
return Drive;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD APIENTRY NPGetConnection(
|
||||||
|
LPWSTR lpLocalName, LPWSTR lpRemoteName, LPDWORD lpnBufferLen)
|
||||||
{
|
{
|
||||||
DWORD NpResult;
|
DWORD NpResult;
|
||||||
NTSTATUS Result;
|
NTSTATUS Result;
|
||||||
@ -118,15 +342,10 @@ DWORD APIENTRY NPGetConnection(LPWSTR lpLocalName, LPWSTR lpRemoteName, LPDWORD
|
|||||||
SIZE_T VolumeListSize, VolumeNameSize;
|
SIZE_T VolumeListSize, VolumeNameSize;
|
||||||
ULONG Backslashes;
|
ULONG Backslashes;
|
||||||
|
|
||||||
if (0 == lpLocalName ||
|
if (!FspNpCheckLocalName(lpLocalName))
|
||||||
!(
|
|
||||||
(L'A' <= lpLocalName[0] && lpLocalName[0] <= L'Z') ||
|
|
||||||
(L'a' <= lpLocalName[0] && lpLocalName[0] <= L'z')
|
|
||||||
) ||
|
|
||||||
L':' != lpLocalName[1])
|
|
||||||
return WN_BAD_LOCALNAME;
|
return WN_BAD_LOCALNAME;
|
||||||
|
|
||||||
LocalNameBuf[0] = lpLocalName[0];
|
LocalNameBuf[0] = lpLocalName[0] & ~0x20; /* convert to uppercase */
|
||||||
LocalNameBuf[1] = L':';
|
LocalNameBuf[1] = L':';
|
||||||
LocalNameBuf[2] = L'\0';
|
LocalNameBuf[2] = L'\0';
|
||||||
|
|
||||||
@ -189,6 +408,351 @@ DWORD APIENTRY NPGetConnection(LPWSTR lpLocalName, LPWSTR lpRemoteName, LPDWORD
|
|||||||
return NpResult;
|
return NpResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 dwType = lpNetResource->dwType;
|
||||||
|
LPWSTR lpRemoteName = lpNetResource->lpRemoteName;
|
||||||
|
LPWSTR lpLocalName = lpNetResource->lpLocalName;
|
||||||
|
WCHAR LocalNameBuf[3];
|
||||||
|
PWSTR ClassName, InstanceName, RemoteName, P;
|
||||||
|
ULONG ClassNameLen, InstanceNameLen;
|
||||||
|
PWSTR PipeBuf = 0;
|
||||||
|
|
||||||
|
if (dwType & RESOURCETYPE_PRINT)
|
||||||
|
return WN_BAD_VALUE;
|
||||||
|
|
||||||
|
if (!FspNpCheckRemoteName(lpRemoteName))
|
||||||
|
return WN_BAD_NETNAME;
|
||||||
|
|
||||||
|
if (!FspNpParseRemoteName(lpRemoteName,
|
||||||
|
&ClassName, &ClassNameLen, &InstanceName, &InstanceNameLen))
|
||||||
|
return WN_BAD_NETNAME;
|
||||||
|
RemoteName = lpRemoteName + 1;
|
||||||
|
|
||||||
|
LocalNameBuf[0] = L'\0';
|
||||||
|
if (0 != lpLocalName && L'\0' != lpLocalName[0])
|
||||||
|
{
|
||||||
|
if (!FspNpCheckLocalName(lpLocalName))
|
||||||
|
return WN_BAD_LOCALNAME;
|
||||||
|
|
||||||
|
LocalNameBuf[0] = lpLocalName[0] & ~0x20; /* convert to uppercase */
|
||||||
|
LocalNameBuf[1] = L':';
|
||||||
|
LocalNameBuf[2] = L'\0';
|
||||||
|
|
||||||
|
if (GetLogicalDrives() & (1 << (LocalNameBuf[0] - 'A')))
|
||||||
|
return WN_ALREADY_CONNECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
PipeBuf = MemAlloc(LAUNCHER_PIPE_BUFFER_SIZE);
|
||||||
|
if (0 == PipeBuf)
|
||||||
|
return WN_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
P = PipeBuf;
|
||||||
|
*P++ = LauncherSvcInstanceStart;
|
||||||
|
memcpy(P, ClassName, ClassNameLen * sizeof(WCHAR)); P += ClassNameLen; *P++ = L'\0';
|
||||||
|
memcpy(P, InstanceName, InstanceNameLen * sizeof(WCHAR)); P += InstanceNameLen; *P++ = L'\0';
|
||||||
|
lstrcpyW(P, RemoteName); P += lstrlenW(RemoteName) + 1;
|
||||||
|
lstrcpyW(P, LocalNameBuf); P += lstrlenW(LocalNameBuf) + 1;
|
||||||
|
|
||||||
|
NpResult = FspNpCallLauncherPipe(
|
||||||
|
PipeBuf, (ULONG)(P - PipeBuf) * sizeof(WCHAR), LAUNCHER_PIPE_BUFFER_SIZE);
|
||||||
|
switch (NpResult)
|
||||||
|
{
|
||||||
|
case WN_SUCCESS:
|
||||||
|
break;
|
||||||
|
case ERROR_ALREADY_EXISTS:
|
||||||
|
/*
|
||||||
|
* The file system is already running! If we are being asked for a drive mapping,
|
||||||
|
* see if it is the one we already have to decide on the error code to return.
|
||||||
|
*/
|
||||||
|
if (L'\0' != LocalNameBuf[0])
|
||||||
|
{
|
||||||
|
WCHAR ExpectRemoteNameBuf[sizeof(((FSP_FSCTL_VOLUME_PARAMS *)0)->Prefix) / sizeof(WCHAR)];
|
||||||
|
WCHAR RemoteNameBuf[sizeof(((FSP_FSCTL_VOLUME_PARAMS *)0)->Prefix) / sizeof(WCHAR)];
|
||||||
|
DWORD RemoteNameSize;
|
||||||
|
|
||||||
|
P = ExpectRemoteNameBuf;
|
||||||
|
*P++ = L'\\'; *P++ = L'\\';
|
||||||
|
memcpy(P, ClassName, ClassNameLen * sizeof(WCHAR)); P += ClassNameLen; *P++ = L'\\';
|
||||||
|
memcpy(P, InstanceName, InstanceNameLen * sizeof(WCHAR)); P += InstanceNameLen; *P++ = L'\0';
|
||||||
|
|
||||||
|
RemoteNameSize = sizeof RemoteNameBuf / sizeof(WCHAR);
|
||||||
|
NpResult = NPGetConnection(LocalNameBuf, RemoteNameBuf, &RemoteNameSize);
|
||||||
|
if (WN_SUCCESS == NpResult)
|
||||||
|
NpResult = 0 == lstrcmpW(ExpectRemoteNameBuf, RemoteNameBuf) ? WN_SUCCESS : WN_NO_NETWORK;
|
||||||
|
else
|
||||||
|
NpResult = WN_NO_NETWORK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* we are not being asked for a drive mapping, so whatever we have is good! */
|
||||||
|
NpResult = WN_SUCCESS;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
NpResult = WN_NO_NETWORK;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
MemFree(PipeBuf);
|
||||||
|
|
||||||
|
return NpResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD APIENTRY NPCancelConnection(LPWSTR lpName, BOOL fForce)
|
||||||
|
{
|
||||||
|
DWORD NpResult;
|
||||||
|
WCHAR RemoteNameBuf[sizeof(((FSP_FSCTL_VOLUME_PARAMS *)0)->Prefix) / sizeof(WCHAR)];
|
||||||
|
DWORD RemoteNameSize;
|
||||||
|
PWSTR ClassName, InstanceName, RemoteName, P;
|
||||||
|
ULONG ClassNameLen, InstanceNameLen;
|
||||||
|
PWSTR PipeBuf = 0;
|
||||||
|
|
||||||
|
if (FspNpCheckLocalName(lpName))
|
||||||
|
{
|
||||||
|
RemoteNameSize = sizeof RemoteNameBuf / sizeof(WCHAR);
|
||||||
|
NpResult = NPGetConnection(lpName, RemoteNameBuf, &RemoteNameSize);
|
||||||
|
if (WN_SUCCESS != NpResult)
|
||||||
|
return NpResult;
|
||||||
|
|
||||||
|
RemoteName = RemoteNameBuf;
|
||||||
|
}
|
||||||
|
else if (FspNpCheckRemoteName(lpName))
|
||||||
|
RemoteName = lpName;
|
||||||
|
else
|
||||||
|
return WN_BAD_NETNAME;
|
||||||
|
|
||||||
|
if (!FspNpParseRemoteName(RemoteName,
|
||||||
|
&ClassName, &ClassNameLen, &InstanceName, &InstanceNameLen))
|
||||||
|
return WN_BAD_NETNAME;
|
||||||
|
|
||||||
|
PipeBuf = MemAlloc(LAUNCHER_PIPE_BUFFER_SIZE);
|
||||||
|
if (0 == PipeBuf)
|
||||||
|
return WN_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
P = PipeBuf;
|
||||||
|
*P++ = LauncherSvcInstanceStop;
|
||||||
|
memcpy(P, ClassName, ClassNameLen * sizeof(WCHAR)); P += ClassNameLen; *P++ = L'\0';
|
||||||
|
memcpy(P, InstanceName, InstanceNameLen * sizeof(WCHAR)); P += InstanceNameLen; *P++ = L'\0';
|
||||||
|
|
||||||
|
NpResult = FspNpCallLauncherPipe(
|
||||||
|
PipeBuf, (ULONG)(P - PipeBuf) * sizeof(WCHAR), LAUNCHER_PIPE_BUFFER_SIZE);
|
||||||
|
switch (NpResult)
|
||||||
|
{
|
||||||
|
case WN_SUCCESS:
|
||||||
|
break;
|
||||||
|
case ERROR_FILE_NOT_FOUND:
|
||||||
|
NpResult = WN_NOT_CONNECTED;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
NpResult = WN_NO_NETWORK;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
MemFree(PipeBuf);
|
||||||
|
|
||||||
|
return NpResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
DWORD Signature; /* cheap and cheerful! */
|
||||||
|
DWORD dwScope;
|
||||||
|
PWCHAR VolumeListBuf, VolumeListBufEnd, VolumeName;
|
||||||
|
DWORD LogicalDrives;
|
||||||
|
} FSP_NP_ENUM;
|
||||||
|
|
||||||
|
static inline BOOLEAN FspNpValidateEnum(FSP_NP_ENUM *Enum)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
extern HANDLE ProcessHeap;
|
||||||
|
return
|
||||||
|
0 != Enum &&
|
||||||
|
HeapValidate(ProcessHeap, 0, Enum) &&
|
||||||
|
'munE' == Enum->Signature;
|
||||||
|
#else
|
||||||
|
return
|
||||||
|
0 != Enum &&
|
||||||
|
'munE' == Enum->Signature;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD APIENTRY NPOpenEnum(
|
||||||
|
DWORD dwScope, DWORD dwType, DWORD dwUsage, LPNETRESOURCEW lpNetResource, LPHANDLE lphEnum)
|
||||||
|
{
|
||||||
|
NTSTATUS Result;
|
||||||
|
FSP_NP_ENUM *Enum = 0;
|
||||||
|
SIZE_T VolumeListSize;
|
||||||
|
|
||||||
|
switch (dwScope)
|
||||||
|
{
|
||||||
|
case RESOURCE_CONNECTED:
|
||||||
|
case RESOURCE_CONTEXT:
|
||||||
|
/* ignore lpNetResource; according to documentation it should be NULL */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return WN_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dwType & RESOURCETYPE_PRINT)
|
||||||
|
return WN_BAD_VALUE;
|
||||||
|
|
||||||
|
Enum = MemAlloc(sizeof *Enum);
|
||||||
|
if (0 == Enum)
|
||||||
|
return WN_OUT_OF_MEMORY;
|
||||||
|
|
||||||
|
Result = FspNpGetVolumeList(&Enum->VolumeListBuf, &VolumeListSize);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
MemFree(Enum);
|
||||||
|
return WN_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
Enum->Signature = 'munE';
|
||||||
|
Enum->dwScope = dwScope;
|
||||||
|
Enum->VolumeListBufEnd = (PVOID)((PUINT8)Enum->VolumeListBuf + VolumeListSize);
|
||||||
|
Enum->VolumeName = Enum->VolumeListBuf;
|
||||||
|
Enum->LogicalDrives = GetLogicalDrives();
|
||||||
|
|
||||||
|
*lphEnum = Enum;
|
||||||
|
|
||||||
|
return WN_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD APIENTRY NPEnumResource(
|
||||||
|
HANDLE hEnum, LPDWORD lpcCount, LPVOID lpBuffer, LPDWORD lpBufferSize)
|
||||||
|
{
|
||||||
|
FSP_NP_ENUM *Enum = hEnum;
|
||||||
|
DWORD NpResult;
|
||||||
|
LPNETRESOURCEW Resource; /* grows upwards */
|
||||||
|
PWCHAR Strings; /* grows downwards */
|
||||||
|
PWCHAR ProviderName = 0;
|
||||||
|
DWORD Count;
|
||||||
|
PWCHAR P, VolumePrefix;
|
||||||
|
ULONG Backslashes;
|
||||||
|
WCHAR Drive;
|
||||||
|
|
||||||
|
if (!FspNpValidateEnum(Enum))
|
||||||
|
return WN_BAD_HANDLE;
|
||||||
|
|
||||||
|
if (0 == lpcCount || 0 == lpBuffer || 0 == lpBufferSize)
|
||||||
|
return WN_BAD_VALUE;
|
||||||
|
|
||||||
|
Resource = lpBuffer;
|
||||||
|
Strings = (PVOID)((PUINT8)lpBuffer + (*lpBufferSize & ~1/* WCHAR alignment */));
|
||||||
|
Count = 0;
|
||||||
|
for (P = Enum->VolumeName; *lpcCount > Count && Enum->VolumeListBufEnd > P; P++)
|
||||||
|
{
|
||||||
|
if (L'\0' == *P)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Extract the VolumePrefix from the VolumeName.
|
||||||
|
*
|
||||||
|
* The VolumeName will have the following syntax:
|
||||||
|
* \Device\Volume{GUID}\Server\Share
|
||||||
|
*
|
||||||
|
* We want to extract the \Server\Share part. We will simply count backslashes and
|
||||||
|
* stop at the third one.
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (Backslashes = 0, VolumePrefix = Enum->VolumeName; VolumePrefix < P; VolumePrefix++)
|
||||||
|
if (L'\\' == *VolumePrefix)
|
||||||
|
if (3 == ++Backslashes)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (3 == Backslashes)
|
||||||
|
{
|
||||||
|
Drive = FspNpGetDriveLetter(&Enum->LogicalDrives, Enum->VolumeName);
|
||||||
|
|
||||||
|
Strings -= (Drive ? 3 : 0) + 2/* backslash + term-0 */ + lstrlenW(VolumePrefix) +
|
||||||
|
(0 == ProviderName ? lstrlenW(L"" FSP_NP_NAME) + 1 : 0);
|
||||||
|
|
||||||
|
if ((PVOID)(Resource + 1) > (PVOID)Strings)
|
||||||
|
{
|
||||||
|
if (0 == Count)
|
||||||
|
{
|
||||||
|
*lpBufferSize =
|
||||||
|
(DWORD)((PUINT8)(Resource + 1) - (PUINT8)lpBuffer) +
|
||||||
|
(DWORD)((PUINT8)lpBuffer + *lpBufferSize - (PUINT8)Strings);
|
||||||
|
NpResult = WN_MORE_DATA;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*lpcCount = Count;
|
||||||
|
NpResult = WN_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == ProviderName)
|
||||||
|
{
|
||||||
|
ProviderName = Strings + (Drive ? 3 : 0) + 2/* backslash + term-0 */ + lstrlenW(VolumePrefix);
|
||||||
|
lstrcpyW(ProviderName, L"" FSP_NP_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Drive)
|
||||||
|
{
|
||||||
|
Strings[0] = Drive;
|
||||||
|
Strings[1] = L':';
|
||||||
|
Strings[2] = L'\0';
|
||||||
|
|
||||||
|
Strings[3] = L'\\';
|
||||||
|
lstrcpyW(Strings + 4, VolumePrefix);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Strings[0] = L'\\';
|
||||||
|
lstrcpyW(Strings + 1, VolumePrefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
Resource->dwScope = Enum->dwScope;
|
||||||
|
Resource->dwType = RESOURCETYPE_DISK;
|
||||||
|
Resource->dwDisplayType = RESOURCEDISPLAYTYPE_SHARE;
|
||||||
|
Resource->dwUsage = RESOURCEUSAGE_CONNECTABLE;
|
||||||
|
Resource->lpLocalName = Drive ? Strings : 0;
|
||||||
|
Resource->lpRemoteName = Drive ? Strings + 3 : Strings;
|
||||||
|
Resource->lpComment = 0;
|
||||||
|
Resource->lpProvider = ProviderName;
|
||||||
|
Resource++;
|
||||||
|
|
||||||
|
Count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Enum->VolumeName = P + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == Count)
|
||||||
|
NpResult = WN_NO_MORE_ENTRIES;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*lpcCount = Count;
|
||||||
|
NpResult = WN_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return NpResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD APIENTRY NPCloseEnum(HANDLE hEnum)
|
||||||
|
{
|
||||||
|
FSP_NP_ENUM *Enum = hEnum;
|
||||||
|
|
||||||
|
if (!FspNpValidateEnum(Enum))
|
||||||
|
return WN_BAD_HANDLE;
|
||||||
|
|
||||||
|
MemFree(Enum->VolumeListBuf);
|
||||||
|
MemFree(Enum);
|
||||||
|
|
||||||
|
return WN_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS FspNpRegister(VOID)
|
NTSTATUS FspNpRegister(VOID)
|
||||||
{
|
{
|
||||||
extern HINSTANCE DllInstance;
|
extern HINSTANCE DllInstance;
|
||||||
@ -221,8 +785,29 @@ NTSTATUS FspNpRegister(VOID)
|
|||||||
if (ERROR_SUCCESS != RegResult)
|
if (ERROR_SUCCESS != RegResult)
|
||||||
return FspNtStatusFromWin32(RegResult);
|
return FspNtStatusFromWin32(RegResult);
|
||||||
|
|
||||||
RegResult = RegSetValueExW(RegKey,
|
RegResult = ERROR_RESOURCE_NAME_NOT_FOUND; /* not a real resource error! */
|
||||||
L"Name", 0, REG_SZ, (PVOID) L"" FSP_NP_DESC, sizeof L"" FSP_NP_DESC);
|
{
|
||||||
|
PVOID VersionInfo = 0;
|
||||||
|
DWORD Size;
|
||||||
|
PWSTR Description;
|
||||||
|
|
||||||
|
Size = GetFileVersionInfoSizeW(ProviderPath, &Size/*dummy*/);
|
||||||
|
if (0 < Size)
|
||||||
|
{
|
||||||
|
VersionInfo = MemAlloc(Size);
|
||||||
|
if (0 != VersionInfo &&
|
||||||
|
GetFileVersionInfoW(ProviderPath, 0, Size, VersionInfo) &&
|
||||||
|
VerQueryValueW(VersionInfo, L"\\StringFileInfo\\040904b0\\FileDescription",
|
||||||
|
&Description, &Size))
|
||||||
|
{
|
||||||
|
Size = Size * 2 + sizeof(WCHAR);
|
||||||
|
RegResult = RegSetValueExW(RegKey,
|
||||||
|
L"Name", 0, REG_SZ, (PVOID)Description, Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
MemFree(VersionInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (ERROR_SUCCESS != RegResult)
|
if (ERROR_SUCCESS != RegResult)
|
||||||
goto close_and_exit;
|
goto close_and_exit;
|
||||||
|
|
||||||
|
@ -17,6 +17,29 @@
|
|||||||
|
|
||||||
#include <dll/library.h>
|
#include <dll/library.h>
|
||||||
|
|
||||||
|
static ULONG (WINAPI *FspRtlNtStatusToDosError)(NTSTATUS Status);
|
||||||
|
|
||||||
|
VOID FspNtStatusInitialize(BOOLEAN Dynamic)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This function is called during DLL_PROCESS_ATTACH. We must therefore keep
|
||||||
|
* initialization tasks to a minimum.
|
||||||
|
*
|
||||||
|
* GetModuleHandle/GetProcAddress is allowed (because they are kernel32 API's)! See:
|
||||||
|
* https://msdn.microsoft.com/en-us/library/windows/desktop/dn633971(v=vs.85).aspx
|
||||||
|
*/
|
||||||
|
|
||||||
|
HANDLE Handle;
|
||||||
|
|
||||||
|
Handle = GetModuleHandleW(L"ntdll.dll");
|
||||||
|
if (0 != Handle)
|
||||||
|
FspRtlNtStatusToDosError = (PVOID)GetProcAddress(Handle, "RtlNtStatusToDosError");
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID FspNtStatusFinalize(BOOLEAN Dynamic)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
FSP_API NTSTATUS FspNtStatusFromWin32(DWORD Error)
|
FSP_API NTSTATUS FspNtStatusFromWin32(DWORD Error)
|
||||||
{
|
{
|
||||||
switch (Error)
|
switch (Error)
|
||||||
@ -26,3 +49,11 @@ FSP_API NTSTATUS FspNtStatusFromWin32(DWORD Error)
|
|||||||
return STATUS_ACCESS_DENIED;
|
return STATUS_ACCESS_DENIED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FSP_API DWORD FspWin32FromNtStatus(NTSTATUS Status)
|
||||||
|
{
|
||||||
|
if (0 == FspRtlNtStatusToDosError)
|
||||||
|
return ERROR_MR_MID_NOT_FOUND;
|
||||||
|
|
||||||
|
return FspRtlNtStatusToDosError(Status);
|
||||||
|
}
|
||||||
|
607
src/dll/service.c
Normal file
607
src/dll/service.c
Normal file
@ -0,0 +1,607 @@
|
|||||||
|
/**
|
||||||
|
* @file dll/service.c
|
||||||
|
*
|
||||||
|
* @copyright 2015-2016 Bill Zissimopoulos
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* This file is part of WinFsp.
|
||||||
|
*
|
||||||
|
* You can redistribute it and/or modify it under the terms of the
|
||||||
|
* GNU Affero General Public License version 3 as published by the
|
||||||
|
* Free Software Foundation.
|
||||||
|
*
|
||||||
|
* Licensees holding a valid commercial license may use this file in
|
||||||
|
* accordance with the commercial license agreement provided with the
|
||||||
|
* software.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <dll/library.h>
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
SetStatus_ServiceType = 0x0001,
|
||||||
|
SetStatus_CurrentState = 0x0002,
|
||||||
|
SetStatus_ControlsAccepted = 0x0004,
|
||||||
|
SetStatus_Win32ExitCode = 0x0008,
|
||||||
|
SetStatus_ServiceSpecificExitCode = 0x0010,
|
||||||
|
SetStatus_CheckPoint = 0x0020,
|
||||||
|
SetStatus_WaitHint = 0x0040,
|
||||||
|
AddStatus_CheckPoint = 0x0080,
|
||||||
|
GetStatus_ServiceType = 0x0100,
|
||||||
|
GetStatus_CurrentState = 0x0200,
|
||||||
|
GetStatus_ControlsAccepted = 0x0400,
|
||||||
|
GetStatus_Win32ExitCode = 0x0800,
|
||||||
|
GetStatus_ServiceSpecificExitCode = 0x1000,
|
||||||
|
GetStatus_CheckPoint = 0x2000,
|
||||||
|
GetStatus_WaitHint = 0x4000,
|
||||||
|
};
|
||||||
|
|
||||||
|
static SERVICE_TABLE_ENTRYW *FspServiceTable;
|
||||||
|
static HANDLE FspServiceConsoleModeEvent;
|
||||||
|
static UINT32 FspServiceConsoleCtrlHandlerDisabled;
|
||||||
|
|
||||||
|
static VOID FspServiceSetStatus(FSP_SERVICE *Service, ULONG Flags, SERVICE_STATUS *ServiceStatus);
|
||||||
|
static VOID WINAPI FspServiceEntry(DWORD Argc, PWSTR *Argv);
|
||||||
|
static VOID FspServiceMain(FSP_SERVICE *Service, DWORD Argc, PWSTR *Argv);
|
||||||
|
static DWORD WINAPI FspServiceCtrlHandler(
|
||||||
|
DWORD Control, DWORD EventType, PVOID EventData, PVOID Context);
|
||||||
|
static DWORD WINAPI FspServiceConsoleModeThread(PVOID Context);
|
||||||
|
static BOOL WINAPI FspServiceConsoleCtrlHandler(DWORD CtrlType);
|
||||||
|
|
||||||
|
#define FspServiceFromTable() (0 != FspServiceTable ?\
|
||||||
|
(FSP_SERVICE *)((PUINT8)FspServiceTable[0].lpServiceName - FIELD_OFFSET(FSP_SERVICE, ServiceName)) :\
|
||||||
|
0)
|
||||||
|
|
||||||
|
VOID FspServiceInitialize(BOOLEAN Dynamic)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID FspServiceFinalize(BOOLEAN Dynamic)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This function is called during DLL_PROCESS_DETACH. We must therefore keep
|
||||||
|
* finalization tasks to a minimum.
|
||||||
|
*
|
||||||
|
* We must close our console mode event handle. We only do so when we are
|
||||||
|
* explicitly unloaded. If the process is exiting the OS will clean up for us.
|
||||||
|
*/
|
||||||
|
if (Dynamic && 0 != FspServiceConsoleModeEvent)
|
||||||
|
CloseHandle(FspServiceConsoleModeEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API ULONG FspServiceRun(PWSTR ServiceName,
|
||||||
|
FSP_SERVICE_START *OnStart,
|
||||||
|
FSP_SERVICE_STOP *OnStop,
|
||||||
|
FSP_SERVICE_CONTROL *OnControl)
|
||||||
|
{
|
||||||
|
FSP_SERVICE *Service;
|
||||||
|
NTSTATUS Result;
|
||||||
|
ULONG ExitCode;
|
||||||
|
|
||||||
|
Result = FspServiceCreate(ServiceName, OnStart, OnStop, OnControl, &Service);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
FspServiceLog(EVENTLOG_ERROR_TYPE,
|
||||||
|
L"The service %s cannot be created (Status=%lx).", Service->ServiceName, Result);
|
||||||
|
return FspWin32FromNtStatus(Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
FspServiceAllowConsoleMode(Service);
|
||||||
|
Result = FspServiceLoop(Service);
|
||||||
|
ExitCode = FspServiceGetExitCode(Service);
|
||||||
|
FspServiceDelete(Service);
|
||||||
|
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
FspServiceLog(EVENTLOG_ERROR_TYPE,
|
||||||
|
L"The service %s has failed to run (Status=%lx).", Service->ServiceName, Result);
|
||||||
|
return FspWin32FromNtStatus(Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ExitCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API NTSTATUS FspServiceCreate(PWSTR ServiceName,
|
||||||
|
FSP_SERVICE_START *OnStart,
|
||||||
|
FSP_SERVICE_STOP *OnStop,
|
||||||
|
FSP_SERVICE_CONTROL *OnControl,
|
||||||
|
FSP_SERVICE **PService)
|
||||||
|
{
|
||||||
|
FSP_SERVICE *Service;
|
||||||
|
DWORD Size;
|
||||||
|
|
||||||
|
*PService = 0;
|
||||||
|
|
||||||
|
Size = (lstrlenW(ServiceName) + 1) * sizeof(WCHAR);
|
||||||
|
|
||||||
|
Service = MemAlloc(sizeof *Service + Size);
|
||||||
|
if (0 == Service)
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
memset(Service, 0, sizeof *Service);
|
||||||
|
memcpy(Service->ServiceName, ServiceName, Size);
|
||||||
|
|
||||||
|
Service->OnStart = OnStart;
|
||||||
|
Service->OnStop = OnStop;
|
||||||
|
Service->OnControl = OnControl;
|
||||||
|
Service->AcceptControl = OnStop ? SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN : 0;
|
||||||
|
|
||||||
|
InitializeCriticalSection(&Service->ServiceStatusGuard);
|
||||||
|
InitializeCriticalSection(&Service->ServiceStopGuard);
|
||||||
|
|
||||||
|
*PService = Service;
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API VOID FspServiceDelete(FSP_SERVICE *Service)
|
||||||
|
{
|
||||||
|
DeleteCriticalSection(&Service->ServiceStopGuard);
|
||||||
|
DeleteCriticalSection(&Service->ServiceStatusGuard);
|
||||||
|
MemFree(Service);
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID FspServiceSetStatus(FSP_SERVICE *Service, ULONG Flags, SERVICE_STATUS *ServiceStatus)
|
||||||
|
{
|
||||||
|
#define XCHG(FIELD)\
|
||||||
|
if (Flags & SetStatus_##FIELD)\
|
||||||
|
{\
|
||||||
|
DWORD Temp = ServiceStatus->dw##FIELD;\
|
||||||
|
if (Flags & GetStatus_##FIELD)\
|
||||||
|
ServiceStatus->dw##FIELD = Service->ServiceStatus.dw##FIELD;\
|
||||||
|
Service->ServiceStatus.dw##FIELD = Temp;\
|
||||||
|
}
|
||||||
|
|
||||||
|
EnterCriticalSection(&Service->ServiceStatusGuard);
|
||||||
|
|
||||||
|
//XCHG(ServiceType);
|
||||||
|
XCHG(CurrentState);
|
||||||
|
XCHG(ControlsAccepted);
|
||||||
|
XCHG(Win32ExitCode);
|
||||||
|
//XCHG(ServiceSpecificExitCode);
|
||||||
|
if (Flags & AddStatus_CheckPoint)
|
||||||
|
{
|
||||||
|
DWORD Temp = ServiceStatus->dwCheckPoint;
|
||||||
|
if (Flags & GetStatus_CheckPoint)
|
||||||
|
ServiceStatus->dwCheckPoint = Service->ServiceStatus.dwCheckPoint;
|
||||||
|
Service->ServiceStatus.dwCheckPoint += Temp;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
XCHG(CheckPoint);
|
||||||
|
XCHG(WaitHint);
|
||||||
|
|
||||||
|
if (0 != Service->StatusHandle)
|
||||||
|
{
|
||||||
|
if (!SetServiceStatus(Service->StatusHandle, &Service->ServiceStatus))
|
||||||
|
FspServiceLog(EVENTLOG_ERROR_TYPE,
|
||||||
|
L"" __FUNCTION__ ": SetServiceStatus = %ld", GetLastError());
|
||||||
|
}
|
||||||
|
else if (0 != FspServiceConsoleModeEvent &&
|
||||||
|
SERVICE_STOPPED == Service->ServiceStatus.dwCurrentState)
|
||||||
|
{
|
||||||
|
SetEvent(FspServiceConsoleModeEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
LeaveCriticalSection(&Service->ServiceStatusGuard);
|
||||||
|
|
||||||
|
#undef XCHG
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API VOID FspServiceAllowConsoleMode(FSP_SERVICE *Service)
|
||||||
|
{
|
||||||
|
Service->AllowConsoleMode = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API VOID FspServiceAcceptControl(FSP_SERVICE *Service, ULONG Control)
|
||||||
|
{
|
||||||
|
Service->AcceptControl = Control & ~SERVICE_ACCEPT_PAUSE_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API VOID FspServiceRequestTime(FSP_SERVICE *Service, ULONG Time)
|
||||||
|
{
|
||||||
|
SERVICE_STATUS ServiceStatus;
|
||||||
|
|
||||||
|
ServiceStatus.dwCheckPoint = +1;
|
||||||
|
ServiceStatus.dwWaitHint = Time;
|
||||||
|
FspServiceSetStatus(Service,
|
||||||
|
AddStatus_CheckPoint | SetStatus_WaitHint, &ServiceStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API VOID FspServiceSetExitCode(FSP_SERVICE *Service, ULONG ExitCode)
|
||||||
|
{
|
||||||
|
Service->ExitCode = ExitCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API ULONG FspServiceGetExitCode(FSP_SERVICE *Service)
|
||||||
|
{
|
||||||
|
return Service->ServiceStatus.dwWin32ExitCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API NTSTATUS FspServiceLoop(FSP_SERVICE *Service)
|
||||||
|
{
|
||||||
|
NTSTATUS Result;
|
||||||
|
SERVICE_TABLE_ENTRYW ServiceTable[2];
|
||||||
|
|
||||||
|
Service->ExitCode = NO_ERROR;
|
||||||
|
Service->ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
|
||||||
|
Service->ServiceStatus.dwCurrentState = SERVICE_STOPPED;
|
||||||
|
Service->ServiceStatus.dwControlsAccepted = 0;
|
||||||
|
Service->ServiceStatus.dwWin32ExitCode = NO_ERROR;
|
||||||
|
Service->ServiceStatus.dwServiceSpecificExitCode = 0;
|
||||||
|
Service->ServiceStatus.dwCheckPoint = 0;
|
||||||
|
Service->ServiceStatus.dwWaitHint = 0;
|
||||||
|
|
||||||
|
ServiceTable[0].lpServiceName = Service->ServiceName;
|
||||||
|
ServiceTable[0].lpServiceProc = FspServiceEntry;
|
||||||
|
ServiceTable[1].lpServiceName = 0;
|
||||||
|
ServiceTable[1].lpServiceProc = 0;
|
||||||
|
FspServiceTable = ServiceTable;
|
||||||
|
|
||||||
|
if (!StartServiceCtrlDispatcherW(ServiceTable))
|
||||||
|
{
|
||||||
|
HANDLE Thread;
|
||||||
|
PWSTR *Argv;
|
||||||
|
DWORD Argc;
|
||||||
|
DWORD WaitResult;
|
||||||
|
DWORD LastError;
|
||||||
|
|
||||||
|
LastError = GetLastError();
|
||||||
|
if (!Service->AllowConsoleMode || ERROR_FAILED_SERVICE_CONTROLLER_CONNECT != LastError)
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(LastError);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ENTER CONSOLE MODE! */
|
||||||
|
|
||||||
|
/* create/reset the console mode event and console control handler */
|
||||||
|
if (0 == FspServiceConsoleModeEvent)
|
||||||
|
{
|
||||||
|
FspServiceConsoleModeEvent = CreateEventW(0, TRUE, FALSE, 0);
|
||||||
|
if (0 == FspServiceConsoleModeEvent)
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto console_mode_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SetConsoleCtrlHandler(FspServiceConsoleCtrlHandler, TRUE))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto console_mode_exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ResetEvent(FspServiceConsoleModeEvent);
|
||||||
|
FspServiceConsoleCtrlHandlerDisabled = 0;
|
||||||
|
MemoryBarrier();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* prepare the command line arguments */
|
||||||
|
Argv = CommandLineToArgvW(GetCommandLineW(), &Argc);
|
||||||
|
if (0 == Argv)
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto console_mode_exit;
|
||||||
|
}
|
||||||
|
Argv[0] = Service->ServiceName;
|
||||||
|
|
||||||
|
/* create the console mode startup thread (mimic StartServiceCtrlDispatcherW) */
|
||||||
|
Thread = CreateThread(0, 0, FspServiceConsoleModeThread, Argv/* give ownership */, 0, 0);
|
||||||
|
if (0 == Thread)
|
||||||
|
{
|
||||||
|
LocalFree(Argv);
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto console_mode_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* wait for the console mode startup thread to terminate */
|
||||||
|
WaitResult = WaitForSingleObject(Thread, INFINITE);
|
||||||
|
CloseHandle(Thread);
|
||||||
|
if (WAIT_OBJECT_0 != WaitResult)
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto console_mode_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* wait until signaled by the console control handler */
|
||||||
|
WaitResult = WaitForSingleObject(FspServiceConsoleModeEvent, INFINITE);
|
||||||
|
if (WAIT_OBJECT_0 != WaitResult)
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto console_mode_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Service->AcceptControl & SERVICE_ACCEPT_STOP)
|
||||||
|
FspServiceCtrlHandler(SERVICE_CONTROL_STOP, 0, 0, Service);
|
||||||
|
|
||||||
|
console_mode_exit:
|
||||||
|
/*
|
||||||
|
* Turns out that if we are sleeping/waiting in the FspServiceConsoleCtrlHandler
|
||||||
|
* we cannot call SetConsoleCtrlHandler, because we will deadlock. So we cannot
|
||||||
|
* really cleanup our console control handler upon return from this function.
|
||||||
|
*
|
||||||
|
* What we do instead is disable our handler by setting a variable.
|
||||||
|
*/
|
||||||
|
FspServiceConsoleCtrlHandlerDisabled = 1;
|
||||||
|
MemoryBarrier();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
FspServiceTable = 0;
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API VOID FspServiceStop(FSP_SERVICE *Service)
|
||||||
|
{
|
||||||
|
SERVICE_STATUS ServiceStatus;
|
||||||
|
BOOLEAN Stopped;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
if (!TryEnterCriticalSection(&Service->ServiceStopGuard))
|
||||||
|
return; /* the service is already being stopped! */
|
||||||
|
|
||||||
|
EnterCriticalSection(&Service->ServiceStatusGuard);
|
||||||
|
Stopped = SERVICE_STOPPED == Service->ServiceStatus.dwCurrentState;
|
||||||
|
LeaveCriticalSection(&Service->ServiceStatusGuard);
|
||||||
|
if (Stopped)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
|
||||||
|
ServiceStatus.dwCheckPoint = 0;
|
||||||
|
ServiceStatus.dwWaitHint = 0;
|
||||||
|
FspServiceSetStatus(Service,
|
||||||
|
SetStatus_CurrentState | SetStatus_CheckPoint | SetStatus_WaitHint |
|
||||||
|
GetStatus_CurrentState | GetStatus_CheckPoint | GetStatus_WaitHint,
|
||||||
|
&ServiceStatus);
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
if (0 != Service->OnStop)
|
||||||
|
Result = Service->OnStop(Service);
|
||||||
|
|
||||||
|
if (NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
|
||||||
|
ServiceStatus.dwWin32ExitCode = Service->ExitCode;
|
||||||
|
FspServiceSetStatus(Service,
|
||||||
|
SetStatus_CurrentState | SetStatus_Win32ExitCode, &ServiceStatus);
|
||||||
|
|
||||||
|
FspServiceLog(EVENTLOG_INFORMATION_TYPE,
|
||||||
|
L"The service %s has been stopped.", Service->ServiceName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* revert the service status */
|
||||||
|
FspServiceSetStatus(Service,
|
||||||
|
SetStatus_CurrentState | SetStatus_CheckPoint | SetStatus_WaitHint,
|
||||||
|
&ServiceStatus);
|
||||||
|
|
||||||
|
FspServiceLog(EVENTLOG_ERROR_TYPE,
|
||||||
|
L"The service %s has failed to stop (Status=%lx).", Service->ServiceName, Result);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
LeaveCriticalSection(&Service->ServiceStopGuard);
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID WINAPI FspServiceEntry(DWORD Argc, PWSTR *Argv)
|
||||||
|
{
|
||||||
|
FSP_SERVICE *Service;
|
||||||
|
|
||||||
|
Service = FspServiceFromTable();
|
||||||
|
if (0 == Service)
|
||||||
|
{
|
||||||
|
FspServiceLog(EVENTLOG_ERROR_TYPE,
|
||||||
|
L"" __FUNCTION__ ": internal error: FspServiceFromTable = 0");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Service->StatusHandle = RegisterServiceCtrlHandlerExW(Service->ServiceName,
|
||||||
|
FspServiceCtrlHandler, Service);
|
||||||
|
if (0 == Service->StatusHandle)
|
||||||
|
{
|
||||||
|
FspServiceLog(EVENTLOG_ERROR_TYPE,
|
||||||
|
L"" __FUNCTION__ ": RegisterServiceCtrlHandlerW = %ld", GetLastError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FspServiceMain(Service, Argc, Argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID FspServiceMain(FSP_SERVICE *Service, DWORD Argc, PWSTR *Argv)
|
||||||
|
{
|
||||||
|
SERVICE_STATUS ServiceStatus;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
|
||||||
|
ServiceStatus.dwControlsAccepted = 0;
|
||||||
|
FspServiceSetStatus(Service,
|
||||||
|
SetStatus_CurrentState | SetStatus_ControlsAccepted, &ServiceStatus);
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
if (0 != Service->OnStart)
|
||||||
|
Result = Service->OnStart(Service, Argc, Argv);
|
||||||
|
|
||||||
|
if (NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
|
||||||
|
ServiceStatus.dwControlsAccepted = Service->AcceptControl;
|
||||||
|
FspServiceSetStatus(Service,
|
||||||
|
SetStatus_CurrentState | SetStatus_ControlsAccepted, &ServiceStatus);
|
||||||
|
|
||||||
|
FspServiceLog(EVENTLOG_INFORMATION_TYPE,
|
||||||
|
L"The service %s has been started.", Service->ServiceName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
|
||||||
|
ServiceStatus.dwWin32ExitCode = FspWin32FromNtStatus(Result);
|
||||||
|
FspServiceSetStatus(Service,
|
||||||
|
SetStatus_CurrentState | SetStatus_Win32ExitCode, &ServiceStatus);
|
||||||
|
|
||||||
|
FspServiceLog(EVENTLOG_ERROR_TYPE,
|
||||||
|
L"The service %s has failed to start (Status=%lx).", Service->ServiceName, Result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static DWORD WINAPI FspServiceCtrlHandler(
|
||||||
|
DWORD Control, DWORD EventType, PVOID EventData, PVOID Context)
|
||||||
|
{
|
||||||
|
FSP_SERVICE *Service = Context;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
switch (Control)
|
||||||
|
{
|
||||||
|
case SERVICE_CONTROL_SHUTDOWN:
|
||||||
|
/*
|
||||||
|
* Shutdown simply falls through to Stop. If specific Shutdown handling is needed
|
||||||
|
* we need to enable this. We also need to arrange for console mode to have two
|
||||||
|
* events: one to signal Stop and another to signal Shutdown. We currently use a
|
||||||
|
* single event for both console mode controls.
|
||||||
|
*/
|
||||||
|
#if 0
|
||||||
|
Result = STATUS_NOT_IMPLEMENTED;
|
||||||
|
if (0 != Service->OnControl)
|
||||||
|
Result = Service->OnControl(Service, Control, EventType, EventData);
|
||||||
|
if (STATUS_NOT_IMPLEMENTED != Result)
|
||||||
|
return FspWin32FromNtStatus(Result);
|
||||||
|
/* fall through */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case SERVICE_CONTROL_STOP:
|
||||||
|
FspServiceStop(Service);
|
||||||
|
return NO_ERROR;
|
||||||
|
|
||||||
|
case SERVICE_CONTROL_PAUSE:
|
||||||
|
case SERVICE_CONTROL_CONTINUE:
|
||||||
|
return ERROR_CALL_NOT_IMPLEMENTED;
|
||||||
|
|
||||||
|
case SERVICE_CONTROL_INTERROGATE:
|
||||||
|
return NO_ERROR;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
if (0 != Service->OnControl)
|
||||||
|
Result = Service->OnControl(Service, Control, EventType, EventData);
|
||||||
|
return FspWin32FromNtStatus(Result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static DWORD WINAPI FspServiceConsoleModeThread(PVOID Context)
|
||||||
|
{
|
||||||
|
FSP_SERVICE *Service;
|
||||||
|
PWSTR *Argv = Context;
|
||||||
|
DWORD Argc;
|
||||||
|
|
||||||
|
for (Argc = 0; 0 != Argv[Argc]; Argc++)
|
||||||
|
;
|
||||||
|
|
||||||
|
Service = FspServiceFromTable();
|
||||||
|
if (0 == Service)
|
||||||
|
FspServiceLog(EVENTLOG_ERROR_TYPE,
|
||||||
|
L"" __FUNCTION__ ": internal error: FspServiceFromTable = 0");
|
||||||
|
else
|
||||||
|
FspServiceMain(Service, Argc, Argv);
|
||||||
|
|
||||||
|
LocalFree(Argv);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL WINAPI FspServiceConsoleCtrlHandler(DWORD CtrlType)
|
||||||
|
{
|
||||||
|
UINT32 Disabled = FspServiceConsoleCtrlHandlerDisabled;
|
||||||
|
MemoryBarrier();
|
||||||
|
if (Disabled)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
switch (CtrlType)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
case CTRL_C_EVENT:
|
||||||
|
case CTRL_BREAK_EVENT:
|
||||||
|
if (0 != FspServiceConsoleModeEvent)
|
||||||
|
SetEvent(FspServiceConsoleModeEvent);
|
||||||
|
return TRUE;
|
||||||
|
case CTRL_CLOSE_EVENT:
|
||||||
|
case CTRL_SHUTDOWN_EVENT:
|
||||||
|
/*
|
||||||
|
* Returning from these events will kill the process. OTOH if we do not return timely
|
||||||
|
* the OS will kill us within 5-20 seconds. Our strategy is to wait some time (30 sec)
|
||||||
|
* to give the process some time to cleanup itself.
|
||||||
|
*
|
||||||
|
* We only do so if we have a Close event or we are interactive. If we are running as
|
||||||
|
* a service the OS will not kill us after delivering a Shutdown (or Logoff) event.
|
||||||
|
*/
|
||||||
|
if (0 != FspServiceConsoleModeEvent)
|
||||||
|
SetEvent(FspServiceConsoleModeEvent);
|
||||||
|
if (CTRL_CLOSE_EVENT == CtrlType || FspServiceIsInteractive())
|
||||||
|
Sleep(30000);
|
||||||
|
return TRUE;
|
||||||
|
case CTRL_LOGOFF_EVENT:
|
||||||
|
/* services should ignore this! */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API BOOLEAN FspServiceIsInteractive(VOID)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Modeled after System.Environment.UserInteractive.
|
||||||
|
* See http://referencesource.microsoft.com/#mscorlib/system/environment.cs,947ad026e7cb830c
|
||||||
|
*/
|
||||||
|
static HWINSTA ProcessWindowStation;
|
||||||
|
static BOOLEAN IsInteractive;
|
||||||
|
HWINSTA CurrentWindowStation;
|
||||||
|
USEROBJECTFLAGS Flags;
|
||||||
|
|
||||||
|
CurrentWindowStation = GetProcessWindowStation();
|
||||||
|
if (0 != CurrentWindowStation && ProcessWindowStation != CurrentWindowStation)
|
||||||
|
{
|
||||||
|
if (GetUserObjectInformationW(CurrentWindowStation, UOI_FLAGS, &Flags, sizeof Flags, 0))
|
||||||
|
IsInteractive = 0 != (Flags.dwFlags & WSF_VISIBLE);
|
||||||
|
ProcessWindowStation = CurrentWindowStation;
|
||||||
|
}
|
||||||
|
return IsInteractive;
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API VOID FspServiceLog(ULONG Type, PWSTR Format, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, Format);
|
||||||
|
FspServiceLogV(Type, Format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
FSP_API VOID FspServiceLogV(ULONG Type, PWSTR Format, va_list ap)
|
||||||
|
{
|
||||||
|
if (FspServiceIsInteractive())
|
||||||
|
{
|
||||||
|
WCHAR BufW[1024];
|
||||||
|
/* wvsprintfW is only safe with a 1024 WCHAR buffer */
|
||||||
|
PSTR BufA;
|
||||||
|
DWORD Length;
|
||||||
|
|
||||||
|
wvsprintfW(BufW, Format, ap);
|
||||||
|
BufW[(sizeof BufW / sizeof BufW[0]) - 1] = L'\0';
|
||||||
|
|
||||||
|
Length = lstrlenW(BufW);
|
||||||
|
BufA = MemAlloc(Length * 3 + 1/* '\n' */);
|
||||||
|
if (0 != BufA)
|
||||||
|
{
|
||||||
|
Length = WideCharToMultiByte(CP_UTF8, 0, BufW, Length, BufA, Length * 3 + 1/* '\n' */,
|
||||||
|
0, 0);
|
||||||
|
if (0 < Length)
|
||||||
|
{
|
||||||
|
BufA[Length++] = '\n';
|
||||||
|
WriteFile(GetStdHandle(STD_ERROR_HANDLE), BufA, Length, &Length, 0);
|
||||||
|
}
|
||||||
|
MemFree(BufA);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
FspEventLogV(Type, Format, ap);
|
||||||
|
}
|
37
src/dll/version.rc
Normal file
37
src/dll/version.rc
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#include <winver.h>
|
||||||
|
|
||||||
|
#define STR(x) STR_(x)
|
||||||
|
#define STR_(x) #x
|
||||||
|
|
||||||
|
VS_VERSION_INFO VERSIONINFO
|
||||||
|
FILEVERSION MyVersionWithCommas
|
||||||
|
PRODUCTVERSION MyVersionWithCommas
|
||||||
|
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||||
|
#ifdef _DEBUG
|
||||||
|
FILEFLAGS VS_FF_DEBUG
|
||||||
|
#else
|
||||||
|
FILEFLAGS 0
|
||||||
|
#endif
|
||||||
|
FILEOS VOS_NT
|
||||||
|
FILETYPE VFT_DLL
|
||||||
|
FILESUBTYPE 0
|
||||||
|
BEGIN
|
||||||
|
BLOCK "StringFileInfo"
|
||||||
|
BEGIN
|
||||||
|
BLOCK "040904b0"
|
||||||
|
BEGIN
|
||||||
|
VALUE "CompanyName", STR(MyCompanyName)
|
||||||
|
VALUE "FileDescription", STR(MyDescription)
|
||||||
|
VALUE "FileVersion", STR(MyVersion)
|
||||||
|
VALUE "InternalName", "winfsp.dll"
|
||||||
|
VALUE "LegalCopyright", STR(MyCopyright)
|
||||||
|
VALUE "OriginalFilename", "winfsp.dll"
|
||||||
|
VALUE "ProductName", STR(MyProductName)
|
||||||
|
VALUE "ProductVersion", STR(MyVersion)
|
||||||
|
END
|
||||||
|
END
|
||||||
|
BLOCK "VarFileInfo"
|
||||||
|
BEGIN
|
||||||
|
VALUE "Translation", 0x409, 1200
|
||||||
|
END
|
||||||
|
END
|
37
src/launcher/launchctl-version.rc
Normal file
37
src/launcher/launchctl-version.rc
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#include <winver.h>
|
||||||
|
|
||||||
|
#define STR(x) STR_(x)
|
||||||
|
#define STR_(x) #x
|
||||||
|
|
||||||
|
VS_VERSION_INFO VERSIONINFO
|
||||||
|
FILEVERSION MyVersionWithCommas
|
||||||
|
PRODUCTVERSION MyVersionWithCommas
|
||||||
|
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||||
|
#ifdef _DEBUG
|
||||||
|
FILEFLAGS VS_FF_DEBUG
|
||||||
|
#else
|
||||||
|
FILEFLAGS 0
|
||||||
|
#endif
|
||||||
|
FILEOS VOS_NT
|
||||||
|
FILETYPE VFT_APP
|
||||||
|
FILESUBTYPE 0
|
||||||
|
BEGIN
|
||||||
|
BLOCK "StringFileInfo"
|
||||||
|
BEGIN
|
||||||
|
BLOCK "040904b0"
|
||||||
|
BEGIN
|
||||||
|
VALUE "CompanyName", STR(MyCompanyName)
|
||||||
|
VALUE "FileDescription", STR(MyDescription)
|
||||||
|
VALUE "FileVersion", STR(MyVersion)
|
||||||
|
VALUE "InternalName", "launchctl.exe"
|
||||||
|
VALUE "LegalCopyright", STR(MyCopyright)
|
||||||
|
VALUE "OriginalFilename", "launchctl.exe"
|
||||||
|
VALUE "ProductName", STR(MyProductName)
|
||||||
|
VALUE "ProductVersion", STR(MyVersion)
|
||||||
|
END
|
||||||
|
END
|
||||||
|
BLOCK "VarFileInfo"
|
||||||
|
BEGIN
|
||||||
|
VALUE "Translation", 0x409, 1200
|
||||||
|
END
|
||||||
|
END
|
291
src/launcher/launchctl.c
Normal file
291
src/launcher/launchctl.c
Normal file
@ -0,0 +1,291 @@
|
|||||||
|
/**
|
||||||
|
* @file launcher/launchctl.c
|
||||||
|
*
|
||||||
|
* @copyright 2015-2016 Bill Zissimopoulos
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* This file is part of WinFsp.
|
||||||
|
*
|
||||||
|
* You can redistribute it and/or modify it under the terms of the
|
||||||
|
* GNU Affero General Public License version 3 as published by the
|
||||||
|
* Free Software Foundation.
|
||||||
|
*
|
||||||
|
* Licensees holding a valid commercial license may use this file in
|
||||||
|
* accordance with the commercial license agreement provided with the
|
||||||
|
* software.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <launcher/launcher.h>
|
||||||
|
|
||||||
|
#define PROGNAME "launchctl"
|
||||||
|
|
||||||
|
#define info(format, ...) printlog(GetStdHandle(STD_OUTPUT_HANDLE), format, __VA_ARGS__)
|
||||||
|
#define warn(format, ...) printlog(GetStdHandle(STD_ERROR_HANDLE), format, __VA_ARGS__)
|
||||||
|
#define fatal(ExitCode, format, ...) (warn(format, __VA_ARGS__), ExitProcess(ExitCode))
|
||||||
|
|
||||||
|
static void vprintlog(HANDLE h, const char *format, va_list ap)
|
||||||
|
{
|
||||||
|
char buf[1024];
|
||||||
|
/* wvsprintf is only safe with a 1024 byte buffer */
|
||||||
|
size_t len;
|
||||||
|
DWORD BytesTransferred;
|
||||||
|
|
||||||
|
wvsprintfA(buf, format, ap);
|
||||||
|
buf[sizeof buf - 1] = '\0';
|
||||||
|
|
||||||
|
len = lstrlenA(buf);
|
||||||
|
buf[len++] = '\n';
|
||||||
|
|
||||||
|
WriteFile(h, buf, (DWORD)len, &BytesTransferred, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void printlog(HANDLE h, const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, format);
|
||||||
|
vprintlog(h, format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void usage(void)
|
||||||
|
{
|
||||||
|
fatal(ERROR_INVALID_PARAMETER,
|
||||||
|
"usage: %s COMMAND ARGS\n"
|
||||||
|
"\n"
|
||||||
|
"commands:\n"
|
||||||
|
" start ClassName InstanceName Args...\n"
|
||||||
|
" stop ClassName InstanceName\n"
|
||||||
|
" info ClassName InstanceName\n"
|
||||||
|
" list\n",
|
||||||
|
PROGNAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int call_pipe_and_report(PWSTR PipeBuf, ULONG SendSize, ULONG RecvSize)
|
||||||
|
{
|
||||||
|
NTSTATUS Result;
|
||||||
|
DWORD LastError, BytesTransferred;
|
||||||
|
|
||||||
|
Result = FspCallNamedPipeSecurely(L"" LAUNCHER_PIPE_NAME, PipeBuf, SendSize, PipeBuf, RecvSize,
|
||||||
|
&BytesTransferred, NMPWAIT_USE_DEFAULT_WAIT, LAUNCHER_PIPE_OWNER);
|
||||||
|
LastError = FspWin32FromNtStatus(Result);
|
||||||
|
|
||||||
|
if (0 != LastError)
|
||||||
|
warn("KO CallNamedPipe = %ld", LastError);
|
||||||
|
else if (sizeof(WCHAR) > BytesTransferred)
|
||||||
|
warn("KO launcher: empty buffer");
|
||||||
|
else if (LauncherSuccess == PipeBuf[0])
|
||||||
|
{
|
||||||
|
if (sizeof(WCHAR) == BytesTransferred)
|
||||||
|
info("OK");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ULONG Count = 0;
|
||||||
|
|
||||||
|
for (PWSTR P = PipeBuf, PipeBufEnd = P + BytesTransferred / sizeof(WCHAR);
|
||||||
|
PipeBufEnd > P; P++)
|
||||||
|
if (L'\0' == *P)
|
||||||
|
{
|
||||||
|
/* print a newline every 2 nulls; this works for both list and info */
|
||||||
|
*P = 1 == Count % 2 ? L'\n' : L' ';
|
||||||
|
Count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BytesTransferred < RecvSize)
|
||||||
|
PipeBuf[BytesTransferred / sizeof(WCHAR)] = L'\0';
|
||||||
|
else
|
||||||
|
PipeBuf[RecvSize / sizeof(WCHAR) - 1] = L'\0';
|
||||||
|
|
||||||
|
info("OK\n%S", PipeBuf + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (LauncherFailure == PipeBuf[0])
|
||||||
|
{
|
||||||
|
if (BytesTransferred < RecvSize)
|
||||||
|
PipeBuf[BytesTransferred / sizeof(WCHAR)] = L'\0';
|
||||||
|
else
|
||||||
|
PipeBuf[RecvSize / sizeof(WCHAR) - 1] = L'\0';
|
||||||
|
|
||||||
|
info("KO launcher: error %S", PipeBuf + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
warn("KO launcher: corrupted buffer", 0);
|
||||||
|
|
||||||
|
return LastError;
|
||||||
|
}
|
||||||
|
|
||||||
|
int start(PWSTR PipeBuf, ULONG PipeBufSize,
|
||||||
|
PWSTR ClassName, PWSTR InstanceName, DWORD Argc, PWSTR *Argv)
|
||||||
|
{
|
||||||
|
PWSTR P;
|
||||||
|
DWORD ClassNameSize, InstanceNameSize, ArgvSize;
|
||||||
|
|
||||||
|
ClassNameSize = lstrlenW(ClassName) + 1;
|
||||||
|
InstanceNameSize = lstrlenW(InstanceName) + 1;
|
||||||
|
ArgvSize = 0;
|
||||||
|
for (DWORD Argi = 0; Argc > Argi; Argi++)
|
||||||
|
ArgvSize += lstrlenW(Argv[Argi]) + 1;
|
||||||
|
|
||||||
|
if (PipeBufSize < (1 + ClassNameSize + InstanceNameSize + ArgvSize) * sizeof(WCHAR))
|
||||||
|
return ERROR_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
P = PipeBuf;
|
||||||
|
*P++ = LauncherSvcInstanceStart;
|
||||||
|
memcpy(P, ClassName, ClassNameSize * sizeof(WCHAR)); P += ClassNameSize;
|
||||||
|
memcpy(P, InstanceName, InstanceNameSize * sizeof(WCHAR)); P += InstanceNameSize;
|
||||||
|
for (DWORD Argi = 0; Argc > Argi; Argi++)
|
||||||
|
{
|
||||||
|
ArgvSize = lstrlenW(Argv[Argi]) + 1;
|
||||||
|
memcpy(P, Argv[Argi], ArgvSize * sizeof(WCHAR)); P += ArgvSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return call_pipe_and_report(PipeBuf, (ULONG)((P - PipeBuf) * sizeof(WCHAR)), PipeBufSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
int stop(PWSTR PipeBuf, ULONG PipeBufSize,
|
||||||
|
PWSTR ClassName, PWSTR InstanceName)
|
||||||
|
{
|
||||||
|
PWSTR P;
|
||||||
|
DWORD ClassNameSize, InstanceNameSize;
|
||||||
|
|
||||||
|
ClassNameSize = lstrlenW(ClassName) + 1;
|
||||||
|
InstanceNameSize = lstrlenW(InstanceName) + 1;
|
||||||
|
|
||||||
|
if (PipeBufSize < (1 + ClassNameSize + InstanceNameSize) * sizeof(WCHAR))
|
||||||
|
return ERROR_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
P = PipeBuf;
|
||||||
|
*P++ = LauncherSvcInstanceStop;
|
||||||
|
memcpy(P, ClassName, ClassNameSize * sizeof(WCHAR)); P += ClassNameSize;
|
||||||
|
memcpy(P, InstanceName, InstanceNameSize * sizeof(WCHAR)); P += InstanceNameSize;
|
||||||
|
|
||||||
|
return call_pipe_and_report(PipeBuf, (ULONG)((P - PipeBuf) * sizeof(WCHAR)), PipeBufSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
int getinfo(PWSTR PipeBuf, ULONG PipeBufSize,
|
||||||
|
PWSTR ClassName, PWSTR InstanceName)
|
||||||
|
{
|
||||||
|
PWSTR P;
|
||||||
|
DWORD ClassNameSize, InstanceNameSize;
|
||||||
|
|
||||||
|
ClassNameSize = lstrlenW(ClassName) + 1;
|
||||||
|
InstanceNameSize = lstrlenW(InstanceName) + 1;
|
||||||
|
|
||||||
|
if (PipeBufSize < (1 + ClassNameSize + InstanceNameSize) * sizeof(WCHAR))
|
||||||
|
return ERROR_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
P = PipeBuf;
|
||||||
|
*P++ = LauncherSvcInstanceInfo;
|
||||||
|
memcpy(P, ClassName, ClassNameSize * sizeof(WCHAR)); P += ClassNameSize;
|
||||||
|
memcpy(P, InstanceName, InstanceNameSize * sizeof(WCHAR)); P += InstanceNameSize;
|
||||||
|
|
||||||
|
return call_pipe_and_report(PipeBuf, (ULONG)((P - PipeBuf) * sizeof(WCHAR)), PipeBufSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
int list(PWSTR PipeBuf, ULONG PipeBufSize)
|
||||||
|
{
|
||||||
|
PWSTR P;
|
||||||
|
|
||||||
|
if (PipeBufSize < 1 * sizeof(WCHAR))
|
||||||
|
return ERROR_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
P = PipeBuf;
|
||||||
|
*P++ = LauncherSvcInstanceList;
|
||||||
|
|
||||||
|
return call_pipe_and_report(PipeBuf, (ULONG)((P - PipeBuf) * sizeof(WCHAR)), PipeBufSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
int quit(PWSTR PipeBuf, ULONG PipeBufSize)
|
||||||
|
{
|
||||||
|
/* works only against DEBUG version of launcher */
|
||||||
|
|
||||||
|
PWSTR P;
|
||||||
|
|
||||||
|
if (PipeBufSize < 1 * sizeof(WCHAR))
|
||||||
|
return ERROR_INVALID_PARAMETER;
|
||||||
|
|
||||||
|
P = PipeBuf;
|
||||||
|
*P++ = LauncherQuit;
|
||||||
|
|
||||||
|
return call_pipe_and_report(PipeBuf, (ULONG)((P - PipeBuf) * sizeof(WCHAR)), PipeBufSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
int wmain(int argc, wchar_t **argv)
|
||||||
|
{
|
||||||
|
PWSTR PipeBuf = 0;
|
||||||
|
|
||||||
|
/* allocate our PipeBuf early on; freed on process exit by the system */
|
||||||
|
PipeBuf = MemAlloc(LAUNCHER_PIPE_BUFFER_SIZE);
|
||||||
|
if (0 == PipeBuf)
|
||||||
|
return ERROR_NO_SYSTEM_RESOURCES;
|
||||||
|
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
|
||||||
|
if (0 == argc)
|
||||||
|
usage();
|
||||||
|
|
||||||
|
if (0 == lstrcmpW(L"start", argv[0]))
|
||||||
|
{
|
||||||
|
if (3 > argc || argc > 12)
|
||||||
|
usage();
|
||||||
|
|
||||||
|
return start(PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE, argv[1], argv[2], argc - 3, argv + 3);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (0 == lstrcmpW(L"stop", argv[0]))
|
||||||
|
{
|
||||||
|
if (3 != argc)
|
||||||
|
usage();
|
||||||
|
|
||||||
|
return stop(PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE, argv[1], argv[2]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (0 == lstrcmpW(L"info", argv[0]))
|
||||||
|
{
|
||||||
|
if (3 != argc)
|
||||||
|
usage();
|
||||||
|
|
||||||
|
return getinfo(PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE, argv[1], argv[2]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (0 == lstrcmpW(L"list", argv[0]))
|
||||||
|
{
|
||||||
|
if (1 != argc)
|
||||||
|
usage();
|
||||||
|
|
||||||
|
return list(PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (0 == lstrcmpW(L"quit", argv[0]))
|
||||||
|
{
|
||||||
|
if (1 != argc)
|
||||||
|
usage();
|
||||||
|
|
||||||
|
/* works only against DEBUG version of launcher */
|
||||||
|
return quit(PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
usage();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wmainCRTStartup(void)
|
||||||
|
{
|
||||||
|
DWORD Argc;
|
||||||
|
PWSTR *Argv;
|
||||||
|
|
||||||
|
extern HANDLE ProcessHeap;
|
||||||
|
ProcessHeap = GetProcessHeap();
|
||||||
|
if (0 == ProcessHeap)
|
||||||
|
ExitProcess(GetLastError());
|
||||||
|
|
||||||
|
Argv = CommandLineToArgvW(GetCommandLineW(), &Argc);
|
||||||
|
if (0 == Argv)
|
||||||
|
ExitProcess(GetLastError());
|
||||||
|
|
||||||
|
ExitProcess(wmain(Argc, Argv));
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE ProcessHeap;
|
37
src/launcher/launcher-version.rc
Normal file
37
src/launcher/launcher-version.rc
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#include <winver.h>
|
||||||
|
|
||||||
|
#define STR(x) STR_(x)
|
||||||
|
#define STR_(x) #x
|
||||||
|
|
||||||
|
VS_VERSION_INFO VERSIONINFO
|
||||||
|
FILEVERSION MyVersionWithCommas
|
||||||
|
PRODUCTVERSION MyVersionWithCommas
|
||||||
|
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||||
|
#ifdef _DEBUG
|
||||||
|
FILEFLAGS VS_FF_DEBUG
|
||||||
|
#else
|
||||||
|
FILEFLAGS 0
|
||||||
|
#endif
|
||||||
|
FILEOS VOS_NT
|
||||||
|
FILETYPE VFT_APP
|
||||||
|
FILESUBTYPE 0
|
||||||
|
BEGIN
|
||||||
|
BLOCK "StringFileInfo"
|
||||||
|
BEGIN
|
||||||
|
BLOCK "040904b0"
|
||||||
|
BEGIN
|
||||||
|
VALUE "CompanyName", STR(MyCompanyName)
|
||||||
|
VALUE "FileDescription", STR(MyDescription)
|
||||||
|
VALUE "FileVersion", STR(MyVersion)
|
||||||
|
VALUE "InternalName", "launcher.exe"
|
||||||
|
VALUE "LegalCopyright", STR(MyCopyright)
|
||||||
|
VALUE "OriginalFilename", "launcher.exe"
|
||||||
|
VALUE "ProductName", STR(MyProductName)
|
||||||
|
VALUE "ProductVersion", STR(MyVersion)
|
||||||
|
END
|
||||||
|
END
|
||||||
|
BLOCK "VarFileInfo"
|
||||||
|
BEGIN
|
||||||
|
VALUE "Translation", 0x409, 1200
|
||||||
|
END
|
||||||
|
END
|
992
src/launcher/launcher.c
Normal file
992
src/launcher/launcher.c
Normal file
@ -0,0 +1,992 @@
|
|||||||
|
/**
|
||||||
|
* @file launcher/launcher.c
|
||||||
|
*
|
||||||
|
* @copyright 2015-2016 Bill Zissimopoulos
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* This file is part of WinFsp.
|
||||||
|
*
|
||||||
|
* You can redistribute it and/or modify it under the terms of the
|
||||||
|
* GNU Affero General Public License version 3 as published by the
|
||||||
|
* Free Software Foundation.
|
||||||
|
*
|
||||||
|
* Licensees holding a valid commercial license may use this file in
|
||||||
|
* accordance with the commercial license agreement provided with the
|
||||||
|
* software.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <launcher/launcher.h>
|
||||||
|
#include <sddl.h>
|
||||||
|
|
||||||
|
#define PROGNAME "WinFsp.Launcher"
|
||||||
|
#define REGKEY "SYSTEM\\CurrentControlSet\\Services\\" PROGNAME "\\Services"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
HANDLE Process;
|
||||||
|
HANDLE ProcessWait;
|
||||||
|
} KILL_PROCESS_DATA;
|
||||||
|
|
||||||
|
static VOID CALLBACK KillProcessWait(PVOID Context, BOOLEAN Timeout);
|
||||||
|
|
||||||
|
VOID KillProcess(ULONG ProcessId, HANDLE Process, ULONG Timeout)
|
||||||
|
{
|
||||||
|
if (GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, ProcessId))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* If GenerateConsoleCtrlEvent succeeds, but the child process does not exit
|
||||||
|
* timely we will terminate it with extreme prejudice. This is done by calling
|
||||||
|
* RegisterWaitForSingleObject with timeout on a duplicated process handle.
|
||||||
|
*
|
||||||
|
* If GenerateConsoleCtrlEvent succeeds, but we are not able to successfully call
|
||||||
|
* RegisterWaitForSingleObject, we do NOT terminate the child process forcibly.
|
||||||
|
* This is by design as it is not the child process's fault and the child process
|
||||||
|
* should (we hope in this case) respond to the console control event timely.
|
||||||
|
*/
|
||||||
|
|
||||||
|
KILL_PROCESS_DATA *KillProcessData;
|
||||||
|
|
||||||
|
KillProcessData = MemAlloc(sizeof *KillProcessData);
|
||||||
|
if (0 != KillProcessData)
|
||||||
|
{
|
||||||
|
if (DuplicateHandle(GetCurrentProcess(), Process, GetCurrentProcess(), &KillProcessData->Process,
|
||||||
|
0, FALSE, DUPLICATE_SAME_ACCESS))
|
||||||
|
{
|
||||||
|
if (RegisterWaitForSingleObject(&KillProcessData->ProcessWait, KillProcessData->Process,
|
||||||
|
KillProcessWait, KillProcessData, Timeout, WT_EXECUTEONLYONCE))
|
||||||
|
KillProcessData = 0;
|
||||||
|
else
|
||||||
|
CloseHandle(KillProcessData->Process);
|
||||||
|
}
|
||||||
|
|
||||||
|
MemFree(KillProcessData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
TerminateProcess(Process, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID CALLBACK KillProcessWait(PVOID Context, BOOLEAN Timeout)
|
||||||
|
{
|
||||||
|
KILL_PROCESS_DATA *KillProcessData = Context;
|
||||||
|
|
||||||
|
if (Timeout)
|
||||||
|
TerminateProcess(KillProcessData->Process, 0);
|
||||||
|
|
||||||
|
UnregisterWaitEx(KillProcessData->ProcessWait, 0);
|
||||||
|
CloseHandle(KillProcessData->Process);
|
||||||
|
MemFree(KillProcessData);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
PWSTR ClassName;
|
||||||
|
PWSTR InstanceName;
|
||||||
|
PWSTR CommandLine;
|
||||||
|
PSECURITY_DESCRIPTOR SecurityDescriptor;
|
||||||
|
DWORD ProcessId;
|
||||||
|
HANDLE Process;
|
||||||
|
HANDLE ProcessWait;
|
||||||
|
LIST_ENTRY ListEntry;
|
||||||
|
WCHAR Buffer[];
|
||||||
|
} SVC_INSTANCE;
|
||||||
|
|
||||||
|
static CRITICAL_SECTION SvcInstanceLock;
|
||||||
|
static HANDLE SvcInstanceEvent;
|
||||||
|
static LIST_ENTRY SvcInstanceList = { &SvcInstanceList, &SvcInstanceList };
|
||||||
|
|
||||||
|
static VOID CALLBACK SvcInstanceTerminated(PVOID Context, BOOLEAN Timeout);
|
||||||
|
|
||||||
|
static SVC_INSTANCE *SvcInstanceLookup(PWSTR ClassName, PWSTR InstanceName)
|
||||||
|
{
|
||||||
|
SVC_INSTANCE *SvcInstance;
|
||||||
|
PLIST_ENTRY ListEntry;
|
||||||
|
|
||||||
|
for (ListEntry = SvcInstanceList.Flink;
|
||||||
|
&SvcInstanceList != ListEntry;
|
||||||
|
ListEntry = ListEntry->Flink)
|
||||||
|
{
|
||||||
|
SvcInstance = CONTAINING_RECORD(ListEntry, SVC_INSTANCE, ListEntry);
|
||||||
|
|
||||||
|
if (0 == lstrcmpW(ClassName, SvcInstance->ClassName) &&
|
||||||
|
0 == lstrcmpW(InstanceName, SvcInstance->InstanceName))
|
||||||
|
return SvcInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG SvcInstanceArgumentLength(PWSTR Arg)
|
||||||
|
{
|
||||||
|
ULONG Length;
|
||||||
|
|
||||||
|
Length = 2; /* for beginning and ending quotes */
|
||||||
|
for (PWSTR P = Arg; *P; P++)
|
||||||
|
if (L'"' != *P)
|
||||||
|
Length++;
|
||||||
|
|
||||||
|
return Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PWSTR SvcInstanceArgumentCopy(PWSTR Dest, PWSTR Arg)
|
||||||
|
{
|
||||||
|
*Dest++ = L'"';
|
||||||
|
for (PWSTR P = Arg; *P; P++)
|
||||||
|
if (L'"' != *P)
|
||||||
|
*Dest++ = *P;
|
||||||
|
*Dest++ = L'"';
|
||||||
|
|
||||||
|
return Dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS SvcInstanceReplaceArguments(PWSTR String, ULONG Argc, PWSTR *Argv,
|
||||||
|
PWSTR *PNewString)
|
||||||
|
{
|
||||||
|
PWSTR NewString = 0, P, Q;
|
||||||
|
PWSTR EmptyArg = L"";
|
||||||
|
ULONG Length;
|
||||||
|
|
||||||
|
*PNewString = 0;
|
||||||
|
|
||||||
|
Length = 0;
|
||||||
|
for (P = String; *P; P++)
|
||||||
|
{
|
||||||
|
switch (*P)
|
||||||
|
{
|
||||||
|
case L'%':
|
||||||
|
P++;
|
||||||
|
if (L'0' <= *P && *P <= '9')
|
||||||
|
{
|
||||||
|
if (Argc > (ULONG)(*P - L'0'))
|
||||||
|
Length += SvcInstanceArgumentLength(Argv[*P - L'0']);
|
||||||
|
else
|
||||||
|
Length += SvcInstanceArgumentLength(EmptyArg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Length++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Length++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NewString = MemAlloc((Length + 1) * sizeof(WCHAR));
|
||||||
|
if (0 == NewString)
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
|
||||||
|
for (P = String, Q = NewString; *P; P++)
|
||||||
|
{
|
||||||
|
switch (*P)
|
||||||
|
{
|
||||||
|
case L'%':
|
||||||
|
P++;
|
||||||
|
if (L'0' <= *P && *P <= '9')
|
||||||
|
{
|
||||||
|
if (Argc > (ULONG)(*P - L'0'))
|
||||||
|
Q = SvcInstanceArgumentCopy(Q, Argv[*P - L'0']);
|
||||||
|
else
|
||||||
|
Q = SvcInstanceArgumentCopy(Q, EmptyArg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*Q++ = *P;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
*Q++ = *P;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*Q = L'\0';
|
||||||
|
|
||||||
|
*PNewString = NewString;
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS SvcInstanceAccessCheck(HANDLE ClientToken, ULONG DesiredAccess,
|
||||||
|
PSECURITY_DESCRIPTOR SecurityDescriptor)
|
||||||
|
{
|
||||||
|
static GENERIC_MAPPING GenericMapping =
|
||||||
|
{
|
||||||
|
.GenericRead = STANDARD_RIGHTS_READ | SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS |
|
||||||
|
SERVICE_INTERROGATE | SERVICE_ENUMERATE_DEPENDENTS,
|
||||||
|
.GenericWrite = STANDARD_RIGHTS_WRITE | SERVICE_CHANGE_CONFIG,
|
||||||
|
.GenericExecute = STANDARD_RIGHTS_EXECUTE | SERVICE_START | SERVICE_STOP |
|
||||||
|
SERVICE_PAUSE_CONTINUE | SERVICE_USER_DEFINED_CONTROL,
|
||||||
|
.GenericAll = SERVICE_ALL_ACCESS,
|
||||||
|
};
|
||||||
|
UINT8 PrivilegeSetBuf[sizeof(PRIVILEGE_SET) + 15 * sizeof(LUID_AND_ATTRIBUTES)];
|
||||||
|
PPRIVILEGE_SET PrivilegeSet = (PVOID)PrivilegeSetBuf;
|
||||||
|
DWORD PrivilegeSetLength = sizeof PrivilegeSetBuf;
|
||||||
|
ULONG GrantedAccess;
|
||||||
|
BOOL AccessStatus;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
if (AccessCheck(SecurityDescriptor, ClientToken, DesiredAccess,
|
||||||
|
&GenericMapping, PrivilegeSet, &PrivilegeSetLength, &GrantedAccess, &AccessStatus))
|
||||||
|
Result = AccessStatus ? STATUS_SUCCESS : STATUS_ACCESS_DENIED;
|
||||||
|
else
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS SvcInstanceCreate(HANDLE ClientToken,
|
||||||
|
PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWSTR *Argv0, HANDLE Job,
|
||||||
|
SVC_INSTANCE **PSvcInstance)
|
||||||
|
{
|
||||||
|
SVC_INSTANCE *SvcInstance = 0;
|
||||||
|
HKEY RegKey = 0;
|
||||||
|
DWORD RegResult, RegSize;
|
||||||
|
DWORD ClassNameSize, InstanceNameSize;
|
||||||
|
WCHAR Executable[MAX_PATH], CommandLineBuf[512], SecurityBuf[512];
|
||||||
|
PWSTR CommandLine, Security;
|
||||||
|
DWORD JobControl;
|
||||||
|
PSECURITY_DESCRIPTOR SecurityDescriptor = 0;
|
||||||
|
PWSTR Argv[10];
|
||||||
|
STARTUPINFOW StartupInfo;
|
||||||
|
PROCESS_INFORMATION ProcessInfo;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
*PSvcInstance = 0;
|
||||||
|
|
||||||
|
lstrcpyW(CommandLineBuf, L"%0 ");
|
||||||
|
lstrcpyW(SecurityBuf, L"O:SYG:SY");
|
||||||
|
|
||||||
|
if (Argc > sizeof Argv / sizeof Argv[0] - 1)
|
||||||
|
Argc = sizeof Argv / sizeof Argv[0] - 1;
|
||||||
|
memcpy(Argv + 1, Argv0, Argc * sizeof(PWSTR));
|
||||||
|
Argv[0] = 0;
|
||||||
|
Argc++;
|
||||||
|
|
||||||
|
memset(&StartupInfo, 0, sizeof StartupInfo);
|
||||||
|
memset(&ProcessInfo, 0, sizeof ProcessInfo);
|
||||||
|
|
||||||
|
EnterCriticalSection(&SvcInstanceLock);
|
||||||
|
|
||||||
|
if (0 != SvcInstanceLookup(ClassName, InstanceName))
|
||||||
|
{
|
||||||
|
Result = STATUS_OBJECT_NAME_COLLISION;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
RegResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"" REGKEY, 0, KEY_READ, &RegKey);
|
||||||
|
if (ERROR_SUCCESS != RegResult)
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(RegResult);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
RegSize = sizeof Executable;
|
||||||
|
Executable[0] = L'\0';
|
||||||
|
RegResult = RegGetValueW(RegKey, ClassName, L"Executable", RRF_RT_REG_SZ, 0,
|
||||||
|
Executable, &RegSize);
|
||||||
|
if (ERROR_SUCCESS != RegResult)
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(RegResult);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
Argv[0] = Executable;
|
||||||
|
|
||||||
|
CommandLine = CommandLineBuf + lstrlenW(CommandLineBuf);
|
||||||
|
RegSize = (DWORD)(sizeof CommandLineBuf - (CommandLine - CommandLineBuf) * sizeof(WCHAR));
|
||||||
|
RegResult = RegGetValueW(RegKey, ClassName, L"CommandLine", RRF_RT_REG_SZ, 0,
|
||||||
|
CommandLine, &RegSize);
|
||||||
|
if (ERROR_SUCCESS != RegResult && ERROR_FILE_NOT_FOUND != RegResult)
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(RegResult);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (ERROR_FILE_NOT_FOUND == RegResult)
|
||||||
|
CommandLine[-1] = L'\0';
|
||||||
|
CommandLine = CommandLineBuf;
|
||||||
|
|
||||||
|
Security = SecurityBuf + lstrlenW(SecurityBuf);
|
||||||
|
RegSize = (DWORD)(sizeof SecurityBuf - (Security - SecurityBuf) * sizeof(WCHAR));
|
||||||
|
RegResult = RegGetValueW(RegKey, ClassName, L"Security", RRF_RT_REG_SZ, 0,
|
||||||
|
Security, &RegSize);
|
||||||
|
if (ERROR_SUCCESS != RegResult && ERROR_FILE_NOT_FOUND != RegResult)
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(RegResult);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
RegSize = sizeof JobControl;
|
||||||
|
JobControl = 1; /* default is YES! */
|
||||||
|
RegResult = RegGetValueW(RegKey, ClassName, L"JobControl", RRF_RT_REG_DWORD, 0,
|
||||||
|
&JobControl, &RegSize);
|
||||||
|
if (ERROR_SUCCESS != RegResult && ERROR_FILE_NOT_FOUND != RegResult)
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(RegResult);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
RegCloseKey(RegKey);
|
||||||
|
RegKey = 0;
|
||||||
|
|
||||||
|
if (L'\0' == Security[0])
|
||||||
|
lstrcpyW(Security, L"" SVC_INSTANCE_DEFAULT_SDDL);
|
||||||
|
if (L'D' == Security[0] && L':' == Security[1])
|
||||||
|
Security = SecurityBuf;
|
||||||
|
|
||||||
|
if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(Security, SDDL_REVISION_1,
|
||||||
|
&SecurityDescriptor, 0))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
FspDebugLogSD(__FUNCTION__ ": SDDL = %s\n", SecurityDescriptor);
|
||||||
|
|
||||||
|
Result = SvcInstanceAccessCheck(ClientToken, SERVICE_START, SecurityDescriptor);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
ClassNameSize = (lstrlenW(ClassName) + 1) * sizeof(WCHAR);
|
||||||
|
InstanceNameSize = (lstrlenW(InstanceName) + 1) * sizeof(WCHAR);
|
||||||
|
|
||||||
|
SvcInstance = MemAlloc(sizeof *SvcInstance + ClassNameSize + InstanceNameSize);
|
||||||
|
if (0 == SvcInstance)
|
||||||
|
{
|
||||||
|
Result = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(SvcInstance, 0, sizeof *SvcInstance);
|
||||||
|
memcpy(SvcInstance->Buffer, ClassName, ClassNameSize);
|
||||||
|
memcpy(SvcInstance->Buffer + ClassNameSize / sizeof(WCHAR), InstanceName, InstanceNameSize);
|
||||||
|
SvcInstance->ClassName = SvcInstance->Buffer;
|
||||||
|
SvcInstance->InstanceName = SvcInstance->Buffer + ClassNameSize / sizeof(WCHAR);
|
||||||
|
SvcInstance->SecurityDescriptor = SecurityDescriptor;
|
||||||
|
|
||||||
|
Result = SvcInstanceReplaceArguments(CommandLine, Argc, Argv, &SvcInstance->CommandLine);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
StartupInfo.cb = sizeof StartupInfo;
|
||||||
|
if (!CreateProcessW(Executable, SvcInstance->CommandLine, 0, 0, FALSE,
|
||||||
|
CREATE_SUSPENDED | CREATE_NEW_PROCESS_GROUP, 0, 0, &StartupInfo, &ProcessInfo))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
SvcInstance->ProcessId = ProcessInfo.dwProcessId;
|
||||||
|
SvcInstance->Process = ProcessInfo.hProcess;
|
||||||
|
|
||||||
|
if (!RegisterWaitForSingleObject(&SvcInstance->ProcessWait, SvcInstance->Process,
|
||||||
|
SvcInstanceTerminated, SvcInstance, INFINITE, WT_EXECUTEONLYONCE))
|
||||||
|
{
|
||||||
|
Result = FspNtStatusFromWin32(GetLastError());
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != Job && JobControl)
|
||||||
|
{
|
||||||
|
if (!AssignProcessToJobObject(Job, SvcInstance->Process))
|
||||||
|
FspServiceLog(EVENTLOG_WARNING_TYPE,
|
||||||
|
L"Ignorning error: AssignProcessToJobObject = %ld", GetLastError());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ONCE THE PROCESS IS RESUMED NO MORE FAILURES ALLOWED!
|
||||||
|
*/
|
||||||
|
|
||||||
|
ResumeThread(ProcessInfo.hThread);
|
||||||
|
CloseHandle(ProcessInfo.hThread);
|
||||||
|
ProcessInfo.hThread = 0;
|
||||||
|
|
||||||
|
InsertTailList(&SvcInstanceList, &SvcInstance->ListEntry);
|
||||||
|
ResetEvent(SvcInstanceEvent);
|
||||||
|
|
||||||
|
*PSvcInstance = SvcInstance;
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
LocalFree(SecurityDescriptor);
|
||||||
|
|
||||||
|
if (0 != ProcessInfo.hThread)
|
||||||
|
CloseHandle(ProcessInfo.hThread);
|
||||||
|
|
||||||
|
if (0 != SvcInstance)
|
||||||
|
{
|
||||||
|
if (0 != SvcInstance->ProcessWait)
|
||||||
|
UnregisterWaitEx(SvcInstance->ProcessWait, 0);
|
||||||
|
|
||||||
|
if (0 != SvcInstance->Process)
|
||||||
|
{
|
||||||
|
TerminateProcess(SvcInstance->Process, 0);
|
||||||
|
CloseHandle(SvcInstance->Process);
|
||||||
|
}
|
||||||
|
|
||||||
|
MemFree(SvcInstance->CommandLine);
|
||||||
|
MemFree(SvcInstance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != RegKey)
|
||||||
|
RegCloseKey(RegKey);
|
||||||
|
|
||||||
|
LeaveCriticalSection(&SvcInstanceLock);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID SvcInstanceDelete(SVC_INSTANCE *SvcInstance)
|
||||||
|
{
|
||||||
|
EnterCriticalSection(&SvcInstanceLock);
|
||||||
|
if (RemoveEntryList(&SvcInstance->ListEntry))
|
||||||
|
SetEvent(SvcInstanceEvent);
|
||||||
|
LeaveCriticalSection(&SvcInstanceLock);
|
||||||
|
|
||||||
|
if (0 != SvcInstance->ProcessWait)
|
||||||
|
UnregisterWaitEx(SvcInstance->ProcessWait, 0);
|
||||||
|
if (0 != SvcInstance->Process)
|
||||||
|
CloseHandle(SvcInstance->Process);
|
||||||
|
|
||||||
|
LocalFree(SvcInstance->SecurityDescriptor);
|
||||||
|
|
||||||
|
MemFree(SvcInstance->CommandLine);
|
||||||
|
MemFree(SvcInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID CALLBACK SvcInstanceTerminated(PVOID Context, BOOLEAN Timeout)
|
||||||
|
{
|
||||||
|
SVC_INSTANCE *SvcInstance = Context;
|
||||||
|
|
||||||
|
SvcInstanceDelete(SvcInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS SvcInstanceStart(HANDLE ClientToken,
|
||||||
|
PWSTR ClassName, PWSTR InstanceName, ULONG Argc, PWSTR *Argv, HANDLE Job)
|
||||||
|
{
|
||||||
|
SVC_INSTANCE *SvcInstance;
|
||||||
|
|
||||||
|
return SvcInstanceCreate(ClientToken, ClassName, InstanceName, Argc, Argv, Job, &SvcInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS SvcInstanceStop(HANDLE ClientToken,
|
||||||
|
PWSTR ClassName, PWSTR InstanceName)
|
||||||
|
{
|
||||||
|
SVC_INSTANCE *SvcInstance;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
EnterCriticalSection(&SvcInstanceLock);
|
||||||
|
|
||||||
|
SvcInstance = SvcInstanceLookup(ClassName, InstanceName);
|
||||||
|
if (0 == SvcInstance)
|
||||||
|
{
|
||||||
|
Result = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = SvcInstanceAccessCheck(ClientToken, SERVICE_STOP, SvcInstance->SecurityDescriptor);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
KillProcess(SvcInstance->ProcessId, SvcInstance->Process, LAUNCHER_KILL_TIMEOUT);
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
LeaveCriticalSection(&SvcInstanceLock);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS SvcInstanceGetInfo(HANDLE ClientToken,
|
||||||
|
PWSTR ClassName, PWSTR InstanceName, PWSTR Buffer, PULONG PSize)
|
||||||
|
{
|
||||||
|
SVC_INSTANCE *SvcInstance;
|
||||||
|
PWSTR P = Buffer;
|
||||||
|
ULONG ClassNameSize, InstanceNameSize, CommandLineSize;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
EnterCriticalSection(&SvcInstanceLock);
|
||||||
|
|
||||||
|
SvcInstance = SvcInstanceLookup(ClassName, InstanceName);
|
||||||
|
if (0 == SvcInstance)
|
||||||
|
{
|
||||||
|
Result = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = SvcInstanceAccessCheck(ClientToken, SERVICE_QUERY_STATUS, SvcInstance->SecurityDescriptor);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
ClassNameSize = lstrlenW(SvcInstance->ClassName) + 1;
|
||||||
|
InstanceNameSize = lstrlenW(SvcInstance->InstanceName) + 1;
|
||||||
|
CommandLineSize = lstrlenW(SvcInstance->CommandLine) + 1;
|
||||||
|
|
||||||
|
if (*PSize < (ClassNameSize + InstanceNameSize + CommandLineSize) * sizeof(WCHAR))
|
||||||
|
{
|
||||||
|
Result = STATUS_BUFFER_TOO_SMALL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(P, SvcInstance->ClassName, ClassNameSize * sizeof(WCHAR)); P += ClassNameSize;
|
||||||
|
memcpy(P, SvcInstance->InstanceName, InstanceNameSize * sizeof(WCHAR)); P += InstanceNameSize;
|
||||||
|
memcpy(P, SvcInstance->CommandLine, CommandLineSize * sizeof(WCHAR)); P += CommandLineSize;
|
||||||
|
|
||||||
|
*PSize = (ULONG)(P - Buffer) * sizeof(WCHAR);
|
||||||
|
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
LeaveCriticalSection(&SvcInstanceLock);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS SvcInstanceGetNameList(HANDLE ClientToken,
|
||||||
|
PWSTR Buffer, PULONG PSize)
|
||||||
|
{
|
||||||
|
SVC_INSTANCE *SvcInstance;
|
||||||
|
PLIST_ENTRY ListEntry;
|
||||||
|
PWSTR P = Buffer, BufferEnd = P + *PSize / sizeof(WCHAR);
|
||||||
|
ULONG ClassNameSize, InstanceNameSize;
|
||||||
|
|
||||||
|
EnterCriticalSection(&SvcInstanceLock);
|
||||||
|
|
||||||
|
for (ListEntry = SvcInstanceList.Flink;
|
||||||
|
&SvcInstanceList != ListEntry;
|
||||||
|
ListEntry = ListEntry->Flink)
|
||||||
|
{
|
||||||
|
SvcInstance = CONTAINING_RECORD(ListEntry, SVC_INSTANCE, ListEntry);
|
||||||
|
|
||||||
|
ClassNameSize = lstrlenW(SvcInstance->ClassName) + 1;
|
||||||
|
InstanceNameSize = lstrlenW(SvcInstance->InstanceName) + 1;
|
||||||
|
|
||||||
|
if (BufferEnd < P + ClassNameSize + InstanceNameSize)
|
||||||
|
break;
|
||||||
|
|
||||||
|
memcpy(P, SvcInstance->ClassName, ClassNameSize * sizeof(WCHAR)); P += ClassNameSize;
|
||||||
|
memcpy(P, SvcInstance->InstanceName, InstanceNameSize * sizeof(WCHAR)); P += InstanceNameSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
LeaveCriticalSection(&SvcInstanceLock);
|
||||||
|
|
||||||
|
*PSize = (ULONG)(P - Buffer) * sizeof(WCHAR);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS SvcInstanceStopAndWaitAll(VOID)
|
||||||
|
{
|
||||||
|
SVC_INSTANCE *SvcInstance;
|
||||||
|
PLIST_ENTRY ListEntry;
|
||||||
|
|
||||||
|
EnterCriticalSection(&SvcInstanceLock);
|
||||||
|
|
||||||
|
for (ListEntry = SvcInstanceList.Flink;
|
||||||
|
&SvcInstanceList != ListEntry;
|
||||||
|
ListEntry = ListEntry->Flink)
|
||||||
|
{
|
||||||
|
SvcInstance = CONTAINING_RECORD(ListEntry, SVC_INSTANCE, ListEntry);
|
||||||
|
|
||||||
|
KillProcess(SvcInstance->ProcessId, SvcInstance->Process, LAUNCHER_KILL_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
LeaveCriticalSection(&SvcInstanceLock);
|
||||||
|
|
||||||
|
WaitForSingleObject(SvcInstanceEvent, LAUNCHER_STOP_TIMEOUT);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HANDLE SvcJob, SvcThread, SvcEvent;
|
||||||
|
static DWORD SvcThreadId;
|
||||||
|
static HANDLE SvcPipe = INVALID_HANDLE_VALUE;
|
||||||
|
static OVERLAPPED SvcOverlapped;
|
||||||
|
|
||||||
|
static DWORD WINAPI SvcPipeServer(PVOID Context);
|
||||||
|
static VOID SvcPipeTransact(HANDLE ClientToken, PWSTR PipeBuf, PULONG PSize);
|
||||||
|
|
||||||
|
static NTSTATUS SvcStart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
||||||
|
{
|
||||||
|
SECURITY_ATTRIBUTES SecurityAttributes = { 0 };
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate a console in case we are running as a service without one.
|
||||||
|
* This will ensure that we can send console control events to service instances.
|
||||||
|
*/
|
||||||
|
if (AllocConsole())
|
||||||
|
ShowWindow(GetConsoleWindow(), SW_HIDE);
|
||||||
|
|
||||||
|
InitializeCriticalSection(&SvcInstanceLock);
|
||||||
|
|
||||||
|
SecurityAttributes.nLength = sizeof SecurityAttributes;
|
||||||
|
SecurityAttributes.bInheritHandle = FALSE;
|
||||||
|
if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(L"" LAUNCHER_PIPE_SDDL, SDDL_REVISION_1,
|
||||||
|
&SecurityAttributes.lpSecurityDescriptor, 0))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
FspDebugLogSD(__FUNCTION__ ": SDDL = %s\n", SecurityAttributes.lpSecurityDescriptor);
|
||||||
|
|
||||||
|
SvcInstanceEvent = CreateEventW(0, TRUE, TRUE, 0);
|
||||||
|
if (0 == SvcInstanceEvent)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
SvcJob = CreateJobObjectW(0, 0);
|
||||||
|
if (0 != SvcJob)
|
||||||
|
{
|
||||||
|
JOBOBJECT_EXTENDED_LIMIT_INFORMATION LimitInfo;
|
||||||
|
|
||||||
|
memset(&LimitInfo, 0, sizeof LimitInfo);
|
||||||
|
LimitInfo.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
|
||||||
|
if (!SetInformationJobObject(SvcJob, JobObjectExtendedLimitInformation,
|
||||||
|
&LimitInfo, sizeof LimitInfo))
|
||||||
|
{
|
||||||
|
CloseHandle(SvcJob);
|
||||||
|
SvcJob = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SvcEvent = CreateEventW(0, TRUE, FALSE, 0);
|
||||||
|
if (0 == SvcEvent)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
SvcOverlapped.hEvent = CreateEventW(0, TRUE, FALSE, 0);
|
||||||
|
if (0 == SvcOverlapped.hEvent)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
SvcPipe = CreateNamedPipeW(L"" LAUNCHER_PIPE_NAME,
|
||||||
|
PIPE_ACCESS_DUPLEX |
|
||||||
|
FILE_FLAG_FIRST_PIPE_INSTANCE | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_OVERLAPPED,
|
||||||
|
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS,
|
||||||
|
1, LAUNCHER_PIPE_BUFFER_SIZE, LAUNCHER_PIPE_BUFFER_SIZE, LAUNCHER_PIPE_DEFAULT_TIMEOUT,
|
||||||
|
&SecurityAttributes);
|
||||||
|
if (INVALID_HANDLE_VALUE == SvcPipe)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
SvcThread = CreateThread(0, 0, SvcPipeServer, Service, 0, &SvcThreadId);
|
||||||
|
if (0 == SvcThread)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
LocalFree(SecurityAttributes.lpSecurityDescriptor);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
DWORD LastError = GetLastError();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The OS will cleanup for us. So there is no need to explicitly release these resources.
|
||||||
|
*/
|
||||||
|
#if 0
|
||||||
|
if (0 != SvcThread)
|
||||||
|
CloseHandle(SvcThread);
|
||||||
|
|
||||||
|
if (INVALID_HANDLE_VALUE != SvcPipe)
|
||||||
|
CloseHandle(SvcPipe);
|
||||||
|
|
||||||
|
if (0 != SvcOverlapped.hEvent)
|
||||||
|
CloseHandle(SvcOverlapped.hEvent);
|
||||||
|
|
||||||
|
if (0 != SvcEvent)
|
||||||
|
CloseHandle(SvcEvent);
|
||||||
|
|
||||||
|
if (0 != SvcJob)
|
||||||
|
CloseHandle(SvcJob);
|
||||||
|
|
||||||
|
if (0 != SvcInstanceEvent)
|
||||||
|
CloseHandle(SvcInstanceEvent);
|
||||||
|
|
||||||
|
LocalFree(SecurityAttributes.lpSecurityDescriptor);
|
||||||
|
|
||||||
|
DeleteCriticalSection(&SvcInstanceLock);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return FspNtStatusFromWin32(LastError);
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS SvcStop(FSP_SERVICE *Service)
|
||||||
|
{
|
||||||
|
if (GetCurrentThreadId() != SvcThreadId)
|
||||||
|
{
|
||||||
|
SetEvent(SvcEvent);
|
||||||
|
FspServiceRequestTime(Service, LAUNCHER_STOP_TIMEOUT);
|
||||||
|
WaitForSingleObject(SvcThread, LAUNCHER_STOP_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The OS will cleanup for us. So there is no need to explicitly release these resources.
|
||||||
|
*
|
||||||
|
* This also protects us from scenarios where not all child processes terminate timely
|
||||||
|
* and KillProcess decides to terminate them forcibly, thus creating racing conditions
|
||||||
|
* with SvcInstanceTerminated.
|
||||||
|
*/
|
||||||
|
#if 0
|
||||||
|
if (0 != SvcThread)
|
||||||
|
CloseHandle(SvcThread);
|
||||||
|
|
||||||
|
if (INVALID_HANDLE_VALUE != SvcPipe)
|
||||||
|
CloseHandle(SvcPipe);
|
||||||
|
|
||||||
|
if (0 != SvcOverlapped.hEvent)
|
||||||
|
CloseHandle(SvcOverlapped.hEvent);
|
||||||
|
|
||||||
|
if (0 != SvcEvent)
|
||||||
|
CloseHandle(SvcEvent);
|
||||||
|
|
||||||
|
if (0 != SvcJob)
|
||||||
|
CloseHandle(SvcJob);
|
||||||
|
|
||||||
|
if (0 != SvcInstanceEvent)
|
||||||
|
CloseHandle(SvcInstanceEvent);
|
||||||
|
|
||||||
|
DeleteCriticalSection(&SvcInstanceLock);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline DWORD SvcPipeWaitResult(BOOL Success, HANDLE StopEvent,
|
||||||
|
HANDLE Handle, OVERLAPPED *Overlapped, PDWORD PBytesTransferred)
|
||||||
|
{
|
||||||
|
HANDLE WaitObjects[2];
|
||||||
|
DWORD WaitResult;
|
||||||
|
|
||||||
|
if (!Success && ERROR_IO_PENDING != GetLastError())
|
||||||
|
return GetLastError();
|
||||||
|
|
||||||
|
WaitObjects[0] = StopEvent;
|
||||||
|
WaitObjects[1] = Overlapped->hEvent;
|
||||||
|
WaitResult = WaitForMultipleObjects(2, WaitObjects, FALSE, INFINITE);
|
||||||
|
if (WAIT_OBJECT_0 == WaitResult)
|
||||||
|
return -1; /* special: stop thread */
|
||||||
|
else if (WAIT_OBJECT_0 + 1 == WaitResult)
|
||||||
|
{
|
||||||
|
if (!GetOverlappedResult(Handle, Overlapped, PBytesTransferred, TRUE))
|
||||||
|
return GetLastError();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return GetLastError();
|
||||||
|
}
|
||||||
|
|
||||||
|
static DWORD WINAPI SvcPipeServer(PVOID Context)
|
||||||
|
{
|
||||||
|
static PWSTR LoopErrorMessage =
|
||||||
|
L"Error in service main loop (%s = %ld). Exiting...";
|
||||||
|
static PWSTR LoopWarningMessage =
|
||||||
|
L"Error in service main loop (%s = %ld). Continuing...";
|
||||||
|
FSP_SERVICE *Service = Context;
|
||||||
|
PWSTR PipeBuf = 0;
|
||||||
|
HANDLE ClientToken;
|
||||||
|
DWORD LastError, BytesTransferred;
|
||||||
|
|
||||||
|
PipeBuf = MemAlloc(LAUNCHER_PIPE_BUFFER_SIZE);
|
||||||
|
if (0 == PipeBuf)
|
||||||
|
{
|
||||||
|
FspServiceSetExitCode(Service, ERROR_NO_SYSTEM_RESOURCES);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
LastError = SvcPipeWaitResult(
|
||||||
|
ConnectNamedPipe(SvcPipe, &SvcOverlapped),
|
||||||
|
SvcEvent, SvcPipe, &SvcOverlapped, &BytesTransferred);
|
||||||
|
if (-1 == LastError)
|
||||||
|
break;
|
||||||
|
else if (0 != LastError &&
|
||||||
|
ERROR_PIPE_CONNECTED != LastError && ERROR_NO_DATA != LastError)
|
||||||
|
{
|
||||||
|
FspServiceLog(EVENTLOG_WARNING_TYPE, LoopWarningMessage,
|
||||||
|
L"ConnectNamedPipe", LastError);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
LastError = SvcPipeWaitResult(
|
||||||
|
ReadFile(SvcPipe, PipeBuf, LAUNCHER_PIPE_BUFFER_SIZE, &BytesTransferred, &SvcOverlapped),
|
||||||
|
SvcEvent, SvcPipe, &SvcOverlapped, &BytesTransferred);
|
||||||
|
if (-1 == LastError)
|
||||||
|
break;
|
||||||
|
else if (0 != LastError || sizeof(WCHAR) > BytesTransferred)
|
||||||
|
{
|
||||||
|
DisconnectNamedPipe(SvcPipe);
|
||||||
|
if (0 != LastError)
|
||||||
|
FspServiceLog(EVENTLOG_WARNING_TYPE, LoopWarningMessage,
|
||||||
|
L"ReadFile", LastError);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClientToken = 0;
|
||||||
|
if (!ImpersonateNamedPipeClient(SvcPipe) ||
|
||||||
|
!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &ClientToken) ||
|
||||||
|
!RevertToSelf())
|
||||||
|
{
|
||||||
|
LastError = GetLastError();
|
||||||
|
if (0 == ClientToken)
|
||||||
|
{
|
||||||
|
CloseHandle(ClientToken);
|
||||||
|
DisconnectNamedPipe(SvcPipe);
|
||||||
|
FspServiceLog(EVENTLOG_WARNING_TYPE, LoopWarningMessage,
|
||||||
|
L"ImpersonateNamedPipeClient||OpenThreadToken", LastError);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CloseHandle(ClientToken);
|
||||||
|
DisconnectNamedPipe(SvcPipe);
|
||||||
|
FspServiceLog(EVENTLOG_ERROR_TYPE, LoopErrorMessage,
|
||||||
|
L"RevertToSelf", LastError);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SvcPipeTransact(ClientToken, PipeBuf, &BytesTransferred);
|
||||||
|
|
||||||
|
CloseHandle(ClientToken);
|
||||||
|
|
||||||
|
LastError = SvcPipeWaitResult(
|
||||||
|
WriteFile(SvcPipe, PipeBuf, BytesTransferred, &BytesTransferred, &SvcOverlapped),
|
||||||
|
SvcEvent, SvcPipe, &SvcOverlapped, &BytesTransferred);
|
||||||
|
if (-1 == LastError)
|
||||||
|
break;
|
||||||
|
else if (0 != LastError)
|
||||||
|
{
|
||||||
|
DisconnectNamedPipe(SvcPipe);
|
||||||
|
FspServiceLog(EVENTLOG_WARNING_TYPE, LoopWarningMessage,
|
||||||
|
L"WriteFile", LastError);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
DisconnectNamedPipe(SvcPipe);
|
||||||
|
}
|
||||||
|
|
||||||
|
exit:
|
||||||
|
MemFree(PipeBuf);
|
||||||
|
|
||||||
|
SvcInstanceStopAndWaitAll();
|
||||||
|
|
||||||
|
FspServiceStop(Service);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline PWSTR SvcPipeTransactGetPart(PWSTR *PP, PWSTR PipeBufEnd)
|
||||||
|
{
|
||||||
|
PWSTR PipeBufBeg = *PP, P;
|
||||||
|
|
||||||
|
for (P = PipeBufBeg; PipeBufEnd > P && *P; P++)
|
||||||
|
;
|
||||||
|
|
||||||
|
if (PipeBufEnd > P)
|
||||||
|
{
|
||||||
|
*PP = P + 1;
|
||||||
|
return PipeBufBeg;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*PP = P;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline VOID SvcPipeTransactResult(NTSTATUS Result, PWSTR PipeBuf, PULONG PSize)
|
||||||
|
{
|
||||||
|
if (NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
*PipeBuf = LauncherSuccess;
|
||||||
|
*PSize += sizeof(WCHAR);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*PSize = (wsprintfW(PipeBuf, L"%c%ld", LauncherFailure, FspWin32FromNtStatus(Result)) + 1) *
|
||||||
|
sizeof(WCHAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID SvcPipeTransact(HANDLE ClientToken, PWSTR PipeBuf, PULONG PSize)
|
||||||
|
{
|
||||||
|
if (sizeof(WCHAR) > *PSize)
|
||||||
|
return;
|
||||||
|
|
||||||
|
PWSTR P = PipeBuf, PipeBufEnd = PipeBuf + *PSize / sizeof(WCHAR);
|
||||||
|
PWSTR ClassName, InstanceName;
|
||||||
|
ULONG Argc; PWSTR Argv[9];
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
|
*PSize = 0;
|
||||||
|
|
||||||
|
switch (*P++)
|
||||||
|
{
|
||||||
|
case LauncherSvcInstanceStart:
|
||||||
|
ClassName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
||||||
|
InstanceName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
||||||
|
for (Argc = 0; sizeof Argv / sizeof Argv[0] > Argc; Argc++)
|
||||||
|
if (0 == (Argv[Argc] = SvcPipeTransactGetPart(&P, PipeBufEnd)))
|
||||||
|
break;
|
||||||
|
|
||||||
|
Result = STATUS_INVALID_PARAMETER;
|
||||||
|
if (0 != ClassName && 0 != InstanceName)
|
||||||
|
Result = SvcInstanceStart(ClientToken, ClassName, InstanceName, Argc, Argv, SvcJob);
|
||||||
|
|
||||||
|
SvcPipeTransactResult(Result, PipeBuf, PSize);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LauncherSvcInstanceStop:
|
||||||
|
ClassName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
||||||
|
InstanceName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
||||||
|
|
||||||
|
Result = STATUS_INVALID_PARAMETER;
|
||||||
|
if (0 != ClassName && 0 != InstanceName)
|
||||||
|
Result = SvcInstanceStop(ClientToken, ClassName, InstanceName);
|
||||||
|
|
||||||
|
SvcPipeTransactResult(Result, PipeBuf, PSize);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LauncherSvcInstanceInfo:
|
||||||
|
ClassName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
||||||
|
InstanceName = SvcPipeTransactGetPart(&P, PipeBufEnd);
|
||||||
|
|
||||||
|
Result = STATUS_INVALID_PARAMETER;
|
||||||
|
if (0 != ClassName && 0 != InstanceName)
|
||||||
|
{
|
||||||
|
*PSize = LAUNCHER_PIPE_BUFFER_SIZE - 1;
|
||||||
|
Result = SvcInstanceGetInfo(ClientToken, ClassName, InstanceName, PipeBuf + 1, PSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
SvcPipeTransactResult(Result, PipeBuf, PSize);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LauncherSvcInstanceList:
|
||||||
|
*PSize = LAUNCHER_PIPE_BUFFER_SIZE - 1;
|
||||||
|
Result = SvcInstanceGetNameList(ClientToken, PipeBuf + 1, PSize);
|
||||||
|
|
||||||
|
SvcPipeTransactResult(Result, PipeBuf, PSize);
|
||||||
|
break;
|
||||||
|
|
||||||
|
#if !defined(NDEBUG)
|
||||||
|
case LauncherQuit:
|
||||||
|
SetEvent(SvcEvent);
|
||||||
|
|
||||||
|
SvcPipeTransactResult(STATUS_SUCCESS, PipeBuf, PSize);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
SvcPipeTransactResult(STATUS_INVALID_PARAMETER, PipeBuf, PSize);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int wmain(int argc, wchar_t **argv)
|
||||||
|
{
|
||||||
|
return FspServiceRun(L"" PROGNAME, SvcStart, SvcStop, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wmainCRTStartup(void)
|
||||||
|
{
|
||||||
|
extern HANDLE ProcessHeap;
|
||||||
|
ProcessHeap = GetProcessHeap();
|
||||||
|
if (0 == ProcessHeap)
|
||||||
|
ExitProcess(GetLastError());
|
||||||
|
|
||||||
|
ExitProcess(wmain(0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE ProcessHeap;
|
65
src/launcher/launcher.h
Normal file
65
src/launcher/launcher.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/**
|
||||||
|
* @file launcher/launcher.h
|
||||||
|
*
|
||||||
|
* @copyright 2015-2016 Bill Zissimopoulos
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* This file is part of WinFsp.
|
||||||
|
*
|
||||||
|
* You can redistribute it and/or modify it under the terms of the
|
||||||
|
* GNU Affero General Public License version 3 as published by the
|
||||||
|
* Free Software Foundation.
|
||||||
|
*
|
||||||
|
* Licensees holding a valid commercial license may use this file in
|
||||||
|
* accordance with the commercial license agreement provided with the
|
||||||
|
* software.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WINFSP_LAUNCHER_LAUNCHER_H_INCLUDED
|
||||||
|
#define WINFSP_LAUNCHER_LAUNCHER_H_INCLUDED
|
||||||
|
|
||||||
|
#include <winfsp/winfsp.h>
|
||||||
|
#include <shared/minimal.h>
|
||||||
|
|
||||||
|
#define LAUNCHER_STOP_TIMEOUT 5500
|
||||||
|
#define LAUNCHER_KILL_TIMEOUT 5000
|
||||||
|
|
||||||
|
#define LAUNCHER_PIPE_NAME "\\\\.\\pipe\\WinFsp.{14E7137D-22B4-437A-B0C1-D21D1BDF3767}"
|
||||||
|
#define LAUNCHER_PIPE_BUFFER_SIZE 2048
|
||||||
|
#define LAUNCHER_PIPE_DEFAULT_TIMEOUT 3000
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* FILE_CREATE_PIPE_INSTANCE right to Everyone to disallow the creation of additional
|
||||||
|
* pipe instances.
|
||||||
|
*/
|
||||||
|
#define LAUNCHER_PIPE_SDDL "O:SYG:SYD:P(A;;GA;;;SY)(A;;GA;;;BA)(A;;GRDCCR;;;WD)"
|
||||||
|
#define LAUNCHER_PIPE_OWNER ((PSID)WinLocalSystemSid)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The default service instance SDDL gives full access to LocalSystem and Administrators.
|
||||||
|
* The only possible service instance rights are as follows:
|
||||||
|
* RP SERVICE_START
|
||||||
|
* WP SERVICE_STOP
|
||||||
|
* LC SERVICE_QUERY_STATUS
|
||||||
|
*
|
||||||
|
* To create a service that can be started, stopped or queried by Everyone, you can set
|
||||||
|
* the following SDDL:
|
||||||
|
* D:P(A;;RPWPLC;;;WD)
|
||||||
|
*/
|
||||||
|
#define SVC_INSTANCE_DEFAULT_SDDL "D:P(A;;RPWPLC;;;SY)(A;;RPWPLC;;;BA)"
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
LauncherSvcInstanceStart = 'S', /* requires: SERVICE_START */
|
||||||
|
LauncherSvcInstanceStop = 'T', /* requires: SERVICE_STOP */
|
||||||
|
LauncherSvcInstanceInfo = 'I', /* requires: SERVICE_QUERY_STATUS */
|
||||||
|
LauncherSvcInstanceList = 'L', /* requires: none*/
|
||||||
|
LauncherQuit = 'Q', /* DEBUG version only */
|
||||||
|
|
||||||
|
LauncherSuccess = '$',
|
||||||
|
LauncherFailure = '!',
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
87
src/shared/minimal.h
Normal file
87
src/shared/minimal.h
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/**
|
||||||
|
* @file shared/minimal.h
|
||||||
|
*
|
||||||
|
* @copyright 2015-2016 Bill Zissimopoulos
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* This file is part of WinFsp.
|
||||||
|
*
|
||||||
|
* You can redistribute it and/or modify it under the terms of the
|
||||||
|
* GNU Affero General Public License version 3 as published by the
|
||||||
|
* Free Software Foundation.
|
||||||
|
*
|
||||||
|
* Licensees holding a valid commercial license may use this file in
|
||||||
|
* accordance with the commercial license agreement provided with the
|
||||||
|
* software.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WINFSP_SHARED_MINIMAL_H_INCLUDED
|
||||||
|
#define WINFSP_SHARED_MINIMAL_H_INCLUDED
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Eliminate dependency on the MSVCRT libraries.
|
||||||
|
*
|
||||||
|
* For this to work the following project settings must be set:
|
||||||
|
* - "C/C++ > General > SDL checks" must be empty (not "Yes" or "No").
|
||||||
|
* - "C/C++ > Code Generation > Basic Runtime Checks" must be set to "Default"
|
||||||
|
* - "C/C++ > Code Generation > Security Check" must be disabled (/GS-).
|
||||||
|
* - "Linker > Input > Ignore All Default Libraries" must be "Yes".
|
||||||
|
*/
|
||||||
|
|
||||||
|
#undef RtlFillMemory
|
||||||
|
#undef RtlMoveMemory
|
||||||
|
NTSYSAPI VOID NTAPI RtlFillMemory(VOID *Destination, DWORD Length, BYTE Fill);
|
||||||
|
NTSYSAPI VOID NTAPI RtlMoveMemory(VOID *Destination, CONST VOID *Source, DWORD Length);
|
||||||
|
|
||||||
|
#pragma function(memcpy)
|
||||||
|
#pragma function(memset)
|
||||||
|
static inline
|
||||||
|
void *memcpy(void *dst, const void *src, size_t siz)
|
||||||
|
{
|
||||||
|
RtlMoveMemory(dst, src, (DWORD)siz);
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
static inline
|
||||||
|
void *memset(void *dst, int val, size_t siz)
|
||||||
|
{
|
||||||
|
RtlFillMemory(dst, (DWORD)siz, val);
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline PVOID MemAlloc(SIZE_T Size)
|
||||||
|
{
|
||||||
|
extern HANDLE ProcessHeap;
|
||||||
|
return HeapAlloc(ProcessHeap, 0, Size);
|
||||||
|
}
|
||||||
|
static inline VOID MemFree(PVOID Pointer)
|
||||||
|
{
|
||||||
|
extern HANDLE ProcessHeap;
|
||||||
|
if (0 != Pointer)
|
||||||
|
HeapFree(ProcessHeap, 0, Pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static FORCEINLINE
|
||||||
|
VOID InsertTailList(PLIST_ENTRY ListHead, PLIST_ENTRY Entry)
|
||||||
|
{
|
||||||
|
PLIST_ENTRY Blink;
|
||||||
|
|
||||||
|
Blink = ListHead->Blink;
|
||||||
|
Entry->Flink = ListHead;
|
||||||
|
Entry->Blink = Blink;
|
||||||
|
Blink->Flink = Entry;
|
||||||
|
ListHead->Blink = Entry;
|
||||||
|
}
|
||||||
|
static FORCEINLINE
|
||||||
|
BOOLEAN RemoveEntryList(PLIST_ENTRY Entry)
|
||||||
|
{
|
||||||
|
PLIST_ENTRY Blink;
|
||||||
|
PLIST_ENTRY Flink;
|
||||||
|
|
||||||
|
Flink = Entry->Flink;
|
||||||
|
Blink = Entry->Blink;
|
||||||
|
Blink->Flink = Flink;
|
||||||
|
Flink->Blink = Blink;
|
||||||
|
return Flink == Blink;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -28,7 +28,7 @@
|
|||||||
#pragma warning(disable:4100) /* unreferenced formal parameter */
|
#pragma warning(disable:4100) /* unreferenced formal parameter */
|
||||||
#pragma warning(disable:4200) /* zero-sized array in struct/union */
|
#pragma warning(disable:4200) /* zero-sized array in struct/union */
|
||||||
|
|
||||||
#define DRIVER_NAME "WinFsp"
|
#define DRIVER_NAME FSP_FSCTL_DRIVER_NAME
|
||||||
|
|
||||||
/* IoCreateDeviceSecure default SDDL's */
|
/* IoCreateDeviceSecure default SDDL's */
|
||||||
#define FSP_FSCTL_DEVICE_SDDL "D:P(A;;GA;;;SY)(A;;GA;;;BA)(A;;GR;;;WD)"
|
#define FSP_FSCTL_DEVICE_SDDL "D:P(A;;GA;;;SY)(A;;GA;;;BA)(A;;GR;;;WD)"
|
||||||
|
37
src/sys/version.rc
Normal file
37
src/sys/version.rc
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#include <winver.h>
|
||||||
|
|
||||||
|
#define STR(x) STR_(x)
|
||||||
|
#define STR_(x) #x
|
||||||
|
|
||||||
|
VS_VERSION_INFO VERSIONINFO
|
||||||
|
FILEVERSION MyVersionWithCommas
|
||||||
|
PRODUCTVERSION MyVersionWithCommas
|
||||||
|
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||||
|
#ifdef _DEBUG
|
||||||
|
FILEFLAGS VS_FF_DEBUG
|
||||||
|
#else
|
||||||
|
FILEFLAGS 0
|
||||||
|
#endif
|
||||||
|
FILEOS VOS_NT
|
||||||
|
FILETYPE VFT_DRV
|
||||||
|
FILESUBTYPE VFT2_DRV_SYSTEM
|
||||||
|
BEGIN
|
||||||
|
BLOCK "StringFileInfo"
|
||||||
|
BEGIN
|
||||||
|
BLOCK "040904b0"
|
||||||
|
BEGIN
|
||||||
|
VALUE "CompanyName", STR(MyCompanyName)
|
||||||
|
VALUE "FileDescription", STR(MyDescription)
|
||||||
|
VALUE "FileVersion", STR(MyVersion)
|
||||||
|
VALUE "InternalName", "winfsp.sys"
|
||||||
|
VALUE "LegalCopyright", STR(MyCopyright)
|
||||||
|
VALUE "OriginalFilename", "winfsp.sys"
|
||||||
|
VALUE "ProductName", STR(MyProductName)
|
||||||
|
VALUE "ProductVersion", STR(MyVersion)
|
||||||
|
END
|
||||||
|
END
|
||||||
|
BLOCK "VarFileInfo"
|
||||||
|
BEGIN
|
||||||
|
VALUE "Translation", 0x409, 1200
|
||||||
|
END
|
||||||
|
END
|
@ -693,7 +693,7 @@ NTSTATUS FspVolumeTransact(
|
|||||||
if (0 == ProcessIrp)
|
if (0 == ProcessIrp)
|
||||||
{
|
{
|
||||||
/* either IRP was canceled or a bogus Hint was provided */
|
/* either IRP was canceled or a bogus Hint was provided */
|
||||||
DEBUGLOG("BOGUS(Kind=%d, Hint=%p)", Response->Kind, (PVOID)Response->Hint);
|
DEBUGLOG("BOGUS(Kind=%d, Hint=%p)", Response->Kind, (PVOID)(UINT_PTR)Response->Hint);
|
||||||
Response = NextResponse;
|
Response = NextResponse;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
30
tools/DigiCert High Assurance EV Root CA.crt
Normal file
30
tools/DigiCert High Assurance EV Root CA.crt
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
-----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-----
|
29
tools/build.bat
Normal file
29
tools/build.bat
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
set Configuration=Release
|
||||||
|
set MsiName="WinFsp - Windows File System Proxy"
|
||||||
|
set CrossCert="%~dp0DigiCert High Assurance EV Root CA.crt"
|
||||||
|
set Issuer="DigiCert"
|
||||||
|
set Subject="Navimatics Corporation"
|
||||||
|
|
||||||
|
call "%VS140COMNTOOLS%\..\..\VC\vcvarsall.bat"
|
||||||
|
|
||||||
|
if not X%1==X set Configuration=%1
|
||||||
|
|
||||||
|
cd %~dp0..\build\VStudio
|
||||||
|
if exist build\ del /s/q build >nul
|
||||||
|
|
||||||
|
devenv winfsp.sln /build "%Configuration%|x64"
|
||||||
|
devenv winfsp.sln /build "%Configuration%|x86"
|
||||||
|
|
||||||
|
for %%f in (build\%Configuration%\winfsp-x64.sys build\%Configuration%\winfsp-x86.sys) do (
|
||||||
|
signtool sign /ac %CrossCert% /i %Issuer% /n %Subject% /fd sha1 /t http://timestamp.digicert.com %%f
|
||||||
|
signtool sign /as /ac %CrossCert% /i %Issuer% /n %Subject% /fd sha256 /tr http://timestamp.digicert.com /td sha256 %%f
|
||||||
|
)
|
||||||
|
|
||||||
|
devenv winfsp.sln /build "Installer.%Configuration%|x86"
|
||||||
|
|
||||||
|
for %%f in (build\%Configuration%\winfsp-*.msi) do (
|
||||||
|
signtool sign /ac %CrossCert% /i %Issuer% /n %Subject% /fd sha1 /t http://timestamp.digicert.com /d %MsiName% %%f
|
||||||
|
REM signtool sign /ac %CrossCert% /i %Issuer% /n %Subject% /fd sha256 /tr http://timestamp.digicert.com /td sha256 /d %MsiName% %%f
|
||||||
|
)
|
192
tst/memfs/memfs-main-old.c
Normal file
192
tst/memfs/memfs-main-old.c
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
/**
|
||||||
|
* @file memfs-main-old.c
|
||||||
|
*
|
||||||
|
* This file serves as an example that it is possible to create
|
||||||
|
* a WinFsp file system without using the FspService framework.
|
||||||
|
*
|
||||||
|
* Please note that this file is no longer maintained.
|
||||||
|
*
|
||||||
|
* @copyright 2015-2016 Bill Zissimopoulos
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* This file is part of WinFsp.
|
||||||
|
*
|
||||||
|
* You can redistribute it and/or modify it under the terms of the
|
||||||
|
* GNU Affero General Public License version 3 as published by the
|
||||||
|
* Free Software Foundation.
|
||||||
|
*
|
||||||
|
* Licensees holding a valid commercial license may use this file in
|
||||||
|
* accordance with the commercial license agreement provided with the
|
||||||
|
* software.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <winfsp/winfsp.h>
|
||||||
|
#include "memfs.h"
|
||||||
|
|
||||||
|
#define PROGNAME "memfs"
|
||||||
|
|
||||||
|
static void vwarn(const char *format, va_list ap)
|
||||||
|
{
|
||||||
|
char buf[1024];
|
||||||
|
/* wvsprintf is only safe with a 1024 byte buffer */
|
||||||
|
DWORD BytesTransferred;
|
||||||
|
|
||||||
|
wvsprintfA(buf, format, ap);
|
||||||
|
buf[sizeof buf - 1] = '\0';
|
||||||
|
|
||||||
|
WriteFile(GetStdHandle(STD_ERROR_HANDLE),
|
||||||
|
buf, (DWORD)strlen(buf),
|
||||||
|
&BytesTransferred, 0);
|
||||||
|
WriteFile(GetStdHandle(STD_ERROR_HANDLE),
|
||||||
|
"\n", 1,
|
||||||
|
&BytesTransferred, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void warn(const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, format);
|
||||||
|
vwarn(format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fail(const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, format);
|
||||||
|
vwarn(format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void usage(void)
|
||||||
|
{
|
||||||
|
static char usage[] = ""
|
||||||
|
"usage: %s OPTIONS\n"
|
||||||
|
"\n"
|
||||||
|
"options:\n"
|
||||||
|
" -t FileInfoTimeout [millis]\n"
|
||||||
|
" -n MaxFileNodes\n"
|
||||||
|
" -s MaxFileSize [bytes]\n"
|
||||||
|
" -S RootSddl [file rights: FA, etc; NO generic rights: GA, etc.]\n"
|
||||||
|
" -u \\Server\\Share [UNC prefix (single backslash)]\n"
|
||||||
|
" -m MountPoint [X:]\n";
|
||||||
|
|
||||||
|
warn(usage, PROGNAME);
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG argtol(wchar_t **argp, ULONG deflt)
|
||||||
|
{
|
||||||
|
if (0 == argp[0])
|
||||||
|
usage();
|
||||||
|
|
||||||
|
wchar_t *endp;
|
||||||
|
ULONG ul = wcstol(argp[0], &endp, 10);
|
||||||
|
return L'\0' != argp[0][0] && L'\0' == *endp ? ul : deflt;
|
||||||
|
}
|
||||||
|
|
||||||
|
static wchar_t *argtos(wchar_t **argp)
|
||||||
|
{
|
||||||
|
if (0 == argp[0])
|
||||||
|
usage();
|
||||||
|
|
||||||
|
return argp[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
static HANDLE MainEvent;
|
||||||
|
|
||||||
|
static BOOL WINAPI ConsoleCtrlHandler(DWORD CtrlType)
|
||||||
|
{
|
||||||
|
SetEvent(MainEvent);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int wmain(int argc, wchar_t **argv)
|
||||||
|
{
|
||||||
|
wchar_t **argp;
|
||||||
|
NTSTATUS Result;
|
||||||
|
MEMFS *Memfs;
|
||||||
|
ULONG Flags = MemfsDisk;
|
||||||
|
ULONG FileInfoTimeout = INFINITE;
|
||||||
|
ULONG MaxFileNodes = 1024;
|
||||||
|
ULONG MaxFileSize = 16 * 1024 * 1024;
|
||||||
|
PWSTR MountPoint = 0;
|
||||||
|
PWSTR VolumePrefix = 0;
|
||||||
|
PWSTR RootSddl = 0;
|
||||||
|
|
||||||
|
for (argp = argv + 1; 0 != argp[0]; argp++)
|
||||||
|
{
|
||||||
|
if (L'-' != argp[0][0])
|
||||||
|
break;
|
||||||
|
switch (argp[0][1])
|
||||||
|
{
|
||||||
|
case L'?':
|
||||||
|
usage();
|
||||||
|
break;
|
||||||
|
case L'm':
|
||||||
|
MountPoint = argtos(++argp);
|
||||||
|
break;
|
||||||
|
case L'n':
|
||||||
|
MaxFileNodes = argtol(++argp, MaxFileNodes);
|
||||||
|
break;
|
||||||
|
case L'S':
|
||||||
|
RootSddl = argtos(++argp);
|
||||||
|
break;
|
||||||
|
case L's':
|
||||||
|
MaxFileSize = argtol(++argp, MaxFileSize);
|
||||||
|
break;
|
||||||
|
case L't':
|
||||||
|
FileInfoTimeout = argtol(++argp, FileInfoTimeout);
|
||||||
|
break;
|
||||||
|
case L'u':
|
||||||
|
VolumePrefix = argtos(++argp);
|
||||||
|
Flags = MemfsNet;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != argp[0])
|
||||||
|
usage();
|
||||||
|
|
||||||
|
MainEvent = CreateEvent(0, TRUE, FALSE, 0);
|
||||||
|
if (0 == MainEvent)
|
||||||
|
fail("error: cannot create MainEvent");
|
||||||
|
|
||||||
|
Result = MemfsCreate(Flags, FileInfoTimeout, MaxFileNodes, MaxFileSize, VolumePrefix, RootSddl,
|
||||||
|
&Memfs);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
fail("error: cannot create MEMFS");
|
||||||
|
Result = MemfsStart(Memfs);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
fail("error: cannot start MEMFS");
|
||||||
|
Result = FspFileSystemSetMountPoint(MemfsFileSystem(Memfs), MountPoint);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
fail("error: cannot mount MEMFS");
|
||||||
|
MountPoint = FspFileSystemMountPoint(MemfsFileSystem(Memfs));
|
||||||
|
|
||||||
|
warn("%s -t %ld -n %ld -s %ld%s%S%s%S -m %S",
|
||||||
|
PROGNAME, FileInfoTimeout, MaxFileNodes, MaxFileSize,
|
||||||
|
RootSddl ? " -S " : "", RootSddl ? RootSddl : L"",
|
||||||
|
VolumePrefix ? " -u " : "", VolumePrefix ? VolumePrefix : L"",
|
||||||
|
MountPoint);
|
||||||
|
SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
|
||||||
|
if (WAIT_OBJECT_0 != WaitForSingleObject(MainEvent, INFINITE))
|
||||||
|
fail("error: cannot wait on MainEvent");
|
||||||
|
|
||||||
|
FspFileSystemRemoveMountPoint(MemfsFileSystem(Memfs));
|
||||||
|
MemfsStop(Memfs);
|
||||||
|
MemfsDelete(Memfs);
|
||||||
|
|
||||||
|
/* the OS will handle this! */
|
||||||
|
// CloseHandle(MainEvent);
|
||||||
|
// MainEvent = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -20,46 +20,116 @@
|
|||||||
|
|
||||||
#define PROGNAME "memfs"
|
#define PROGNAME "memfs"
|
||||||
|
|
||||||
static void vwarn(const char *format, va_list ap)
|
#define info(format, ...) FspServiceLog(EVENTLOG_INFORMATION_TYPE, format, __VA_ARGS__)
|
||||||
|
#define warn(format, ...) FspServiceLog(EVENTLOG_WARNING_TYPE, format, __VA_ARGS__)
|
||||||
|
#define fail(format, ...) FspServiceLog(EVENTLOG_ERROR_TYPE, format, __VA_ARGS__)
|
||||||
|
|
||||||
|
#define argtos(v) if (arge > ++argp) v = *argp; else goto usage
|
||||||
|
#define argtol(v) if (arge > ++argp) v = wcstol_deflt(*argp, v); else goto usage
|
||||||
|
|
||||||
|
static ULONG wcstol_deflt(wchar_t *w, ULONG deflt)
|
||||||
{
|
{
|
||||||
char buf[1024];
|
wchar_t *endp;
|
||||||
/* wvsprintf is only safe with a 1024 byte buffer */
|
ULONG ul = wcstol(w, &endp, 10);
|
||||||
DWORD BytesTransferred;
|
return L'\0' != w[0] && L'\0' == *endp ? ul : deflt;
|
||||||
|
|
||||||
wvsprintfA(buf, format, ap);
|
|
||||||
buf[sizeof buf - 1] = '\0';
|
|
||||||
|
|
||||||
WriteFile(GetStdHandle(STD_ERROR_HANDLE),
|
|
||||||
buf, (DWORD)strlen(buf),
|
|
||||||
&BytesTransferred, 0);
|
|
||||||
WriteFile(GetStdHandle(STD_ERROR_HANDLE),
|
|
||||||
"\n", 1,
|
|
||||||
&BytesTransferred, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void warn(const char *format, ...)
|
NTSTATUS SvcStart(FSP_SERVICE *Service, ULONG argc, PWSTR *argv)
|
||||||
{
|
{
|
||||||
va_list ap;
|
wchar_t **argp, **arge;
|
||||||
|
ULONG Flags = MemfsDisk;
|
||||||
|
ULONG FileInfoTimeout = INFINITE;
|
||||||
|
ULONG MaxFileNodes = 1024;
|
||||||
|
ULONG MaxFileSize = 16 * 1024 * 1024;
|
||||||
|
PWSTR MountPoint = 0;
|
||||||
|
PWSTR VolumePrefix = 0;
|
||||||
|
PWSTR RootSddl = 0;
|
||||||
|
MEMFS *Memfs = 0;
|
||||||
|
NTSTATUS Result;
|
||||||
|
|
||||||
va_start(ap, format);
|
for (argp = argv + 1, arge = argv + argc; arge > argp; argp++)
|
||||||
vwarn(format, ap);
|
{
|
||||||
va_end(ap);
|
if (L'-' != argp[0][0])
|
||||||
}
|
break;
|
||||||
|
switch (argp[0][1])
|
||||||
|
{
|
||||||
|
case L'?':
|
||||||
|
goto usage;
|
||||||
|
case L'm':
|
||||||
|
argtos(MountPoint);
|
||||||
|
break;
|
||||||
|
case L'n':
|
||||||
|
argtol(MaxFileNodes);
|
||||||
|
break;
|
||||||
|
case L'S':
|
||||||
|
argtos(RootSddl);
|
||||||
|
break;
|
||||||
|
case L's':
|
||||||
|
argtol(MaxFileSize);
|
||||||
|
break;
|
||||||
|
case L't':
|
||||||
|
argtol(FileInfoTimeout);
|
||||||
|
break;
|
||||||
|
case L'u':
|
||||||
|
argtos(VolumePrefix);
|
||||||
|
Flags = MemfsNet;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto usage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void fail(const char *format, ...)
|
if (arge > argp)
|
||||||
{
|
goto usage;
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, format);
|
if (MemfsDisk == Flags && 0 == MountPoint)
|
||||||
vwarn(format, ap);
|
goto usage;
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
exit(1);
|
Result = MemfsCreate(Flags, FileInfoTimeout, MaxFileNodes, MaxFileSize, VolumePrefix, RootSddl,
|
||||||
}
|
&Memfs);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
fail(L"cannot create MEMFS");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
static void usage(void)
|
if (0 != MountPoint && L'\0' != MountPoint[0])
|
||||||
{
|
{
|
||||||
static char usage[] = ""
|
Result = FspFileSystemSetMountPoint(MemfsFileSystem(Memfs),
|
||||||
|
L'*' == MountPoint[0] && L'\0' == MountPoint[1] ? 0 : MountPoint);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
fail(L"cannot mount MEMFS");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result = MemfsStart(Memfs);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
{
|
||||||
|
fail(L"cannot start MEMFS");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
MountPoint = FspFileSystemMountPoint(MemfsFileSystem(Memfs));
|
||||||
|
|
||||||
|
info(L"%s -t %ld -n %ld -s %ld%s%s%s%s%s%s",
|
||||||
|
L"" PROGNAME, FileInfoTimeout, MaxFileNodes, MaxFileSize,
|
||||||
|
RootSddl ? L" -S " : L"", RootSddl ? RootSddl : L"",
|
||||||
|
VolumePrefix ? L" -u " : L"", VolumePrefix ? VolumePrefix : L"",
|
||||||
|
MountPoint ? L" -m " : L"", MountPoint ? MountPoint : L"");
|
||||||
|
|
||||||
|
Service->UserContext = Memfs;
|
||||||
|
Result = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (!NT_SUCCESS(Result) && 0 != Memfs)
|
||||||
|
MemfsDelete(Memfs);
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
|
||||||
|
usage:
|
||||||
|
static wchar_t usage[] = L""
|
||||||
"usage: %s OPTIONS\n"
|
"usage: %s OPTIONS\n"
|
||||||
"\n"
|
"\n"
|
||||||
"options:\n"
|
"options:\n"
|
||||||
@ -68,120 +138,24 @@ static void usage(void)
|
|||||||
" -s MaxFileSize [bytes]\n"
|
" -s MaxFileSize [bytes]\n"
|
||||||
" -S RootSddl [file rights: FA, etc; NO generic rights: GA, etc.]\n"
|
" -S RootSddl [file rights: FA, etc; NO generic rights: GA, etc.]\n"
|
||||||
" -u \\Server\\Share [UNC prefix (single backslash)]\n"
|
" -u \\Server\\Share [UNC prefix (single backslash)]\n"
|
||||||
" -m MountPoint [X:]\n";
|
" -m MountPoint [X:|* (required if no UNC prefix)]\n";
|
||||||
|
|
||||||
warn(usage, PROGNAME);
|
fail(usage, L"" PROGNAME);
|
||||||
exit(2);
|
|
||||||
|
return STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ULONG argtol(wchar_t **argp, ULONG deflt)
|
NTSTATUS SvcStop(FSP_SERVICE *Service)
|
||||||
{
|
{
|
||||||
if (0 == argp[0])
|
MEMFS *Memfs = Service->UserContext;
|
||||||
usage();
|
|
||||||
|
|
||||||
wchar_t *endp;
|
MemfsStop(Memfs);
|
||||||
ULONG ul = wcstol(argp[0], &endp, 10);
|
MemfsDelete(Memfs);
|
||||||
return L'\0' != argp[0][0] && L'\0' == *endp ? ul : deflt;
|
|
||||||
}
|
|
||||||
|
|
||||||
static wchar_t *argtos(wchar_t **argp)
|
return STATUS_SUCCESS;
|
||||||
{
|
|
||||||
if (0 == argp[0])
|
|
||||||
usage();
|
|
||||||
|
|
||||||
return argp[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
static HANDLE MainEvent;
|
|
||||||
|
|
||||||
static BOOL WINAPI ConsoleCtrlHandler(DWORD CtrlType)
|
|
||||||
{
|
|
||||||
SetEvent(MainEvent);
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int wmain(int argc, wchar_t **argv)
|
int wmain(int argc, wchar_t **argv)
|
||||||
{
|
{
|
||||||
wchar_t **argp;
|
return FspServiceRun(L"" PROGNAME, SvcStart, SvcStop, 0);
|
||||||
NTSTATUS Result;
|
|
||||||
MEMFS *Memfs;
|
|
||||||
ULONG Flags = MemfsDisk;
|
|
||||||
ULONG FileInfoTimeout = INFINITE;
|
|
||||||
ULONG MaxFileNodes = 1024;
|
|
||||||
ULONG MaxFileSize = 16 * 1024 * 1024;
|
|
||||||
PWSTR MountPoint = 0;
|
|
||||||
PWSTR VolumePrefix = 0;
|
|
||||||
PWSTR RootSddl = 0;
|
|
||||||
|
|
||||||
for (argp = argv + 1; 0 != argp[0]; argp++)
|
|
||||||
{
|
|
||||||
if (L'-' != argp[0][0])
|
|
||||||
break;
|
|
||||||
switch (argp[0][1])
|
|
||||||
{
|
|
||||||
case L'?':
|
|
||||||
usage();
|
|
||||||
break;
|
|
||||||
case L'm':
|
|
||||||
MountPoint = argtos(++argp);
|
|
||||||
break;
|
|
||||||
case L'n':
|
|
||||||
MaxFileNodes = argtol(++argp, MaxFileNodes);
|
|
||||||
break;
|
|
||||||
case L'S':
|
|
||||||
RootSddl = argtos(++argp);
|
|
||||||
break;
|
|
||||||
case L's':
|
|
||||||
MaxFileSize = argtol(++argp, MaxFileSize);
|
|
||||||
break;
|
|
||||||
case L't':
|
|
||||||
FileInfoTimeout = argtol(++argp, FileInfoTimeout);
|
|
||||||
break;
|
|
||||||
case L'u':
|
|
||||||
VolumePrefix = argtos(++argp);
|
|
||||||
Flags = MemfsNet;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
usage();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 != argp[0])
|
|
||||||
usage();
|
|
||||||
|
|
||||||
MainEvent = CreateEvent(0, TRUE, FALSE, 0);
|
|
||||||
if (0 == MainEvent)
|
|
||||||
fail("error: cannot create MainEvent");
|
|
||||||
|
|
||||||
Result = MemfsCreate(Flags, FileInfoTimeout, MaxFileNodes, MaxFileSize, VolumePrefix, RootSddl,
|
|
||||||
&Memfs);
|
|
||||||
if (!NT_SUCCESS(Result))
|
|
||||||
fail("error: cannot create MEMFS");
|
|
||||||
Result = MemfsStart(Memfs);
|
|
||||||
if (!NT_SUCCESS(Result))
|
|
||||||
fail("error: cannot start MEMFS");
|
|
||||||
Result = FspFileSystemSetMountPoint(MemfsFileSystem(Memfs), MountPoint);
|
|
||||||
if (!NT_SUCCESS(Result))
|
|
||||||
fail("error: cannot mount MEMFS");
|
|
||||||
MountPoint = FspFileSystemMountPoint(MemfsFileSystem(Memfs));
|
|
||||||
|
|
||||||
warn("%s -t %ld -n %ld -s %ld%s%S%s%S -m %S",
|
|
||||||
PROGNAME, FileInfoTimeout, MaxFileNodes, MaxFileSize,
|
|
||||||
RootSddl ? " -S " : "", RootSddl ? RootSddl : L"",
|
|
||||||
VolumePrefix ? " -u " : "", VolumePrefix ? VolumePrefix : L"",
|
|
||||||
MountPoint);
|
|
||||||
SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
|
|
||||||
if (WAIT_OBJECT_0 != WaitForSingleObject(MainEvent, INFINITE))
|
|
||||||
fail("error: cannot wait on MainEvent");
|
|
||||||
|
|
||||||
FspFileSystemRemoveMountPoint(MemfsFileSystem(Memfs));
|
|
||||||
MemfsStop(Memfs);
|
|
||||||
MemfsDelete(Memfs);
|
|
||||||
|
|
||||||
/* the OS will handle this! */
|
|
||||||
// CloseHandle(MainEvent);
|
|
||||||
// MainEvent = 0;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* @file memfs.c
|
* @file memfs.cpp
|
||||||
*
|
*
|
||||||
* @copyright 2015-2016 Bill Zissimopoulos
|
* @copyright 2015-2016 Bill Zissimopoulos
|
||||||
*/
|
*/
|
||||||
@ -396,7 +396,7 @@ static NTSTATUS Create(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
FileNode->FileInfo.AllocationSize = AllocationSize;
|
FileNode->FileInfo.AllocationSize = AllocationSize;
|
||||||
if (0 != FileNode->FileInfo.AllocationSize)
|
if (0 != FileNode->FileInfo.AllocationSize)
|
||||||
{
|
{
|
||||||
FileNode->FileData = malloc(FileNode->FileInfo.AllocationSize);
|
FileNode->FileData = malloc((size_t)FileNode->FileInfo.AllocationSize);
|
||||||
if (0 == FileNode->FileData)
|
if (0 == FileNode->FileData)
|
||||||
{
|
{
|
||||||
MemfsFileNodeDelete(FileNode);
|
MemfsFileNodeDelete(FileNode);
|
||||||
@ -507,7 +507,7 @@ static NTSTATUS Read(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
if (EndOffset > FileNode->FileInfo.FileSize)
|
if (EndOffset > FileNode->FileInfo.FileSize)
|
||||||
EndOffset = FileNode->FileInfo.FileSize;
|
EndOffset = FileNode->FileInfo.FileSize;
|
||||||
|
|
||||||
memcpy(Buffer, (PUINT8)FileNode->FileData + Offset, EndOffset - Offset);
|
memcpy(Buffer, (PUINT8)FileNode->FileData + Offset, (size_t)(EndOffset - Offset));
|
||||||
|
|
||||||
*PBytesTransferred = (ULONG)(EndOffset - Offset);
|
*PBytesTransferred = (ULONG)(EndOffset - Offset);
|
||||||
|
|
||||||
@ -555,7 +555,7 @@ static NTSTATUS Write(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
SetFileSize(FileSystem, Request, FileNode, EndOffset, FileInfo);
|
SetFileSize(FileSystem, Request, FileNode, EndOffset, FileInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy((PUINT8)FileNode->FileData + Offset, Buffer, EndOffset - Offset);
|
memcpy((PUINT8)FileNode->FileData + Offset, Buffer, (size_t)(EndOffset - Offset));
|
||||||
|
|
||||||
*PBytesTransferred = (ULONG)(EndOffset - Offset);
|
*PBytesTransferred = (ULONG)(EndOffset - Offset);
|
||||||
*FileInfo = FileNode->FileInfo;
|
*FileInfo = FileNode->FileInfo;
|
||||||
@ -619,7 +619,7 @@ static NTSTATUS SetAllocationSize(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
if (AllocationSize > Memfs->MaxFileSize)
|
if (AllocationSize > Memfs->MaxFileSize)
|
||||||
return STATUS_DISK_FULL;
|
return STATUS_DISK_FULL;
|
||||||
|
|
||||||
FileData = realloc(FileNode->FileData, AllocationSize);
|
FileData = realloc(FileNode->FileData, (size_t)AllocationSize);
|
||||||
if (0 == FileData)
|
if (0 == FileData)
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
|
||||||
@ -656,7 +656,7 @@ static NTSTATUS SetFileSize(FSP_FILE_SYSTEM *FileSystem,
|
|||||||
|
|
||||||
if (FileNode->FileInfo.FileSize < FileSize)
|
if (FileNode->FileInfo.FileSize < FileSize)
|
||||||
memset((PUINT8)FileNode->FileData + FileNode->FileInfo.FileSize, 0,
|
memset((PUINT8)FileNode->FileData + FileNode->FileInfo.FileSize, 0,
|
||||||
FileSize - FileNode->FileInfo.FileSize);
|
(size_t)(FileSize - FileNode->FileInfo.FileSize));
|
||||||
FileNode->FileInfo.FileSize = FileSize;
|
FileNode->FileInfo.FileSize = FileSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
16
tst/winfsp-tests/eventlog-test.c
Normal file
16
tst/winfsp-tests/eventlog-test.c
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#include <winfsp/winfsp.h>
|
||||||
|
#include <tlib/testsuite.h>
|
||||||
|
|
||||||
|
void eventlog_test(void)
|
||||||
|
{
|
||||||
|
/* this is not a real test! */
|
||||||
|
|
||||||
|
FspEventLog(EVENTLOG_INFORMATION_TYPE, L"EventLog %s message", L"informational");
|
||||||
|
FspEventLog(EVENTLOG_WARNING_TYPE, L"EventLog %s message", L"warning");
|
||||||
|
FspEventLog(EVENTLOG_ERROR_TYPE, L"EventLog %s message", L"error");
|
||||||
|
}
|
||||||
|
|
||||||
|
void eventlog_tests(void)
|
||||||
|
{
|
||||||
|
TEST_OPT(eventlog_test);
|
||||||
|
}
|
@ -6,6 +6,7 @@ int WinFspNetTests = 1;
|
|||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
TESTSUITE(eventlog_tests);
|
||||||
TESTSUITE(path_tests);
|
TESTSUITE(path_tests);
|
||||||
TESTSUITE(mount_tests);
|
TESTSUITE(mount_tests);
|
||||||
TESTSUITE(timeout_tests);
|
TESTSUITE(timeout_tests);
|
||||||
|
Reference in New Issue
Block a user