Browse Source

Hoisted Doorstop files the rest of the way out of the submodule

This also adds some error tracking stuff to Doorstop
pull/46/head
Anairkoen Schno 5 years ago
parent
commit
5ad7e46eae
29 changed files with 2520 additions and 1 deletions
  1. +0
    -1
      Doorstop
  2. +325
    -0
      Doorstop/.gitignore
  3. +58
    -0
      Doorstop/DoorstopTest/DoorstopTest.csproj
  4. +24
    -0
      Doorstop/DoorstopTest/Loader.cs
  5. +36
    -0
      Doorstop/DoorstopTest/Properties/AssemblyInfo.cs
  6. +116
    -0
      Doorstop/LICENSE
  7. +190
    -0
      Doorstop/Proxy/Proxy.vcxproj
  8. +61
    -0
      Doorstop/Proxy/Proxy.vcxproj.filters
  9. +63
    -0
      Doorstop/Proxy/assert_util.h
  10. +137
    -0
      Doorstop/Proxy/config.h
  11. +65
    -0
      Doorstop/Proxy/crt.h
  12. +64
    -0
      Doorstop/Proxy/dll.def
  13. +162
    -0
      Doorstop/Proxy/hook.h
  14. +462
    -0
      Doorstop/Proxy/main.c
  15. +105
    -0
      Doorstop/Proxy/mono.h
  16. +133
    -0
      Doorstop/Proxy/proxy.c
  17. +54
    -0
      Doorstop/Proxy/proxy.def
  18. +74
    -0
      Doorstop/Proxy/proxy.h
  19. BIN
      Doorstop/Proxy/proxy.rc
  20. +63
    -0
      Doorstop/Proxy/proxydefs.txt
  21. +65
    -0
      Doorstop/Proxy/winapi_util.h
  22. +47
    -0
      Doorstop/README.md
  23. +77
    -0
      Doorstop/UnityDoorstop.sln
  24. BIN
      Doorstop/docs/logo.png
  25. BIN
      Doorstop/docs/logo_sm.png
  26. +52
    -0
      Doorstop/proxygen/proxy_gen.py
  27. +34
    -0
      Doorstop/proxygen/templates/proxy_template.c
  28. +3
    -0
      Doorstop/proxygen/templates/proxy_template.def
  29. +50
    -0
      Doorstop/proxygen/winhttp.txt

+ 0
- 1
Doorstop

@ -1 +0,0 @@
Subproject commit f9a0d26bfb2a6f24abd3b438eb6b813a54e3ed4e

+ 325
- 0
Doorstop/.gitignore View File

@ -0,0 +1,325 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build folder
Build/
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
.vscode/
# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
**/Properties/launchSettings.json
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Typescript v1 declaration files
typings/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush
.cr/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs

+ 58
- 0
Doorstop/DoorstopTest/DoorstopTest.csproj View File

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{62B61CCC-0775-4CF4-B37A-EB5E33CBD08C}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Doorstop</RootNamespace>
<AssemblyName>Doorstop</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<StartupObject />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Verbose|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\Verbose\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Verbose_Release|AnyCPU'">
<OutputPath>bin\Verbose_Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Compile Include="Loader.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

+ 24
- 0
Doorstop/DoorstopTest/Loader.cs View File

@ -0,0 +1,24 @@
using System;
using System.IO;
namespace Doorstop
{
public static class Loader
{
public static void Main(string[] args)
{
using (TextWriter tw = File.CreateText("doorstop_is_alive.txt"))
{
tw.WriteLine($"Hello! This text file was generated by Doorstop on {DateTime.Now:R}!");
tw.WriteLine($"I was called with {args.Length} params!");
for (int i = 0; i < args.Length; i++)
tw.WriteLine($"{i} => {args[i]}");
tw.WriteLine("Replace this DLL with a custom-made one to do whatever you want!");
tw.Flush();
}
}
}
}

+ 36
- 0
Doorstop/DoorstopTest/Properties/AssemblyInfo.cs View File

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("PatchLoader")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("PatchLoader")]
[assembly: AssemblyCopyright("Copyright © 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("62b61ccc-0775-4cf4-b37a-eb5e33cbd08c")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

+ 116
- 0
Doorstop/LICENSE View File

@ -0,0 +1,116 @@
CC0 1.0 Universal
Statement of Purpose
The laws of most jurisdictions throughout the world automatically confer
exclusive Copyright and Related Rights (defined below) upon the creator and
subsequent owner(s) (each and all, an "owner") of an original work of
authorship and/or a database (each, a "Work").
Certain owners wish to permanently relinquish those rights to a Work for the
purpose of contributing to a commons of creative, cultural and scientific
works ("Commons") that the public can reliably and without fear of later
claims of infringement build upon, modify, incorporate in other works, reuse
and redistribute as freely as possible in any form whatsoever and for any
purposes, including without limitation commercial purposes. These owners may
contribute to the Commons to promote the ideal of a free culture and the
further production of creative, cultural and scientific works, or to gain
reputation or greater distribution for their Work in part through the use and
efforts of others.
For these and/or other purposes and motivations, and without any expectation
of additional consideration or compensation, the person associating CC0 with a
Work (the "Affirmer"), to the extent that he or she is an owner of Copyright
and Related Rights in the Work, voluntarily elects to apply CC0 to the Work
and publicly distribute the Work under its terms, with knowledge of his or her
Copyright and Related Rights in the Work and the meaning and intended legal
effect of CC0 on those rights.
1. Copyright and Related Rights. A Work made available under CC0 may be
protected by copyright and related or neighboring rights ("Copyright and
Related Rights"). Copyright and Related Rights include, but are not limited
to, the following:
i. the right to reproduce, adapt, distribute, perform, display, communicate,
and translate a Work;
ii. moral rights retained by the original author(s) and/or performer(s);
iii. publicity and privacy rights pertaining to a person's image or likeness
depicted in a Work;
iv. rights protecting against unfair competition in regards to a Work,
subject to the limitations in paragraph 4(a), below;
v. rights protecting the extraction, dissemination, use and reuse of data in
a Work;
vi. database rights (such as those arising under Directive 96/9/EC of the
European Parliament and of the Council of 11 March 1996 on the legal
protection of databases, and under any national implementation thereof,
including any amended or successor version of such directive); and
vii. other similar, equivalent or corresponding rights throughout the world
based on applicable law or treaty, and any national implementations thereof.
2. Waiver. To the greatest extent permitted by, but not in contravention of,
applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and
unconditionally waives, abandons, and surrenders all of Affirmer's Copyright
and Related Rights and associated claims and causes of action, whether now
known or unknown (including existing as well as future claims and causes of
action), in the Work (i) in all territories worldwide, (ii) for the maximum
duration provided by applicable law or treaty (including future time
extensions), (iii) in any current or future medium and for any number of
copies, and (iv) for any purpose whatsoever, including without limitation
commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes
the Waiver for the benefit of each member of the public at large and to the
detriment of Affirmer's heirs and successors, fully intending that such Waiver
shall not be subject to revocation, rescission, cancellation, termination, or
any other legal or equitable action to disrupt the quiet enjoyment of the Work
by the public as contemplated by Affirmer's express Statement of Purpose.
3. Public License Fallback. Should any part of the Waiver for any reason be
judged legally invalid or ineffective under applicable law, then the Waiver
shall be preserved to the maximum extent permitted taking into account
Affirmer's express Statement of Purpose. In addition, to the extent the Waiver
is so judged Affirmer hereby grants to each affected person a royalty-free,
non transferable, non sublicensable, non exclusive, irrevocable and
unconditional license to exercise Affirmer's Copyright and Related Rights in
the Work (i) in all territories worldwide, (ii) for the maximum duration
provided by applicable law or treaty (including future time extensions), (iii)
in any current or future medium and for any number of copies, and (iv) for any
purpose whatsoever, including without limitation commercial, advertising or
promotional purposes (the "License"). The License shall be deemed effective as
of the date CC0 was applied by Affirmer to the Work. Should any part of the
License for any reason be judged legally invalid or ineffective under
applicable law, such partial invalidity or ineffectiveness shall not
invalidate the remainder of the License, and in such case Affirmer hereby
affirms that he or she will not (i) exercise any of his or her remaining
Copyright and Related Rights in the Work or (ii) assert any associated claims
and causes of action with respect to the Work, in either case contrary to
Affirmer's express Statement of Purpose.
4. Limitations and Disclaimers.
a. No trademark or patent rights held by Affirmer are waived, abandoned,
surrendered, licensed or otherwise affected by this document.
b. Affirmer offers the Work as-is and makes no representations or warranties
of any kind concerning the Work, express, implied, statutory or otherwise,
including without limitation warranties of title, merchantability, fitness
for a particular purpose, non infringement, or the absence of latent or
other defects, accuracy, or the present or absence of errors, whether or not
discoverable, all to the greatest extent permissible under applicable law.
c. Affirmer disclaims responsibility for clearing rights of other persons
that may apply to the Work or any use thereof, including without limitation
any person's Copyright and Related Rights in the Work. Further, Affirmer
disclaims responsibility for obtaining any necessary consents, permissions
or other rights required for any use of the Work.
d. Affirmer understands and acknowledges that Creative Commons is not a
party to this document and has no duty or obligation with respect to this
CC0 or use of the Work.
For more information, please see
<http://creativecommons.org/publicdomain/zero/1.0/>

+ 190
- 0
Doorstop/Proxy/Proxy.vcxproj View File

@ -0,0 +1,190 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Verbose_Release|Win32">
<Configuration>Verbose_Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Verbose_Release|x64">
<Configuration>Verbose_Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{88609E16-731F-46C9-8139-6B1A7A83240D}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>proxy</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>proxy</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Verbose_Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Verbose_Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="Shared">
</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 Condition="'$(Configuration)|$(Platform)'=='Verbose_Release|Win32'" Label="PropertySheets">
<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>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Verbose_Release|x64'" 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 Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(ProjectDir)bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>obj\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Verbose_Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(ProjectDir)bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>obj\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(ProjectDir)bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>obj\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Verbose_Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(ProjectDir)bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>obj\$(Platform)\$(Configuration)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release' Or '$(Configuration)'=='Debug'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MinSpace</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>false</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;NOGDI;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<CLanguageStandard>c11</CLanguageStandard>
<CompileAs>CompileAsC</CompileAs>
<PrecompiledHeaderCompileAs>CompileAsC</PrecompiledHeaderCompileAs>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<WholeProgramOptimization>false</WholeProgramOptimization>
<BufferSecurityCheck>false</BufferSecurityCheck>
<ExceptionHandling>false</ExceptionHandling>
<SupportJustMyCode>false</SupportJustMyCode>
<RuntimeLibrary Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">MultiThreadedDLL</RuntimeLibrary>
<RuntimeLibrary Condition="'$(Configuration)|$(Platform)'=='Release|x64'">MultiThreadedDLL</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<ModuleDefinitionFile>$(MSBuildProjectDirectory)\proxy.def</ModuleDefinitionFile>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
<DelayLoadDLLs>
</DelayLoadDLLs>
<EntryPointSymbol>DllMain</EntryPointSymbol>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<ImageHasSafeExceptionHandlers Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ImageHasSafeExceptionHandlers>
<ImageHasSafeExceptionHandlers Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ImageHasSafeExceptionHandlers>
<AdditionalOptions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalOptions)</AdditionalOptions>
<AdditionalOptions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalOptions)</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)'=='Verbose_Release' Or '$(Configuration)'=='Verbose'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MinSpace</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>false</IntrinsicFunctions>
<PreprocessorDefinitions>_VERBOSE;NDEBUG;_WINDOWS;_USRDLL;NOGDI;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<CLanguageStandard>c11</CLanguageStandard>
<CompileAs>CompileAsC</CompileAs>
<PrecompiledHeaderCompileAs>CompileAsC</PrecompiledHeaderCompileAs>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<WholeProgramOptimization>false</WholeProgramOptimization>
<BufferSecurityCheck>false</BufferSecurityCheck>
<ExceptionHandling>false</ExceptionHandling>
<SupportJustMyCode>false</SupportJustMyCode>
<RuntimeLibrary Condition="'$(Configuration)|$(Platform)'=='Verbose_Release|Win32'">MultiThreadedDLL</RuntimeLibrary>
<RuntimeLibrary Condition="'$(Configuration)|$(Platform)'=='Verbose_Release|x64'">MultiThreadedDLL</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<ModuleDefinitionFile>$(MSBuildProjectDirectory)\proxy.def</ModuleDefinitionFile>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
<DelayLoadDLLs>
</DelayLoadDLLs>
<EntryPointSymbol>DllMain</EntryPointSymbol>
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
<ImageHasSafeExceptionHandlers Condition="'$(Configuration)|$(Platform)'=='Verbose_Release|Win32'">false</ImageHasSafeExceptionHandlers>
<ImageHasSafeExceptionHandlers Condition="'$(Configuration)|$(Platform)'=='Verbose_Release|x64'">false</ImageHasSafeExceptionHandlers>
<AdditionalOptions Condition="'$(Configuration)|$(Platform)'=='Verbose_Release|Win32'">%(AdditionalOptions)</AdditionalOptions>
<AdditionalOptions Condition="'$(Configuration)|$(Platform)'=='Verbose_Release|x64'">%(AdditionalOptions)</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="main.c" />
<ClCompile Include="proxy.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="assert_util.h" />
<ClInclude Include="config.h" />
<ClInclude Include="crt.h" />
<ClInclude Include="hook.h" />
<ClInclude Include="mono.h" />
<ClInclude Include="proxy.h" />
<ClInclude Include="winapi_util.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="proxy.rc" />
</ItemGroup>
<ItemGroup>
<None Include="proxy.def" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<Target Name="AfterBuild">
<Exec Command="$([System.IO.Path]::GetFullPath($([System.IO.Path]::Combine($(MSBuildProjectDirectory), '..', 'BuildUtils', 'ducible.exe')))) $(OutDir)$(MSBuildProjectName).dll $(OutDir)$(MSBuildProjectName).pdb" />
</Target>
</Project>

+ 61
- 0
Doorstop/Proxy/Proxy.vcxproj.filters View File

@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="Other">
<UniqueIdentifier>{384fe73e-c79a-42c8-8d61-73dc2f7e7432}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="proxy.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="mono.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="hook.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="assert_util.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="proxy.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="config.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="winapi_util.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="crt.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="proxy.rc">
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<None Include="proxy.def">
<Filter>Other</Filter>
</None>
</ItemGroup>
</Project>

+ 63
- 0
Doorstop/Proxy/assert_util.h View File

@ -0,0 +1,63 @@
#pragma once
#ifdef _VERBOSE
#pragma comment(lib, "ucrt.lib")
#include <windows.h>
#include <stdio.h>
static HANDLE log_handle;
char buffer[8192];
wchar_t bufferW[8192];
inline void init_logger()
{
log_handle = CreateFileA("doorstop.log", GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
NULL);
}
inline void free_logger()
{
CloseHandle(log_handle);
}
#define LOG(message, ...) \
{ \
int len = _snprintf_s(buffer, sizeof(buffer)/sizeof(char), _TRUNCATE, message, __VA_ARGS__); \
WriteFile(log_handle, buffer, len, NULL, NULL); \
}
#else
inline void init_logger()
{
}
inline void free_logger()
{
}
#define LOG(message, ...)
#endif
#define ASSERT_F(test, message, ...) \
if(!(test)) \
{ \
_snwprintf_s(bufferW, sizeof(bufferW)/sizeof(wchar_t), _TRUNCATE, message, __VA_ARGS__); \
MessageBoxW(NULL, bufferW, L"Doorstop: Fatal", MB_OK | MB_ICONERROR); \
ExitProcess(EXIT_FAILURE); \
}
// A helper for cleaner error logging
#define ASSERT(test, message) \
if(!(test)) \
{ \
MessageBoxW(NULL, message, L"Doorstop: Fatal", MB_OK | MB_ICONERROR); \
ExitProcess(EXIT_FAILURE); \
}
#define ASSERT_SOFT(test, ...) \
if(!(test)) \
{ \
return __VA_ARGS__; \
}

+ 137
- 0
Doorstop/Proxy/config.h View File

@ -0,0 +1,137 @@
#pragma once
#pragma warning( disable : 4267 )
#include <Windows.h>
#include <shellapi.h>
#include "winapi_util.h"
#include "assert_util.h"
#include "crt.h"
#define CONFIG_NAME L"doorstop_config"
#define DEFAULT_TARGET_ASSEMBLY L"Doorstop.dll"
#define EXE_EXTENSION_LENGTH 4
BOOL enabled = FALSE;
BOOL debug = FALSE;
BOOL debug_server = FALSE;
BOOL debug_info = FALSE;
wchar_t *targetAssembly = NULL;
#define STR_EQUAL(str1, str2) (lstrcmpiW(str1, str2) == 0)
inline void initConfigFile()
{
enabled = TRUE;
WIN32_FIND_DATAW findData;
HANDLE findHandle = FindFirstFileW(L"*_Data", &findData);
if (findHandle == INVALID_HANDLE_VALUE)
{
MessageBoxW(NULL, L"Could not locate game being injected!", L"No files found in current directory matching '*_Data'",
MB_OK | MB_ICONERROR | MB_SYSTEMMODAL | MB_TOPMOST | MB_SETFOREGROUND);
ExitProcess(GetLastError());
}
do
{
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{ // must be a directory
wchar_t* target = memalloc(MAX_PATH * sizeof(wchar_t));
const int EXIT_FAILURE = 1;
ASSERT(target != NULL, L"Address returned by memalloc was NULL!");
wmemset(target, 0, MAX_PATH);
wmemcpy(target, findData.cFileName, wcslen(findData.cFileName));
wmemcpy(target + wcslen(target), L"/Managed/IPA.Injector.dll", 26);
targetAssembly = target;
FindClose(findHandle);
break;
}
}
while (FindNextFileW(findHandle, &findData) != 0);
if (targetAssembly == NULL)
{
MessageBoxW(NULL, L"Could not locate game being injected!", L"No valid directories matching '*_Data'",
MB_OK | MB_ICONERROR | MB_SYSTEMMODAL | MB_TOPMOST | MB_SETFOREGROUND);
ExitProcess(GetLastError());
}
}
inline void initCmdArgs()
{
wchar_t *args = GetCommandLineW();
int argc = 0;
wchar_t **argv = CommandLineToArgvW(args, &argc);
#define IS_ARGUMENT(arg_name) STR_EQUAL(arg, arg_name) && i < argc
for (int i = 0; i < argc; i++)
{
wchar_t *arg = argv[i];
/*if (IS_ARGUMENT(L"--doorstop-enable"))
{
wchar_t *par = argv[++i];
if (STR_EQUAL(par, L"true"))
enabled = TRUE;
else if (STR_EQUAL(par, L"false"))
enabled = FALSE;
}
else if (IS_ARGUMENT(L"--doorstop-target"))
{
if (targetAssembly != NULL)
memfree(targetAssembly);
const size_t len = wcslen(argv[i + 1]) + 1;
targetAssembly = memalloc(sizeof(wchar_t) * len);
lstrcpynW(targetAssembly, argv[++i], len);
LOG("Args; Target assembly: %S\n", targetAssembly);
}
else */if (IS_ARGUMENT(L"--mono-debug"))
{
debug = TRUE;
debug_info = TRUE;
LOG("Enabled debugging\n");
}
else if (IS_ARGUMENT(L"--debug"))
{
debug_info = TRUE;
LOG("Enabled loading of debug info\n");
}
else if (IS_ARGUMENT(L"--server"))
{
debug_server = TRUE;
LOG("Server-mode debugging enabled\n");
}
}
LocalFree(argv);
}
inline void initEnvVars()
{
if (GetEnvironmentVariableW(L"DOORSTOP_DISABLE", NULL, 0) != 0)
{
LOG("DOORSTOP_DISABLE is set! Disabling Doorstop!\n");
enabled = FALSE;
}
}
inline void loadConfig()
{
initConfigFile();
initCmdArgs();
initEnvVars();
}
inline void cleanupConfig()
{
if (targetAssembly != NULL)
memfree(targetAssembly);
}

+ 65
- 0
Doorstop/Proxy/crt.h View File

@ -0,0 +1,65 @@
#pragma once
#pragma warning( disable : 4028 28251 6001 )
#include <debugapi.h>
HANDLE hHeap;
#define memalloc(size) HeapAlloc(hHeap, HEAP_GENERATE_EXCEPTIONS, size)
#define memcalloc(size) HeapAlloc(hHeap, HEAP_ZERO_MEMORY, size)
#define memfree(mem) HeapFree(hHeap, 0, mem)
#define STR_LEN(str) (sizeof(str) / sizeof(str[0]))
#define DEBUG_BREAK { if (IsDebuggerPresent()) { __debugbreak(); } }
inline void *wmemcpy(wchar_t *dst, const wchar_t *src, size_t n)
{
wchar_t *d = dst;
const wchar_t *s = src;
while (n--)
*d++ = *s++;
return dst;
}
inline void *wmemset(wchar_t *dst, wchar_t c, size_t n)
{
wchar_t *d = dst;
while (n--)
*(d++) = c;
return dst;
}
void *memset(void *dst, char c, int n)
{
char *d = dst;
while (n--)
*d = c;
return dst;
}
inline void *memcpy(void *dst, const void *src, int n)
{
char *d = dst;
const char *s = src;
while (n--)
*d++ = *s++;
return dst;
}
inline size_t wcslen(wchar_t const *str)
{
size_t result = 0;
while (*str++)
result++;
return result;
}
inline size_t strlen(char const *str)
{
size_t result = 0;
while (*str++)
result++;
return result;
}

+ 64
- 0
Doorstop/Proxy/dll.def View File

@ -0,0 +1,64 @@
EXPORTS
SvchostPushServiceGlobals
WinHttpAddRequestHeaders
WinHttpAutoProxySvcMain
WinHttpCheckPlatform
WinHttpCloseHandle
WinHttpConnect
WinHttpConnectionDeletePolicyEntries
WinHttpConnectionDeleteProxyInfo
WinHttpConnectionFreeNameList
WinHttpConnectionFreeProxyInfo
WinHttpConnectionFreeProxyList
WinHttpConnectionGetNameList
WinHttpConnectionGetProxyInfo
WinHttpConnectionGetProxyList
WinHttpConnectionSetPolicyEntries
WinHttpConnectionSetProxyInfo
WinHttpConnectionUpdateIfIndexTable
WinHttpCrackUrl
WinHttpCreateProxyResolver
WinHttpCreateUrl
WinHttpDetectAutoProxyConfigUrl
WinHttpFreeProxyResult
WinHttpFreeProxyResultEx
WinHttpFreeProxySettings
WinHttpGetDefaultProxyConfiguration
WinHttpGetIEProxyConfigForCurrentUser
WinHttpGetProxyForUrl
WinHttpGetProxyForUrlEx
WinHttpGetProxyForUrlEx2
WinHttpGetProxyForUrlHvsi
WinHttpGetProxyResult
WinHttpGetProxyResultEx
WinHttpGetProxySettingsVersion
WinHttpGetTunnelSocket
WinHttpOpen
WinHttpOpenRequest
WinHttpProbeConnectivity
WinHttpQueryAuthSchemes
WinHttpQueryDataAvailable
WinHttpQueryHeaders
WinHttpQueryOption
WinHttpReadData
WinHttpReadProxySettings
WinHttpReadProxySettingsHvsi
WinHttpReceiveResponse
WinHttpResetAutoProxy
WinHttpSaveProxyCredentials
WinHttpSendRequest
WinHttpSetCredentials
WinHttpSetDefaultProxyConfiguration
WinHttpSetOption
WinHttpSetStatusCallback
WinHttpSetTimeouts
WinHttpTimeFromSystemTime
WinHttpTimeToSystemTime
WinHttpWebSocketClose
WinHttpWebSocketCompleteUpgrade
WinHttpWebSocketQueryCloseStatus
WinHttpWebSocketReceive
WinHttpWebSocketSend
WinHttpWebSocketShutdown
WinHttpWriteData
WinHttpWriteProxySettings

+ 162
- 0
Doorstop/Proxy/hook.h View File

@ -0,0 +1,162 @@
/*
* EAT-based hooking for x86/x64.
*
* Big thanks to ez (https://github.com/ezdiy/) for making this!
*
* Creates "hooks" by modifying the module's export address table.
* The procedure works in three main parts:
*
* 1. Reading the module's PE file and getting all exported functions.
* 2. Finding the right function to "hook" by simple address lookup
* 3. Modify the entry to point to the hook.
*
* The idea is based on the fact that the export table allows forwarding imports:
*
* https://en.wikibooks.org/wiki/X86_Disassembly/Windows_Executable_Files#Forwarding
*
* You can also find some reference material on the same page to understand this code better.
*
*/
#pragma once
#pragma warning( disable : 4267 90 )
#include <windows.h>
// PE format uses RVAs (Relative Virtual Addresses) to save addresses relative to the base of the module
// More info: https://en.wikibooks.org/wiki/X86_Disassembly/Windows_Executable_Files#Relative_Virtual_Addressing_(RVA)
//
// This helper macro converts the saved RVA to a fully valid pointer to the data in the PE file
#define RVA2PTR(t,base,rva) ((t)(((PCHAR) base) + rva))
// A helper function to write into protected memory
inline int vpmemcpy(void *dst, void *src, size_t sz)
{
DWORD oldp;
// Make the memory page writeable
if (!VirtualProtect(dst, sz, PAGE_READWRITE, &oldp))
return 1;
memcpy(dst, src, sz);
// Restore the protection level
VirtualProtect(dst, sz, oldp, &oldp);
return 0;
}
/**
* \brief Replaces the specified function entry in the EAT with a forward to a custom one, thus creating the "hook" effect.
* \param hostDll The address of the module to hook.
* \param originalFunction Address of the original function.
* \param forwardFunctionEntry Name of the function to add a forward to. Must be of form `dll.API`.
* \return TRUE, if hooking succeeded, otherwise, FALSE.
*/
inline BOOL ezHook(HMODULE hostDll, void *originalFunction, char *forwardFunctionEntry)
{
/*
* Note that we are not doing any trampoline magic or editing the assembly!
*
* Instead, we are reading the module's PE file, find the original function's entry in the export address table (EAT),
* and replace it with a forward import.
*
* This ultimately will fool the game/executable to call our hook, while keeping original function intact.
*
* Thus, in order to work, the proxy DLL has to export the hook, because we are essentially
* asking the game to call our hook without ever going to the original function (unlike with trampolines).
*/
size_t fwdlen = strlen(forwardFunctionEntry);
// The module always starts with a DOS (or "MZ") header
IMAGE_DOS_HEADER *mz = (PIMAGE_DOS_HEADER)hostDll;
// Next, get the NT headers. The offset to them is saved in e_lfanew
IMAGE_NT_HEADERS *nt = RVA2PTR(PIMAGE_NT_HEADERS, mz, mz->e_lfanew);
// Get the pointer to the data directory of the exports
IMAGE_DATA_DIRECTORY *edirp = &nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
IMAGE_DATA_DIRECTORY edir = *edirp;
// Finally, the virtual address in the data direcotry tells the location of the exports table
IMAGE_EXPORT_DIRECTORY *exports = RVA2PTR(PIMAGE_EXPORT_DIRECTORY, mz, edir.VirtualAddress);
// Read the addrress of the function list and the address of function names
DWORD *addrs = RVA2PTR(DWORD*, mz, exports->AddressOfFunctions);
// DWORD* names = RVA2PTR(DWORD*, mz, exports->AddressOfNames);
// Iterate through all functions
for (unsigned i = 0; i < exports->NumberOfFunctions; i++)
{
//char* name = RVA2PTR(char*, mz, names[i]); // Name of the exported function
void *addr = RVA2PTR(void*, mz, addrs[i]); // Address of the exported function
// Check if we have the function we need to modify
if (addr == originalFunction)
{
DWORD fptr = edir.VirtualAddress + edir.Size;
int err = 0;
// Update the entry to go the the last entry (which we will populate in the next memcpy)
err |= vpmemcpy(&addrs[i], &fptr, sizeof(fptr));
// Add the forwarding import to our function at the end of the EAT
err |= vpmemcpy(((char*)exports + edir.Size), forwardFunctionEntry, fwdlen);
// Increment the size of the export data directory
// and write the new export data directory
edir.Size += fwdlen + 1;
err |= vpmemcpy(edirp, &edir, sizeof(edir));
return err == 0;
}
}
return FALSE;
}
/**
* \brief Hooks the given function through the Import Address Table
* \param dll Module to hook
* \param targetFunction Address of the target function to hook
* \param detourFunction Address of the detour function
* \return TRUE if successful, otherwise FALSE
*/
inline BOOL iat_hook(HMODULE dll, char const* targetDLL, void *targetFunction, void *detourFunction)
{
IMAGE_DOS_HEADER *mz = (PIMAGE_DOS_HEADER)dll;
IMAGE_NT_HEADERS *nt = RVA2PTR(PIMAGE_NT_HEADERS, mz, mz->e_lfanew);
IMAGE_IMPORT_DESCRIPTOR *imports = RVA2PTR(PIMAGE_IMPORT_DESCRIPTOR, mz, nt->OptionalHeader.DataDirectory[
IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
for (int i = 0; imports[i].Characteristics; i++)
{
char *name = RVA2PTR(char*, mz, imports[i].Name);
if(lstrcmpiA(name, targetDLL) != 0)
continue;
void **thunk = RVA2PTR(void**, mz, imports[i].FirstThunk);
void **nextThunk = RVA2PTR(void**, mz, imports[i+1].FirstThunk);
for (; thunk && thunk < nextThunk; thunk++)
{
void *import = *thunk;
if (import != targetFunction)
continue;
DWORD oldState;
if (!VirtualProtect(thunk, sizeof(void*), PAGE_READWRITE, &oldState))
return FALSE;
*thunk = (void*)detourFunction;
VirtualProtect(thunk, sizeof(void*), oldState, &oldState);
return TRUE;
}
}
return FALSE;
}

+ 462
- 0
Doorstop/Proxy/main.c View File

@ -0,0 +1,462 @@
/*
* main.cpp -- The main "entry point" and the main logic of the DLL.
*
* Here, we define and initialize struct Main that contains the main code of this DLL.
*
* The main procedure goes as follows:
* 1. The loader checks that PatchLoader.dll and mono.dll exist
* 2. mono.dll is loaded into memory and some of its functions are looked up
* 3. mono_jit_init_version is hooked with the help of MinHook
*
* Then, the loader waits until Unity creates its root domain for mono (which is done with mono_jit_init_version).
*
* Inside mono_jit_init_version hook:
* 1. Call the original mono_jit_init_version to get the Unity root domain
* 2. Load PatchLoader.dll into the root domain
* 3. Find and invoke PatchLoader.Loader.Run()
*
* Rest of the work is done on the managed side.
*
*/
#pragma warning( disable : 4267 100 152 6387 4456 6011 )
#include "winapi_util.h"
#include <Windows.h>
#include "config.h"
#include "mono.h"
#include "hook.h"
#include "assert_util.h"
#include "proxy.h"
#include <synchapi.h>
#include <intrin.h>
EXTERN_C IMAGE_DOS_HEADER __ImageBase; // This is provided by MSVC with the infomration about this DLL
HANDLE unhandledMutex;
void ownMonoJitParseOptions(int argc, char * argv[]);
BOOL setOptions = FALSE;
void unhandledException(void* exc, void* data)
{
WaitForSingleObject(unhandledMutex, INFINITE);
void* exception = NULL;
void* mstr = mono_object_to_string(exc, &exception);
if (exception != NULL)
{
#ifdef _VERBOSE
void* monostr = mono_object_to_string(exception, &exception);
if (exception != NULL)
{
DEBUG_BREAK;
LOG("An error occurred while stringifying uncaught error, but the error could not be stringified.\n");
ASSERT(FALSE, L"Uncaught exception; could not stringify");
}
else
{
char* str = mono_string_to_utf8(monostr);
DEBUG_BREAK;
LOG("An error occurred stringifying uncaught error: %s\n", str);
size_t len = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
wchar_t* wstr = memalloc(sizeof(wchar_t) * len);
MultiByteToWideChar(CP_UTF8, 0, str, -1, wstr, len);
ASSERT_F(FALSE, L"Uncaught exception; stringify failed: %s", wstr);
memfree(wstr);
mono_free(str);
}
#else
ASSERT(FALSE, L"Could not stringify uncaught exception");
#endif
}
char* str = mono_string_to_utf8(mstr);
DEBUG_BREAK;
LOG("Uncaught exception: %s\n", str);
size_t len = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
wchar_t* wstr = memalloc(sizeof(wchar_t) * len);
MultiByteToWideChar(CP_UTF8, 0, str, -1, wstr, len);
#ifdef _VERBOSE
ASSERT(FALSE, L"Uncaught exception; see doorstop.log for details");
#else
ASSERT_F(FALSE, L"Uncaught exception: %s", wstr);
#endif
memfree(wstr);
mono_free(str);
ReleaseMutex(unhandledMutex);
}
// The hook for mono_jit_init_version
// We use this since it will always be called once to initialize Mono's JIT
void *ownMonoJitInitVersion(const char *root_domain_name, const char *runtime_version)
{
// Call the original mono_jit_init_version to initialize the Unity Root Domain
if (debug) {
char* opts[1];
opts[0] = "";
ownMonoJitParseOptions(0, opts);
}
#ifdef WIN32
if (debug_info) {
mono_debug_init(MONO_DEBUG_FORMAT_MONO);
}
#endif
void *domain = mono_jit_init_version(root_domain_name, runtime_version);
if (debug_info) {
#ifdef WIN64
mono_debug_init(MONO_DEBUG_FORMAT_MONO);
#endif
mono_debug_domain_create(domain);
}
size_t len = WideCharToMultiByte(CP_UTF8, 0, targetAssembly, -1, NULL, 0, NULL, NULL);
char *dll_path = memalloc(sizeof(char) * len);
WideCharToMultiByte(CP_UTF8, 0, targetAssembly, -1, dll_path, len, NULL, NULL);
LOG("Loading assembly: %s\n", dll_path);
// Load our custom assembly into the domain
void *assembly = mono_domain_assembly_open(domain, dll_path);
if (assembly == NULL)
LOG("Failed to load assembly\n");
memfree(dll_path);
ASSERT_SOFT(assembly != NULL, domain);
// Get assembly's image that contains CIL code
void *image = mono_assembly_get_image(assembly);
ASSERT_SOFT(image != NULL, domain);
// Note: we use the runtime_invoke route since jit_exec will not work on DLLs
// Create a descriptor for a random Main method
void *desc = mono_method_desc_new("*:Main", FALSE);
// Find the first possible Main method in the assembly
void *method = mono_method_desc_search_in_image(desc, image);
ASSERT_SOFT(method != NULL, domain);
void *signature = mono_method_signature(method);
// Get the number of parameters in the signature
UINT32 params = mono_signature_get_param_count(signature);
void **args = NULL;
wchar_t *app_path = NULL;
if (params == 1)
{
// If there is a parameter, it's most likely a string[].
// Populate it as follows
// 0 => path to the game's executable
// 1 => --doorstop-invoke
get_module_path(NULL, &app_path, NULL, 0);
void *exe_path = MONO_STRING(app_path);
void *doorstop_handle = MONO_STRING(L"--doorstop-invoke");
void *args_array = mono_array_new(domain, mono_get_string_class(), 2);
SET_ARRAY_REF(args_array, 0, exe_path);
SET_ARRAY_REF(args_array, 1, doorstop_handle);
args = memalloc(sizeof(void*) * 1);
_ASSERTE(args != nullptr);
args[0] = args_array;
}
LOG("Installing uncaught exception handler\n");
mono_install_unhandled_exception_hook(unhandledException, NULL);
unhandledMutex = CreateMutexW(NULL, FALSE, NULL);
LOG("Invoking method!\n");
void* exception = NULL;
mono_runtime_invoke(method, NULL, args, &exception);
WaitForSingleObject(unhandledMutex, INFINITE); // if the EH is triggered, wait for it
if (args != NULL)
{
memfree(app_path);
memfree(args);
NULL;
}
#ifdef _VERBOSE
if (exception != NULL)
{
void* monostr = mono_object_to_string(exception, &exception);
if (exception != NULL)
LOG("An error occurred while invoking the injector, but the error could not be stringified.\n")
else
{
char* str = mono_string_to_utf8(monostr);
LOG("An error occurred invoking the injector: %s\n", str);
mono_free(str);
}
}
#endif
cleanupConfig();
free_logger();
ReleaseMutex(unhandledMutex);
return domain;
}
void ownMonoJitParseOptions(int argc, char * argv[])
{
setOptions = TRUE;
int size = argc;
#ifdef WIN64
if (debug) size += 2;
#elif defined(WIN32)
if (debug) size += 1;
#endif
char** arguments = memalloc(sizeof(char*) * size);
_ASSERTE(arguments != nullptr);
memcpy(arguments, argv, sizeof(char*) * argc);
if (debug) {
//arguments[argc++] = "--debug";
#ifdef WIN64
arguments[argc++] = "--soft-breakpoints";
#endif
if (debug_server)
arguments[argc] = "--debugger-agent=transport=dt_socket,address=0.0.0.0:10000,server=y";
else
arguments[argc] = "--debugger-agent=transport=dt_socket,address=127.0.0.1:10000,server=n";
}
mono_jit_parse_options(size, arguments);
memfree(arguments);
}
BOOL initialized = FALSE;
void init(HMODULE module)
{
if (!initialized)
{
initialized = TRUE;
LOG("Got mono.dll at %p\n", module);
loadMonoFunctions(module);
}
}
void * WINAPI hookGetProcAddress(HMODULE module, char const *name)
{
if (lstrcmpA(name, "mono_jit_init_version") == 0)
{
init(module);
return (void*)&ownMonoJitInitVersion;
}
if (lstrcmpA(name, "mono_jit_parse_options") == 0 && debug)
{
init(module);
return (void*)&ownMonoJitParseOptions;
}
return (void*)GetProcAddress(module, name);
}
BOOL hookGetMessage(
BOOL isW,
LPMSG msg,
HWND hwnd,
UINT wMsgFilterMin,
UINT wMsgFilterMax
);
BOOL WINAPI hookGetMessageA(LPMSG msg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax)
{
return hookGetMessage(FALSE, msg, hwnd, wMsgFilterMin, wMsgFilterMax);
}
BOOL WINAPI hookGetMessageW(LPMSG msg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax)
{
return hookGetMessage(TRUE, msg, hwnd, wMsgFilterMin, wMsgFilterMax);
}
typedef BOOL(*GetMessageHook)(BOOL isW, BOOL result, LPMSG msg, HWND hwnd, UINT filterMin, UINT filterMax);
GetMessageHook getMessageHook = NULL;
__declspec(dllexport) void __stdcall SetGetMessageHook(GetMessageHook hook) {
getMessageHook = hook;
}
BOOL hookGetMessage(
BOOL isW,
LPMSG msg,
HWND hwnd,
UINT wMsgFilterMin,
UINT wMsgFilterMax
)
{
BOOL loop = FALSE;
BOOL result;
do {
if (isW) {
result = GetMessageW(msg, hwnd, wMsgFilterMin, wMsgFilterMax);
} else {
result = GetMessageA(msg, hwnd, wMsgFilterMin, wMsgFilterMax);
}
if (getMessageHook) {
loop = getMessageHook(isW, result, msg, hwnd, wMsgFilterMin, wMsgFilterMax);
}
} while (loop);
return result;
}
BOOL hookPeekMessage(
BOOL isW,
LPMSG msg,
HWND hwnd,
UINT wMsgFilterMin,
UINT wMsgFilterMax,
UINT wRemoveMsg
);
BOOL WINAPI hookPeekMessageA(LPMSG msg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg)
{
return hookPeekMessage(FALSE, msg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
}
BOOL WINAPI hookPeekMessageW(LPMSG msg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg)
{
return hookPeekMessage(TRUE, msg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
}
typedef BOOL(*PeekMessageHook)(BOOL isW, BOOL result, LPMSG msg, HWND hwnd, UINT filterMin, UINT filterMax, UINT* wRemoveMsg);
PeekMessageHook peekMessageHook = NULL;
__declspec(dllexport) void __stdcall SetPeekMessageHook(PeekMessageHook hook) {
peekMessageHook = hook;
}
BOOL hookPeekMessage(
BOOL isW,
LPMSG msg,
HWND hwnd,
UINT wMsgFilterMin,
UINT wMsgFilterMax,
UINT wRemoveMsg
)
{
BOOL loop = FALSE;
BOOL result;
do {
if (isW) {
result = PeekMessageW(msg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
}
else {
result = PeekMessageA(msg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
}
if (peekMessageHook) {
loop = peekMessageHook(isW, result, msg, hwnd, wMsgFilterMin, wMsgFilterMax, &wRemoveMsg);
}
} while (loop);
return result;
}
BOOL WINAPI DllMain(HINSTANCE hInstDll, DWORD reasonForDllLoad, LPVOID reserved)
{
if (reasonForDllLoad != DLL_PROCESS_ATTACH)
return TRUE;
hHeap = GetProcessHeap();
init_logger();
LOG("Doorstop started!\n");
wchar_t *dll_path = NULL;
size_t dll_path_len = get_module_path((HINSTANCE)&__ImageBase, &dll_path, NULL, 0);
LOG("DLL Path: %S\n", dll_path);
wchar_t *dll_name = get_file_name_no_ext(dll_path, dll_path_len);
LOG("Doorstop DLL Name: %S\n", dll_name);
loadProxy(dll_name);
loadConfig();
// If the loader is disabled, don't inject anything.
if (enabled)
{
LOG("Doorstop enabled!\n");
ASSERT_SOFT(GetFileAttributesW(targetAssembly) != INVALID_FILE_ATTRIBUTES, TRUE);
HMODULE targetModule = GetModuleHandleA("UnityPlayer");
if(targetModule == NULL)
{
LOG("No UnityPlayer.dll; using EXE as the hook target.");
targetModule = GetModuleHandleA(NULL);
}
LOG("Installing IAT hook\n");
if (!iat_hook(targetModule, "kernel32.dll", &GetProcAddress, &hookGetProcAddress))
{
LOG("Failed to install IAT hook!\n");
free_logger();
}
LOG("Hook installed!\n");
LOG("Attempting to install GetMessageA and GetMessageW hooks\n");
if (!iat_hook(targetModule, "user32.dll", &GetMessageA, &hookGetMessageA)) {
LOG("Could not hook GetMessageA! (not an error)\n");
}
if (!iat_hook(targetModule, "user32.dll", &GetMessageW, &hookGetMessageW)) {
LOG("Could not hook GetMessageW! (not an error)\n");
}
LOG("Attempting to install PeekMessageA and PeekMessageW hooks\n");
if (!iat_hook(targetModule, "user32.dll", &PeekMessageA, &hookPeekMessageA)) {
LOG("Could not hook PeekMessageA! (not an error)\n");
}
if (!iat_hook(targetModule, "user32.dll", &PeekMessageW, &hookPeekMessageW)) {
LOG("Could not hook PeekMessageW! (not an error)\n");
}
}
else
{
LOG("Doorstop disabled! memfreeing resources\n");
free_logger();
}
memfree(dll_name);
memfree(dll_path);
return TRUE;
}

+ 105
- 0
Doorstop/Proxy/mono.h View File

@ -0,0 +1,105 @@
/*
* mono.h -- Definitions for Mono C API functions.
*
* The file contains definitions for some of functions provided by Mono C API.
*
* Note: Since we don't use any mono headers, all pointers to mono-related structs are
* replaced with void *.
*/
#pragma once
#pragma warning( disable : 4152 )
#include <windows.h>
// Creates a MonoString based from a C wide string
#define MONO_STRING(str) mono_string_new_utf16(domain, str, wcslen(str))
// Set MonoArray's index to a reference type value (i.e. string)
#define SET_ARRAY_REF(arr, index, refVal) \
{ \
void **p = (void**) mono_array_addr_with_size(arr, sizeof(void*), index); \
mono_gc_wbarrier_set_arrayref(arr, p, refVal); \
}
// Here we define the pointers to some functions within mono.dll
// Note to C learners: these are not signature definitions, but rather "variable"
// definitions with the function pointer type.
// Note: we use void* instead of the real intented structs defined in mono API
// This way we don't need to include or define any of Mono's structs, which saves space
// This, obviously, comes with a drawback of not being able to easily access the contents of the structs
typedef enum {
MONO_DEBUG_FORMAT_NONE,
MONO_DEBUG_FORMAT_MONO,
/* Deprecated, the mdb debugger is not longer supported. */
MONO_DEBUG_FORMAT_DEBUGGER
} MonoDebugFormat;
void (*mono_jit_parse_options)(int argc, char * argv[]);
void (*mono_debug_init)(MonoDebugFormat format);
void(*mono_debug_domain_create)(void*);
void *(*mono_jit_init_version)(const char *root_domain_name, const char *runtime_version);
void *(*mono_domain_assembly_open)(void *domain, const char *name);
void *(*mono_assembly_get_image)(void *assembly);
void *(*mono_runtime_invoke)(void *method, void *obj, void **params, void **exc);
void *(*mono_method_desc_new)(const char *name, int include_namespace);
void *(*mono_method_desc_search_in_image)(void *desc, void *image);
void *(*mono_method_signature)(void *method);
UINT32 (*mono_signature_get_param_count)(void *sig);
void *(*mono_array_new)(void *domain, void *eclass, uintptr_t n);
void (*mono_gc_wbarrier_set_arrayref)(void *arr, void *slot_ptr, void *value);
char *(*mono_array_addr_with_size)(void *arr, int size, uintptr_t idx);
void *(*mono_get_string_class)();
void *(*mono_string_new_utf16)(void *domain, const wchar_t *text, INT32 len);
void* (*mono_object_to_string)(void* obj, void** exc);
char* (*mono_string_to_utf8)(void* str);
void (*mono_free)(void*);
/* Installs a function which is called when the runtime encounters an unhandled exception.
* This hook isn't expected to return.
* If no hook has been installed, the runtime will print a message before aborting.
*/
typedef void (*MonoUnhandledExceptionFunc)(void* exc, void* user_data);
void (*mono_install_unhandled_exception_hook)(MonoUnhandledExceptionFunc func, void* user_data);
/**
* \brief Loads Mono C API function pointers so that the above definitions can be called.
* \param monoLib Mono.dll module.
*/
inline void loadMonoFunctions(HMODULE monoLib)
{
// Enjoy the fact that C allows such sloppy casting
// In C++ you would have to cast to the precise function pointer type
#define GET_MONO_PROC(name) name = (void*)GetProcAddress(monoLib, #name)
// Find and assign all our functions that we are going to use
GET_MONO_PROC(mono_debug_domain_create);
GET_MONO_PROC(mono_domain_assembly_open);
GET_MONO_PROC(mono_assembly_get_image);
GET_MONO_PROC(mono_runtime_invoke);
GET_MONO_PROC(mono_debug_init);
GET_MONO_PROC(mono_jit_init_version);
GET_MONO_PROC(mono_jit_parse_options);
GET_MONO_PROC(mono_method_desc_new);
GET_MONO_PROC(mono_method_desc_search_in_image);
GET_MONO_PROC(mono_method_signature);
GET_MONO_PROC(mono_signature_get_param_count);
GET_MONO_PROC(mono_array_new);
GET_MONO_PROC(mono_get_string_class);
GET_MONO_PROC(mono_string_new_utf16);
GET_MONO_PROC(mono_gc_wbarrier_set_arrayref);
GET_MONO_PROC(mono_array_addr_with_size);
GET_MONO_PROC(mono_object_to_string);
GET_MONO_PROC(mono_string_to_utf8);
GET_MONO_PROC(mono_free);
GET_MONO_PROC(mono_install_unhandled_exception_hook);
}

+ 133
- 0
Doorstop/Proxy/proxy.c View File

@ -0,0 +1,133 @@
/* ==================================
* COMPUTER GENERATED -- DO NOT EDIT
* ==================================
*
* This file contains the definitions for all proxy functions this DLL supports.
*
* The proxies are very simple functions that should be optimizied into a
* single JMP instruction without editing the stack at all.
*
* NOTE: While this works, this is a somewhat hackish approach that is based on how
* the compiler optimizes the code. That said, the proxy will not work on Debug build currently
* (that can be fixed by changing the appropriate compile flag that I am yet to locate).
*/
#pragma warning( disable : 4244 )
#include <windows.h>
#define ADD_ORIGINAL(i, name) originalFunctions[i] = GetProcAddress(dll, #name)
#define PROXY(i, name) \
__declspec(dllexport) ULONG __stdcall name() \
{ \
return originalFunctions[i](); \
}
FARPROC originalFunctions[50] = {0};
void loadFunctions(HMODULE dll)
{
ADD_ORIGINAL(0, WinHttpAddRequestHeaders);
ADD_ORIGINAL(1, WinHttpAutoProxySvcMain);
ADD_ORIGINAL(2, WinHttpCheckPlatform);
ADD_ORIGINAL(3, WinHttpCloseHandle);
ADD_ORIGINAL(4, WinHttpConnect);
ADD_ORIGINAL(5, WinHttpConnectionDeleteProxyInfo);
ADD_ORIGINAL(6, WinHttpConnectionFreeNameList);
ADD_ORIGINAL(7, WinHttpConnectionFreeProxyInfo);
ADD_ORIGINAL(8, WinHttpConnectionFreeProxyList);
ADD_ORIGINAL(9, WinHttpConnectionGetNameList);
ADD_ORIGINAL(10, WinHttpConnectionGetProxyInfo);
ADD_ORIGINAL(11, WinHttpConnectionGetProxyList);
ADD_ORIGINAL(12, WinHttpConnectionSetProxyInfo);
ADD_ORIGINAL(13, WinHttpCrackUrl);
ADD_ORIGINAL(14, WinHttpCreateProxyResolver);
ADD_ORIGINAL(15, WinHttpCreateUrl);
ADD_ORIGINAL(16, WinHttpDetectAutoProxyConfigUrl);
ADD_ORIGINAL(17, WinHttpFreeProxyResult);
ADD_ORIGINAL(18, WinHttpGetDefaultProxyConfiguration);
ADD_ORIGINAL(19, WinHttpGetIEProxyConfigForCurrentUser);
ADD_ORIGINAL(20, WinHttpGetProxyForUrl);
ADD_ORIGINAL(21, WinHttpGetProxyForUrlEx);
ADD_ORIGINAL(22, WinHttpGetProxyResult);
ADD_ORIGINAL(23, WinHttpGetTunnelSocket);
ADD_ORIGINAL(24, WinHttpOpen);
ADD_ORIGINAL(25, WinHttpOpenRequest);
ADD_ORIGINAL(26, WinHttpProbeConnectivity);
ADD_ORIGINAL(27, WinHttpQueryAuthSchemes);
ADD_ORIGINAL(28, WinHttpQueryDataAvailable);
ADD_ORIGINAL(29, WinHttpQueryHeaders);
ADD_ORIGINAL(30, WinHttpQueryOption);
ADD_ORIGINAL(31, WinHttpReadData);
ADD_ORIGINAL(32, WinHttpReceiveResponse);
ADD_ORIGINAL(33, WinHttpResetAutoProxy);
ADD_ORIGINAL(34, WinHttpSaveProxyCredentials);
ADD_ORIGINAL(35, WinHttpSendRequest);
ADD_ORIGINAL(36, WinHttpSetCredentials);
ADD_ORIGINAL(37, WinHttpSetDefaultProxyConfiguration);
ADD_ORIGINAL(38, WinHttpSetOption);
ADD_ORIGINAL(39, WinHttpSetStatusCallback);
ADD_ORIGINAL(40, WinHttpSetTimeouts);
ADD_ORIGINAL(41, WinHttpTimeFromSystemTime);
ADD_ORIGINAL(42, WinHttpTimeToSystemTime);
ADD_ORIGINAL(43, WinHttpWebSocketClose);
ADD_ORIGINAL(44, WinHttpWebSocketCompleteUpgrade);
ADD_ORIGINAL(45, WinHttpWebSocketQueryCloseStatus);
ADD_ORIGINAL(46, WinHttpWebSocketReceive);
ADD_ORIGINAL(47, WinHttpWebSocketSend);
ADD_ORIGINAL(48, WinHttpWebSocketShutdown);
ADD_ORIGINAL(49, WinHttpWriteData);
}
PROXY(0, WinHttpAddRequestHeaders);
PROXY(1, WinHttpAutoProxySvcMain);
PROXY(2, WinHttpCheckPlatform);
PROXY(3, WinHttpCloseHandle);
PROXY(4, WinHttpConnect);
PROXY(5, WinHttpConnectionDeleteProxyInfo);
PROXY(6, WinHttpConnectionFreeNameList);
PROXY(7, WinHttpConnectionFreeProxyInfo);
PROXY(8, WinHttpConnectionFreeProxyList);
PROXY(9, WinHttpConnectionGetNameList);
PROXY(10, WinHttpConnectionGetProxyInfo);
PROXY(11, WinHttpConnectionGetProxyList);
PROXY(12, WinHttpConnectionSetProxyInfo);
PROXY(13, WinHttpCrackUrl);
PROXY(14, WinHttpCreateProxyResolver);
PROXY(15, WinHttpCreateUrl);
PROXY(16, WinHttpDetectAutoProxyConfigUrl);
PROXY(17, WinHttpFreeProxyResult);
PROXY(18, WinHttpGetDefaultProxyConfiguration);
PROXY(19, WinHttpGetIEProxyConfigForCurrentUser);
PROXY(20, WinHttpGetProxyForUrl);
PROXY(21, WinHttpGetProxyForUrlEx);
PROXY(22, WinHttpGetProxyResult);
PROXY(23, WinHttpGetTunnelSocket);
PROXY(24, WinHttpOpen);
PROXY(25, WinHttpOpenRequest);
PROXY(26, WinHttpProbeConnectivity);
PROXY(27, WinHttpQueryAuthSchemes);
PROXY(28, WinHttpQueryDataAvailable);
PROXY(29, WinHttpQueryHeaders);
PROXY(30, WinHttpQueryOption);
PROXY(31, WinHttpReadData);
PROXY(32, WinHttpReceiveResponse);
PROXY(33, WinHttpResetAutoProxy);
PROXY(34, WinHttpSaveProxyCredentials);
PROXY(35, WinHttpSendRequest);
PROXY(36, WinHttpSetCredentials);
PROXY(37, WinHttpSetDefaultProxyConfiguration);
PROXY(38, WinHttpSetOption);
PROXY(39, WinHttpSetStatusCallback);
PROXY(40, WinHttpSetTimeouts);
PROXY(41, WinHttpTimeFromSystemTime);
PROXY(42, WinHttpTimeToSystemTime);
PROXY(43, WinHttpWebSocketClose);
PROXY(44, WinHttpWebSocketCompleteUpgrade);
PROXY(45, WinHttpWebSocketQueryCloseStatus);
PROXY(46, WinHttpWebSocketReceive);
PROXY(47, WinHttpWebSocketSend);
PROXY(48, WinHttpWebSocketShutdown);
PROXY(49, WinHttpWriteData);

+ 54
- 0
Doorstop/Proxy/proxy.def View File

@ -0,0 +1,54 @@
LIBRARY proxy.dll
EXPORTS
WinHttpAddRequestHeaders @1
WinHttpAutoProxySvcMain @2
WinHttpCheckPlatform @3
WinHttpCloseHandle @4
WinHttpConnect @5
WinHttpConnectionDeleteProxyInfo @6
WinHttpConnectionFreeNameList @7
WinHttpConnectionFreeProxyInfo @8
WinHttpConnectionFreeProxyList @9
WinHttpConnectionGetNameList @10
WinHttpConnectionGetProxyInfo @11
WinHttpConnectionGetProxyList @12
WinHttpConnectionSetProxyInfo @13
WinHttpCrackUrl @14
WinHttpCreateProxyResolver @15
WinHttpCreateUrl @16
WinHttpDetectAutoProxyConfigUrl @17
WinHttpFreeProxyResult @18
WinHttpGetDefaultProxyConfiguration @19
WinHttpGetIEProxyConfigForCurrentUser @20
WinHttpGetProxyForUrl @21
WinHttpGetProxyForUrlEx @22
WinHttpGetProxyResult @23
WinHttpGetTunnelSocket @24
WinHttpOpen @25
WinHttpOpenRequest @26
WinHttpProbeConnectivity @27
WinHttpQueryAuthSchemes @28
WinHttpQueryDataAvailable @29
WinHttpQueryHeaders @30
WinHttpQueryOption @31
WinHttpReadData @32
WinHttpReceiveResponse @33
WinHttpResetAutoProxy @34
WinHttpSaveProxyCredentials @35
WinHttpSendRequest @36
WinHttpSetCredentials @37
WinHttpSetDefaultProxyConfiguration @38
WinHttpSetOption @39
WinHttpSetStatusCallback @40
WinHttpSetTimeouts @41
WinHttpTimeFromSystemTime @42
WinHttpTimeToSystemTime @43
WinHttpWebSocketClose @44
WinHttpWebSocketCompleteUpgrade @45
WinHttpWebSocketQueryCloseStatus @46
WinHttpWebSocketReceive @47
WinHttpWebSocketSend @48
WinHttpWebSocketShutdown @49
WinHttpWriteData @50
SetGetMessageHook @51
SetPeekMessageHook @52

+ 74
- 0
Doorstop/Proxy/proxy.h View File

@ -0,0 +1,74 @@
/*
* Proxy.h -- Definitions for proxy-related functionality
*
* The proxy works roughly as follows:
* - We define our exports in proxy.c (computer generated)
* - loadProxy initializes the proxy:
* 1. Look up the name of this DLL
* 2. Find the original DLL with the same name
* 3. Load the original DLL
* 4. Load all functions into originalFunctions array
*
* For more information, refer to proxy.c
*/
#pragma once
#pragma warning( disable : 4267 6387 6386 )
#include <Windows.h>
#include <Shlwapi.h>
#include "assert_util.h"
#include <crtdbg.h>
#define ALT_POSTFIX L"_alt.dll"
#define DLL_POSTFIX L".dll"
extern FARPROC originalFunctions[];
extern void loadFunctions(HMODULE dll);
// Load the proxy functions into memory
inline void loadProxy(wchar_t *moduleName)
{
size_t module_name_len = wcslen(moduleName);
size_t alt_name_len = module_name_len + STR_LEN(ALT_POSTFIX);
wchar_t *alt_name = memalloc(sizeof(wchar_t) * alt_name_len);
wmemcpy(alt_name, moduleName, module_name_len);
wmemcpy(alt_name + module_name_len, ALT_POSTFIX, STR_LEN(ALT_POSTFIX));
wchar_t *dll_path = NULL; // The final DLL path
const int alt_full_path_len = GetFullPathNameW(alt_name, 0, NULL, NULL);
wchar_t *alt_full_path = memalloc(sizeof(wchar_t) * alt_full_path_len);
GetFullPathNameW(alt_name, alt_full_path_len, alt_full_path, NULL);
memfree(alt_name);
LOG("Looking for original DLL from %S\n", alt_full_path);
// Try to look for the alternative first in the same directory.
HMODULE handle = LoadLibrary(alt_full_path);
if (handle == NULL)
{
size_t system_dir_len = GetSystemDirectoryW(NULL, 0);
dll_path = memalloc(sizeof(wchar_t) * (system_dir_len + module_name_len + STR_LEN(DLL_POSTFIX)));
_ASSERTE(dll_path != nullptr);
GetSystemDirectoryW(dll_path, system_dir_len);
dll_path[system_dir_len - 1] = L'\\';
wmemcpy(dll_path + system_dir_len, moduleName, module_name_len);
wmemcpy(dll_path + system_dir_len + module_name_len, DLL_POSTFIX, STR_LEN(DLL_POSTFIX));
LOG("Looking for original DLL from %S\n", dll_path);
handle = LoadLibraryW(dll_path);
}
ASSERT_F(handle != NULL, L"Unable to load the original %s.dll (looked from system directory and from %s_alt.dll)!",
moduleName, moduleName);
memfree(alt_full_path);
memfree(dll_path);
loadFunctions(handle);
}

BIN
Doorstop/Proxy/proxy.rc View File


+ 63
- 0
Doorstop/Proxy/proxydefs.txt View File

@ -0,0 +1,63 @@
SvchostPushServiceGlobals
WinHttpAddRequestHeaders
WinHttpAutoProxySvcMain
WinHttpCheckPlatform
WinHttpCloseHandle
WinHttpConnect
WinHttpConnectionDeletePolicyEntries
WinHttpConnectionDeleteProxyInfo
WinHttpConnectionFreeNameList
WinHttpConnectionFreeProxyInfo
WinHttpConnectionFreeProxyList
WinHttpConnectionGetNameList
WinHttpConnectionGetProxyInfo
WinHttpConnectionGetProxyList
WinHttpConnectionSetPolicyEntries
WinHttpConnectionSetProxyInfo
WinHttpConnectionUpdateIfIndexTable
WinHttpCrackUrl
WinHttpCreateProxyResolver
WinHttpCreateUrl
WinHttpDetectAutoProxyConfigUrl
WinHttpFreeProxyResult
WinHttpFreeProxyResultEx
WinHttpFreeProxySettings
WinHttpGetDefaultProxyConfiguration
WinHttpGetIEProxyConfigForCurrentUser
WinHttpGetProxyForUrl
WinHttpGetProxyForUrlEx
WinHttpGetProxyForUrlEx2
WinHttpGetProxyForUrlHvsi
WinHttpGetProxyResult
WinHttpGetProxyResultEx
WinHttpGetProxySettingsVersion
WinHttpGetTunnelSocket
WinHttpOpen
WinHttpOpenRequest
WinHttpProbeConnectivity
WinHttpQueryAuthSchemes
WinHttpQueryDataAvailable
WinHttpQueryHeaders
WinHttpQueryOption
WinHttpReadData
WinHttpReadProxySettings
WinHttpReadProxySettingsHvsi
WinHttpReceiveResponse
WinHttpResetAutoProxy
WinHttpSaveProxyCredentials
WinHttpSendRequest
WinHttpSetCredentials
WinHttpSetDefaultProxyConfiguration
WinHttpSetOption
WinHttpSetStatusCallback
WinHttpSetTimeouts
WinHttpTimeFromSystemTime
WinHttpTimeToSystemTime
WinHttpWebSocketClose
WinHttpWebSocketCompleteUpgrade
WinHttpWebSocketQueryCloseStatus
WinHttpWebSocketReceive
WinHttpWebSocketSend
WinHttpWebSocketShutdown
WinHttpWriteData
WinHttpWriteProxySettings

+ 65
- 0
Doorstop/Proxy/winapi_util.h View File

@ -0,0 +1,65 @@
#pragma once
#pragma warning( disable : 4267 6387 )
#include <windows.h>
#include "crt.h"
inline size_t get_module_path(HMODULE module, wchar_t **result, size_t *size, size_t free_space)
{
size_t i = 0;
size_t len, s;
*result = NULL;
do
{
if (*result != NULL)
memfree(*result);
i++;
s = i * MAX_PATH + 1;
*result = memalloc(sizeof(wchar_t) * s);
len = GetModuleFileNameW(module, *result, s);
}
while (GetLastError() == ERROR_INSUFFICIENT_BUFFER && s - len >= free_space);
if (size != NULL)
*size = s;
return len;
}
inline wchar_t *get_ini_entry(const wchar_t *config_file, const wchar_t *section, const wchar_t *key,
const wchar_t *default_val)
{
size_t i = 0;
size_t size, read;
wchar_t *result = NULL;
do
{
if (result != NULL)
memfree(result);
i++;
size = i * MAX_PATH + 1;
result = memalloc(sizeof(wchar_t) * size);
read = GetPrivateProfileStringW(section, key, default_val, result, size, config_file);
}
while (read == size - 1);
return result;
}
inline wchar_t *get_file_name_no_ext(wchar_t *str, size_t len)
{
size_t ext_index = len;
size_t i;
for (i = len; i > 0; i--)
{
wchar_t c = *(str + i);
if (c == L'.' && ext_index == len)
ext_index = i;
else if (c == L'\\')
break;
}
size_t result_len = ext_index - i;
wchar_t *result = memcalloc(sizeof(wchar_t) * result_len);
wmemcpy(result, str + i + 1, result_len - 1);
return result;
}

+ 47
- 0
Doorstop/README.md View File

@ -0,0 +1,47 @@
<p align="center">
<img src="https://raw.githubusercontent.com/NeighTools/UnityDoorstop/master/docs/logo_sm.png"/>
</p>
![Github All Releases](https://img.shields.io/github/downloads/NeighTools/UnityDoorstop/total.svg)
![GitHub release](https://img.shields.io/github/release/NeighTools/UnityDoorstop.svg)
![license](https://img.shields.io/github/license/NeighTools/UnityDoorstop.svg)
*Run managed code before Unity does!*
# Unity Doorstop
Doorstop is a tool to execute managed assemblies inside Unity as early as possible!
This repository is indented mainly for developers!
Developers should package Doorstop into their applications for the end-users.
## Features
* **Runs first**: Doorstop runs its own code before Unity has an ability to do so.
* **Configurable**: A very basic configuration file allows to specify your own assembly to execute!
* **Public domain!** You are fully free to embed Doorstop into your application!
## Guides for users and developers on [the wiki](https://github.com/NeighTools/UnityDoorstop/wiki)
## Building
To build, you will need:
* Visual Studio 2017 (2015 might work as well with some modifications)
* Visual C++ Toolset v140
* .NET Framework 3.5 or newer (only for the example, not used by the proxy)
* Python (only to generate proxy functions; not needed to build)
Clone, open in Visual Studio, select the platform (x86/x64) and build.
#### Custom proxy functions
Doorstop's proxy is flexible and allows to be load as different DLLs.
You can modify which functions you want to proxy by adding/removing function names in `Proxy/proxydefs.txt` and running `proxygen/proxy_gen.py ../Proxy/proxydefs.txt` to generate an appropriate proxy functions.
The current set up allows to use the proxy for the following DLLs:
* `winhttp.dll` (All exports)
* `iphlpapi.dll` (Only `GetIpAddrTable`)
(WIP: Currently all build results are placed in separate folders; will be changed later)

+ 77
- 0
Doorstop/UnityDoorstop.sln View File

@ -0,0 +1,77 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27428.2043
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "proxy", "Proxy\Proxy.vcxproj", "{88609E16-731F-46C9-8139-6B1A7A83240D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DoorstopTest", "DoorstopTest\DoorstopTest.csproj", "{62B61CCC-0775-4CF4-B37A-EB5E33CBD08C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
Verbose_Release|Any CPU = Verbose_Release|Any CPU
Verbose_Release|x64 = Verbose_Release|x64
Verbose_Release|x86 = Verbose_Release|x86
Verbose|Any CPU = Verbose|Any CPU
Verbose|x64 = Verbose|x64
Verbose|x86 = Verbose|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{88609E16-731F-46C9-8139-6B1A7A83240D}.Debug|Any CPU.ActiveCfg = Debug|Win32
{88609E16-731F-46C9-8139-6B1A7A83240D}.Debug|x64.ActiveCfg = Debug|x64
{88609E16-731F-46C9-8139-6B1A7A83240D}.Debug|x64.Build.0 = Debug|x64
{88609E16-731F-46C9-8139-6B1A7A83240D}.Debug|x86.ActiveCfg = Debug|Win32
{88609E16-731F-46C9-8139-6B1A7A83240D}.Debug|x86.Build.0 = Debug|Win32
{88609E16-731F-46C9-8139-6B1A7A83240D}.Release|Any CPU.ActiveCfg = Release|Win32
{88609E16-731F-46C9-8139-6B1A7A83240D}.Release|x64.ActiveCfg = Release|x64
{88609E16-731F-46C9-8139-6B1A7A83240D}.Release|x64.Build.0 = Release|x64
{88609E16-731F-46C9-8139-6B1A7A83240D}.Release|x86.ActiveCfg = Release|Win32
{88609E16-731F-46C9-8139-6B1A7A83240D}.Release|x86.Build.0 = Release|Win32
{88609E16-731F-46C9-8139-6B1A7A83240D}.Verbose_Release|Any CPU.ActiveCfg = Verbose_Release|Win32
{88609E16-731F-46C9-8139-6B1A7A83240D}.Verbose_Release|x64.ActiveCfg = Verbose_Release|x64
{88609E16-731F-46C9-8139-6B1A7A83240D}.Verbose_Release|x64.Build.0 = Verbose_Release|x64
{88609E16-731F-46C9-8139-6B1A7A83240D}.Verbose_Release|x86.ActiveCfg = Verbose_Release|Win32
{88609E16-731F-46C9-8139-6B1A7A83240D}.Verbose_Release|x86.Build.0 = Verbose_Release|Win32
{88609E16-731F-46C9-8139-6B1A7A83240D}.Verbose|Any CPU.ActiveCfg = Verbose|Win32
{88609E16-731F-46C9-8139-6B1A7A83240D}.Verbose|x64.ActiveCfg = Verbose|x64
{88609E16-731F-46C9-8139-6B1A7A83240D}.Verbose|x64.Build.0 = Verbose|x64
{88609E16-731F-46C9-8139-6B1A7A83240D}.Verbose|x86.ActiveCfg = Verbose|Win32
{88609E16-731F-46C9-8139-6B1A7A83240D}.Verbose|x86.Build.0 = Verbose|Win32
{62B61CCC-0775-4CF4-B37A-EB5E33CBD08C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{62B61CCC-0775-4CF4-B37A-EB5E33CBD08C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{62B61CCC-0775-4CF4-B37A-EB5E33CBD08C}.Debug|x64.ActiveCfg = Debug|Any CPU
{62B61CCC-0775-4CF4-B37A-EB5E33CBD08C}.Debug|x64.Build.0 = Debug|Any CPU
{62B61CCC-0775-4CF4-B37A-EB5E33CBD08C}.Debug|x86.ActiveCfg = Debug|Any CPU
{62B61CCC-0775-4CF4-B37A-EB5E33CBD08C}.Debug|x86.Build.0 = Debug|Any CPU
{62B61CCC-0775-4CF4-B37A-EB5E33CBD08C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{62B61CCC-0775-4CF4-B37A-EB5E33CBD08C}.Release|Any CPU.Build.0 = Release|Any CPU
{62B61CCC-0775-4CF4-B37A-EB5E33CBD08C}.Release|x64.ActiveCfg = Release|Any CPU
{62B61CCC-0775-4CF4-B37A-EB5E33CBD08C}.Release|x64.Build.0 = Release|Any CPU
{62B61CCC-0775-4CF4-B37A-EB5E33CBD08C}.Release|x86.ActiveCfg = Release|Any CPU
{62B61CCC-0775-4CF4-B37A-EB5E33CBD08C}.Release|x86.Build.0 = Release|Any CPU
{62B61CCC-0775-4CF4-B37A-EB5E33CBD08C}.Verbose_Release|Any CPU.ActiveCfg = Verbose_Release|Any CPU
{62B61CCC-0775-4CF4-B37A-EB5E33CBD08C}.Verbose_Release|Any CPU.Build.0 = Verbose_Release|Any CPU
{62B61CCC-0775-4CF4-B37A-EB5E33CBD08C}.Verbose_Release|x64.ActiveCfg = Verbose_Release|Any CPU
{62B61CCC-0775-4CF4-B37A-EB5E33CBD08C}.Verbose_Release|x64.Build.0 = Verbose_Release|Any CPU
{62B61CCC-0775-4CF4-B37A-EB5E33CBD08C}.Verbose_Release|x86.ActiveCfg = Verbose_Release|Any CPU
{62B61CCC-0775-4CF4-B37A-EB5E33CBD08C}.Verbose_Release|x86.Build.0 = Verbose_Release|Any CPU
{62B61CCC-0775-4CF4-B37A-EB5E33CBD08C}.Verbose|Any CPU.ActiveCfg = Verbose|Any CPU
{62B61CCC-0775-4CF4-B37A-EB5E33CBD08C}.Verbose|Any CPU.Build.0 = Verbose|Any CPU
{62B61CCC-0775-4CF4-B37A-EB5E33CBD08C}.Verbose|x64.ActiveCfg = Verbose|Any CPU
{62B61CCC-0775-4CF4-B37A-EB5E33CBD08C}.Verbose|x64.Build.0 = Verbose|Any CPU
{62B61CCC-0775-4CF4-B37A-EB5E33CBD08C}.Verbose|x86.ActiveCfg = Verbose|Any CPU
{62B61CCC-0775-4CF4-B37A-EB5E33CBD08C}.Verbose|x86.Build.0 = Verbose|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4EF47C82-18DC-4E9E-A878-8C003FFB303D}
EndGlobalSection
EndGlobal

BIN
Doorstop/docs/logo.png View File

Before After
Width: 3469  |  Height: 649  |  Size: 84 KiB

BIN
Doorstop/docs/logo_sm.png View File

Before After
Width: 694  |  Height: 130  |  Size: 14 KiB

+ 52
- 0
Doorstop/proxygen/proxy_gen.py View File

@ -0,0 +1,52 @@
import sys
import os
#import pefile
import io
import string
def main():
path = os.path.dirname(os.path.realpath(sys.argv[0]))
file = sys.argv[1]
proxies = io.StringIO()
proxy_add = io.StringIO()
proxy_def = io.StringIO()
proxy_def_file = io.StringIO()
count = 0
""" for dll in dlls:
pe = pefile.PE(dll, fast_load=True)
pe.parse_data_directories()
for exp in pe.DIRECTORY_ENTRY_EXPORT.symbols:
name = exp.name.decode()
proxies.write("%s\n" % name)
proxy_add.write("ADD_ORIGINAL(%d, %s);\n" % (count, name))
proxy_def.write("PROXY(%d, %s);\n" % (count, name))
count = count + 1 """
with open(file, "r") as includes:
names = includes.readlines()
for name in names:
name = name.strip()
proxies.write(f"{name}\n")
proxy_add.write(f"ADD_ORIGINAL({count}, {name});\n")
proxy_def.write(f"PROXY({count}, {name});\n")
proxy_def_file.write(f" {name} @{count+1}\n")
count = count + 1
with open(f"{path}\\templates\\proxy_template.c", "r") as proxy_file:
new_proxy = string.Template(proxy_file.read()).safe_substitute(proxy_count=count, proxy_add=proxy_add.getvalue(), proxy_def=proxy_def.getvalue())
with open(f"{path}\\..\\Proxy\\proxy.c", "w") as proxy_c_file:
proxy_c_file.write(new_proxy)
with open(f"{path}\\templates\\proxy_template.def", "r") as proxy_file:
new_proxy_def = string.Template(proxy_file.read()).safe_substitute(proxy_exports=proxy_def_file.getvalue())
with open(f"{path}\\..\\Proxy\\proxy.def", "w") as proxy_def_file:
proxy_def_file.write(new_proxy_def)
if __name__ == "__main__":
main()

+ 34
- 0
Doorstop/proxygen/templates/proxy_template.c View File

@ -0,0 +1,34 @@
/* ==================================
* COMPUTER GENERATED -- DO NOT EDIT
* ==================================
*
* This file contains the definitions for all proxy functions this DLL supports.
*
* The proxies are very simple functions that should be optimizied into a
* single JMP instruction without editing the stack at all.
*
* NOTE: While this works, this is a somewhat hackish approach that is based on how
* the compiler optimizes the code. That said, the proxy will not work on Debug build currently
* (that can be fixed by changing the appropriate compile flag that I am yet to locate).
*/
#pragma warning( disable : 4244 )
#include <windows.h>
#define ADD_ORIGINAL(i, name) originalFunctions[i] = GetProcAddress(dll, #name)
#define PROXY(i, name) \
__declspec(dllexport) ULONG __stdcall name() \
{ \
return originalFunctions[i](); \
}
FARPROC originalFunctions[${proxy_count}] = {0};
void loadFunctions(HMODULE dll)
{
${proxy_add}
}
${proxy_def}

+ 3
- 0
Doorstop/proxygen/templates/proxy_template.def View File

@ -0,0 +1,3 @@
LIBRARY proxy.dll
EXPORTS
${proxy_exports}

+ 50
- 0
Doorstop/proxygen/winhttp.txt View File

@ -0,0 +1,50 @@
WinHttpAddRequestHeaders
WinHttpAutoProxySvcMain
WinHttpCheckPlatform
WinHttpCloseHandle
WinHttpConnect
WinHttpConnectionDeleteProxyInfo
WinHttpConnectionFreeNameList
WinHttpConnectionFreeProxyInfo
WinHttpConnectionFreeProxyList
WinHttpConnectionGetNameList
WinHttpConnectionGetProxyInfo
WinHttpConnectionGetProxyList
WinHttpConnectionSetProxyInfo
WinHttpCrackUrl
WinHttpCreateProxyResolver
WinHttpCreateUrl
WinHttpDetectAutoProxyConfigUrl
WinHttpFreeProxyResult
WinHttpGetDefaultProxyConfiguration
WinHttpGetIEProxyConfigForCurrentUser
WinHttpGetProxyForUrl
WinHttpGetProxyForUrlEx
WinHttpGetProxyResult
WinHttpGetTunnelSocket
WinHttpOpen
WinHttpOpenRequest
WinHttpProbeConnectivity
WinHttpQueryAuthSchemes
WinHttpQueryDataAvailable
WinHttpQueryHeaders
WinHttpQueryOption
WinHttpReadData
WinHttpReceiveResponse
WinHttpResetAutoProxy
WinHttpSaveProxyCredentials
WinHttpSendRequest
WinHttpSetCredentials
WinHttpSetDefaultProxyConfiguration
WinHttpSetOption
WinHttpSetStatusCallback
WinHttpSetTimeouts
WinHttpTimeFromSystemTime
WinHttpTimeToSystemTime
WinHttpWebSocketClose
WinHttpWebSocketCompleteUpgrade
WinHttpWebSocketQueryCloseStatus
WinHttpWebSocketReceive
WinHttpWebSocketSend
WinHttpWebSocketShutdown
WinHttpWriteData

Loading…
Cancel
Save