Full Code of earthquake/UniversalDVC for AI

master 9b2f5c0b4bb5 cached
30 files
98.6 KB
28.9k tokens
48 symbols
1 requests
Download .txt
Repository: earthquake/UniversalDVC
Branch: master
Commit: 9b2f5c0b4bb5
Files: 30
Total size: 98.6 KB

Directory structure:
gitextract_jle45i16/

├── .gitattributes
├── .gitignore
├── LICENSE.md
├── README.md
├── UDVC-Plugin/
│   ├── Resource.h
│   ├── UDVC-Plugin.cpp
│   ├── UDVC-Plugin.def
│   ├── UDVC-Plugin.h
│   ├── UDVC-Plugin.rc
│   ├── UDVC-Plugin.rgs
│   ├── UDVC-Plugin.vcxproj
│   ├── UDVC-Plugin.vcxproj.filters
│   ├── UDVC-PluginPS.vcxproj
│   ├── UDVC-PluginPS.vcxproj.filters
│   ├── UDVC-Pluginps.def
│   ├── UDVCPlugin.idl
│   ├── compreg.cpp
│   ├── compreg.h
│   ├── dllfunc.cpp
│   ├── dllmain.cpp
│   ├── dllmain.h
│   ├── stdafx.cpp
│   ├── stdafx.h
│   └── targetver.h
├── UDVC-Plugin.reg
├── UDVC-Plugin.sln
└── UDVC-Server/
    ├── UDVC-Server.cpp
    ├── UDVC-Server.vcxproj
    ├── UDVC-Server.vcxproj.filters
    └── targetver.h

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitattributes
================================================
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto

###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs     diff=csharp

###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following 
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln       merge=binary
#*.csproj    merge=binary
#*.vbproj    merge=binary
#*.vcxproj   merge=binary
#*.vcproj    merge=binary
#*.dbproj    merge=binary
#*.fsproj    merge=binary
#*.lsproj    merge=binary
#*.wixproj   merge=binary
#*.modelproj merge=binary
#*.sqlproj   merge=binary
#*.wwaproj   merge=binary

###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg   binary
#*.png   binary
#*.gif   binary

###############################################################################
# diff behavior for common document formats
# 
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the 
# entries below.
###############################################################################
#*.doc   diff=astextplain
#*.DOC   diff=astextplain
#*.docx  diff=astextplain
#*.DOCX  diff=astextplain
#*.dot   diff=astextplain
#*.DOT   diff=astextplain
#*.pdf   diff=astextplain
#*.PDF   diff=astextplain
#*.rtf   diff=astextplain
#*.RTF   diff=astextplain


================================================
FILE: .gitignore
================================================
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.

# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates

# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs

# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
[Xx]64/
[Xx]86/
[Bb]uild/
bld/
[Bb]in/
[Oo]bj/

# 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

# DNX
project.lock.json
artifacts/

*_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

# 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

# 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: Un-comment the next line if you do not want to checkin
# your web deploy settings because they may include unencrypted
# passwords
#*.pubxml
*.publishproj

# 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 ignoreable files
*.nuget.props
*.nuget.targets

# Microsoft Azure Build Output
csx/
*.build.csdef

# Microsoft Azure Emulator
ecf/
rcf/

# Windows Store app package directory
AppPackages/
BundleArtifacts/

# 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/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs

# 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

# 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

# Visual Studio 6 build log
*.plg

# Visual Studio 6 workspace options file
*.opt

# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions

# LightSwitch generated files
GeneratedArtifacts/
ModelManifest.xml

# Paket dependency manager
.paket/paket.exe

# FAKE - F# Make
.fake/
/UDVC-Server/ReadMe.txt


================================================
FILE: LICENSE.md
================================================
MIT License

Copyright (c) 2020 Balazs Bucsay

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# Universal Dynamic Virtual Channel connector for Remote Desktop Services (UDVC) #
Terminal Services (or Remote Desktop Services) are offering many hidden features for those who want to dig deeper. One of these services is the Dynamic Virtual Channel that enables us to communicate over an open RDP connection without the need to open a new socket, connection or a port on a firewall. These channels can be used to hide data from active network devices, to bypass firewalls, to implement device drivers over networks or just to help penetration testers to transfer data. The possibilities  are endless.

The real reason why this project was created is [XFLTReaT](https://github.com/earthquake/XFLTReaT). This could be used to build up a "VPN" over segregated networks and finally it enables testing over jumpboxes without requesting firewall changes. In a nutshell it makes penetration testers' life easier.

### How does this work? ###
You need to install a plugin (*.dll*) on your client computer that you use to connect to the RDP server. On the RDP server you need to use the other half of the project the *.exe*, which creates the channel between the plugin and the server executable. 
If you want to know more details, please scroll down.

### Installation ###
**It is Windows only.** Dynamic Virtual Channels were introduced in **Window Server 2008 & Windows Vista SP1**. These **and** anything **newer** than these should be good to go.

You can grab the whole project and compile it by yourself or just use the compiled binaries from the [Releases section](https://github.com/earthquake/UniversalDVC/releases). It is important that the correct binary is used in all cases, please select the correct one for the corresponding architecture (if your client is 32bit but the server is 64bit then grab the 32bit dll and 64bit exe).
The *.dll* needs to be placed on the client computer in any directory (for long-term use, you can put it into the %SYSROOT%\\system32\\ or %SYSROOT%\\SysWoW64\\) and install it with the following command as an elevated user (a.k.a Administrator): 
`regsvr32.exe UDVC-Plugin.dll`

If your user is not an administrator, you need to import the registry settings under your user too. Please use the *UDVC-Plugin.reg* file for that.

If you wish to remove it: 
`regsvr32.exe /u UDVC-Plugin.dll`


**Every time you connect to an RDP server from now on, this plugin will be loaded and will configure itself as it was specified in the registry (see below).**


The *.exe* needs to be put on the RDP server and run as any user.

### Modes supported ###
Both sides support three modes at the moment: 
#### Socket server mode (0 - default)
When this mode is enabled, then a listener will be set up on the defined port and interface (IP address).
#### Socket client mode (1)
In this mode a connection will be made towards a listener on the defined IP address and port.
#### Named Pipe mode (2)
This mode sets up a Named Pipe with the specified name. As an example: this mode can be used for other tools to do IPC communication over RDP. Unfortunately, Named Pipes are written to the disk so it is considered slow compared to the socket modes. **If you care about the bandwith, please use the socket modes.**

### Options/Configuration ###
Both the client and the server binary act the same way and it can be configured with the same options.
* **enabled**: *0* disabled, *1* enabled (plugin only). By default it is enabled and will tell you in a messagebox every time you initiate a connection.
* **mode**: *0* for listen(), *1* for connect() and *2* for creating a Named Pipe
* **ip**: which IP to connect to or bind to
* **port**: which port to connect to or bind to
* **namedpipename**: name of the named pipe
* **priority** (server binary only) *LOW, MEDIUM, HIGH, REAL* priorities for data transmission. *REAL* priority could severely affect the accessibility of the session in case of an intense data transfer, since the protocol prioritizes data over the control. 

The server binary will read the options from the command line.
```
PS C:\Users\UDVC\> .\UDVC-Server.exe -h
Universal Dynamic Virtual Channel server application

Usage: C:\Users\UDVC\UDVC-Server.exe [-s | -c [-p port [-h ip]] | -m [-n name]] [-0 | -1 | -2 | -3]
Socket server mode -s (default) OR
Socket client mode -c:
        -p port   port to bind the listener (default: 31337)
        -i ip     ip to bind the listener (default: 127.0.0.1)

Named pipe mode -m:
        -n name   name of the named pipe (by default: "\\.\pipe\UDVC_{RDP SESSION NUMBER}")

Data transfer priority parameters:
        -0        real time             (WTS_CHANNEL_OPTION_DYNAMIC_PRI_REAL)
        -1        high priority         (WTS_CHANNEL_OPTION_DYNAMIC_PRI_HIGH) - default
        -2        medium priority       (WTS_CHANNEL_OPTION_DYNAMIC_PRI_MED)
        -3        low priority          (WTS_CHANNEL_OPTION_DYNAMIC_PRI_LOW)
```

The client *.dll*  reads all the options from the registry, the values can be found under the following key:
`HKEY_CURRENT_USER\SOFTWARE\Microsoft\Terminal Server Client\Default\AddIns\UDVC-Plugin`
  
Every time the module is enabled and before the connection is made a reminder warning is showed. Just like this:
![warning](https://github.com/earthquake/UniversalDVC/blob/master/wiki/warning.png?raw=true)

This warning ensures that the user knows about the plugin is loaded and with what settings.

### Usage
The listeners, connections or named pipes are only created when the server executable was able to connect to the plugin dll. It depends on your configuration, but by default when the Virtual Channel connection was made (the plugin was loaded properly, the server binary was executed) it listens on the localhost:31337 on both endpoints. When you connect to these ports and send data through the socket, it will show up on the other side.

### Example use cases
Just to show a few uses cases where this tool can be used.

Very basic port forwarding. The Segregated 1 machine has a HTTP service on tcp/80. That network is not routed from the 192.168.0.0/24 network, the dual homed jump box must be used to access. Listen mode is configured on the client side on 0.0.0.0:31337 and the server binary was executed with the connect mode settings to create a connection to the web server. The user on the RDP client can use its browser to open http://127.0.0.1:31337 to access the content from http://10.13.37.2:80.
![scenario1](https://github.com/earthquake/UniversalDVC/blob/master/wiki/scenario1.png?raw=true)

A bit more advanced scenario to transfer files. Both endpoints are configured to listen on 0.0.0.0:31337. First the Hacking box connects to the RDP client and waits for the input. Then the Segregated 2 machine connects to the Jump box and reads the whole file into the socket.
![scenario2](https://github.com/earthquake/UniversalDVC/blob/master/wiki/scenario2.png?raw=true)

As an extra, Named Pipes can be used as well. In this case both the RDP client and Jump box create a Named Pipe on both sides (hIPC-client and hIPC-server) and the other machines can connect to these pipes. Whatever is written on the pipes it will show up on the other end. It is not really different from the listen mode example above, except it is using Named Pipes instead of TCP sockets.
![scenario3](https://github.com/earthquake/UniversalDVC/blob/master/wiki/scenario3.png?raw=true)

### Issues
In case the plugin does not load or the executable does not run because it is missing some DLLs for example the VCRUNTIME140.DLL, you might want to install the [Visual C++ Redistributable for Visual Studio 2015](https://www.microsoft.com/en-us/download/details.aspx?id=48145) package.



================================================
FILE: UDVC-Plugin/Resource.h
================================================
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by UDVC-Plugin.rc
//

#define IDS_PROJNAME                    100
#define IDR_UDVCPLUGIN					101
#define IDR_UDVCCLIENTPLUGIN            102

// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        201
#define _APS_NEXT_COMMAND_VALUE         32768
#define _APS_NEXT_CONTROL_VALUE         201
#define _APS_NEXT_SYMED_VALUE           106
#endif
#endif


================================================
FILE: UDVC-Plugin/UDVC-Plugin.cpp
================================================
/*
* MIT License
*
* Copyright(c) 2018-2020 Balazs Bucsay
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files(the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

#include "stdafx.h"
#include "resource.h"
#include "UDVC-Plugin.h"

#pragma comment(lib, "Ws2_32.lib")

#define UDVC_CHANNEL_NAME "UniversalDVC"

struct arguments {
	DWORD enabled;
	DWORD mode; // 0 sock listen(); 1 sock connect(); 2 namedpipe
	WCHAR *namedpipename;
	WCHAR *ip;
	WCHAR *port;
};

struct threadhandles {
	SOCKET sock = NULL;
	SOCKET sockserver = NULL;
	HANDLE pipe = NULL;
};

struct threadargs {
	struct arguments *running_args;
	struct threadhandles *threadhandle;
	IWTSVirtualChannel *m_ptrChannel = NULL;
	HANDLE hThread = NULL;
};

WSADATA		wsaData;

using namespace ATL;

#define CHECK_QUIT_HR( _x_ )    if(FAILED(hr)) { return hr; }

class ATL_NO_VTABLE UDVCPlugin :
	public CComObjectRootEx<CComMultiThreadModel>,
	public CComCoClass<UDVCPlugin, &CLSID_CompReg>,
	public IWTSPlugin,
	public IWTSVirtualChannelCallback,
	public IWTSListenerCallback
{
public:
	CComPtr<IWTSVirtualChannel> m_ptrChannel;

	DECLARE_REGISTRY_RESOURCEID(IDR_UDVCPLUGIN)

	BEGIN_COM_MAP(UDVCPlugin)
		COM_INTERFACE_ENTRY(IWTSPlugin)
		COM_INTERFACE_ENTRY(IWTSVirtualChannelCallback)
		COM_INTERFACE_ENTRY(IWTSListenerCallback)
	END_COM_MAP()

	DECLARE_PROTECT_FINAL_CONSTRUCT()


	HRESULT FinalConstruct()
	{
		return S_OK;
	}

	void FinalRelease()
	{
	}

	// IWTSPlugin.
	//
	HRESULT STDMETHODCALLTYPE
		Initialize(IWTSVirtualChannelManager *pChannelMgr);

	HRESULT STDMETHODCALLTYPE Connected();

	HRESULT STDMETHODCALLTYPE Disconnected(DWORD dwDisconnectCode)
	{
		// Prevent C4100 "unreferenced parameter" warnings.
		WSACleanup();
		dwDisconnectCode;
		return S_OK;
	}

	HRESULT STDMETHODCALLTYPE Terminated()
	{
		return S_OK;
	}

	VOID SetChannel(IWTSVirtualChannel *pChannel, struct threadargs *pTa);

	// IWTSVirtualChannelCallback
	//
	HRESULT STDMETHODCALLTYPE OnDataReceived(ULONG cbSize, __in_bcount(cbSize) BYTE *pBuffer);
	
	HRESULT STDMETHODCALLTYPE OnClose()
	{
		DebugPrint(0, L"[*] Terminating thread, closing socket and channel");
		if (pta->threadhandle->sockserver)
			closesocket(pta->threadhandle->sockserver);
		TerminateThread(pta->hThread, 0);
		return S_OK;// m_ptrChannel->Close();
	}

	HRESULT STDMETHODCALLTYPE
		OnNewChannelConnection(
			__in IWTSVirtualChannel *pChannel,
			__in_opt BSTR data,
			__out BOOL *pbAccept,
			__out IWTSVirtualChannelCallback **ppCallback);

	// non-inherited ones

	struct threadargs ta, *pta;
	struct arguments running_args;
	struct threadhandles threadhandle;

	static VOID UDVCPlugin::DebugPrint(HRESULT hrDbg, __in_z LPWSTR fmt, ...);
	LONG UDVCPlugin::GetDWORDRegKey(HKEY hKey, WCHAR *strValueName, DWORD *nValue);
	LONG UDVCPlugin::GetStringRegKey(HKEY hKey, WCHAR *strValueName, WCHAR **strValue);
	BOOL UDVCPlugin::GetRegistrySettings();
	static DWORD WINAPI UDVCPlugin::ListenerThread(PVOID param);
	static DWORD WINAPI UDVCPlugin::RsWcThread(PVOID param);

};

OBJECT_ENTRY_AUTO(__uuidof(CompReg), UDVCPlugin)


VOID UDVCPlugin::DebugPrint(HRESULT hrDbg, __in_z LPWSTR fmt, ...)
{
	HRESULT	hr;
	TCHAR	Buffer[DEBUG_PRINT_BUFFER_SIZE];
	size_t	Len;

	hr = StringCchPrintf(Buffer, DEBUG_PRINT_BUFFER_SIZE, TEXT("[hr=0x%8x]"), hrDbg);
	assert(SUCCEEDED(hr)); // buffer is sure to be big enough

	hr = StringCchLength(Buffer, DEBUG_PRINT_BUFFER_SIZE, &Len);
	assert(SUCCEEDED(hr)); // StringCchPrintf is supposed to always NULL term

	va_list argptr;
	va_start(argptr, fmt);

	hr = StringCchVPrintf(Buffer + Len, DEBUG_PRINT_BUFFER_SIZE - Len,
		fmt, argptr);

	// the above could fail but we don't care since we
	// should get a NULL terminated partial string

	// insert terminating eol (despite failure)
	hr = StringCchLength(Buffer, DEBUG_PRINT_BUFFER_SIZE, &Len);
	assert(SUCCEEDED(hr)); // again there should be a NULL term

	if (Len < DEBUG_PRINT_BUFFER_SIZE - 1)
	{
		Len++;
		Buffer[Len] = TEXT('\0');
	}

	Buffer[Len - 1] = TEXT('\n');
	OutputDebugString(Buffer);
}

LONG UDVCPlugin::GetDWORDRegKey(HKEY hKey, WCHAR *strValueName, DWORD *nValue)
{
	DWORD dwBufferSize(sizeof(DWORD));
	DWORD nResult;
	LONG nError;

	if ((nError = RegQueryValueEx(hKey, strValueName, 0, NULL, (LPBYTE)&nResult, &dwBufferSize)) == ERROR_SUCCESS)
	{
		*nValue = nResult;
	}
	return nError;
}

LONG UDVCPlugin::GetStringRegKey(HKEY hKey, WCHAR *strValueName, WCHAR **strValue)
{
	LPVOID szTemp = NULL;
	DWORD buflen = 255;
	LONG nError;

	if ((szTemp = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (size_t)buflen)) == NULL)
	{
		DebugPrint(GetLastError(), L"[-] Error allocating heap for read buffer %ld", GetLastError());
		return -1;
	}

	if ((nError = RegQueryValueExW(hKey, strValueName, 0, NULL, (LPBYTE)szTemp, &buflen)) != ERROR_SUCCESS)
	{
		HeapFree(GetProcessHeap(), HEAP_NO_SERIALIZE, szTemp);
		szTemp = NULL;
	}
	*strValue = (WCHAR *)szTemp;

	return nError;
}

BOOL UDVCPlugin::GetRegistrySettings()
{
	HKEY hKey;
	LONG lRes;
	WCHAR *szTemp;

	if ((lRes = RegOpenKeyEx(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Terminal Server Client\\Default\\AddIns\\UDVC-Plugin\\", 0, KEY_READ, &hKey)) != ERROR_SUCCESS)
	{
		DebugPrint(lRes, L"[-] Error opening registry hive/key");
		return FALSE;
	}

	GetDWORDRegKey(hKey, L"enabled", &running_args.enabled);
	GetDWORDRegKey(hKey, L"mode", &(running_args.mode));
	if ((running_args.mode == 0) || (running_args.mode == 1))
	{
		GetStringRegKey(hKey, L"ip", &szTemp);
		if (szTemp != NULL)
		{
			if (wcslen(szTemp) < 16)
			{
				running_args.ip = szTemp;
			}
			else
			{
				MessageBox(NULL, L"IP too long. Please fix it under the following key:\r\nHKCU\\SOFTWARE\\Microsoft\\Terminal Server Client\\Default\\AddIns\\UDVC-Plugin\\", L"Registry value error", MB_OK);
			}
		}
		GetStringRegKey(hKey, L"port", &szTemp);
		if (szTemp != NULL)
		{
			if (wcslen(szTemp) < 6)
			{
				running_args.port = szTemp;
			}
			else
			{
				MessageBox(NULL, L"Port too long. Please fix it under the following key:\r\nHKCU\\SOFTWARE\\Microsoft\\Terminal Server Client\\Default\\AddIns\\UDVC-Plugin\\", L"Registry value error", MB_OK);
			}
		}
	}
	if (running_args.mode == 2)
	{
		GetStringRegKey(hKey, L"namedpipename", &szTemp);
		if (szTemp != NULL)
		{
			if (wcsncmp(szTemp, L"\\\\.\\pipe\\", 9))
			{
				MessageBox(NULL, L"Named pipe name has to start with: \\\\.\\pipe\\\r\nPlease fix it under the following key:\r\nHKCU\\SOFTWARE\\Microsoft\\Terminal Server Client\\Default\\AddIns\\UDVC-Plugin\\", L"Registry value error", MB_OK);
			}
			else
			{
				running_args.namedpipename = szTemp;
			}
		}
	}
	
	return TRUE;
}


// IWTSPlugin::Initialize implementation.
HRESULT UDVCPlugin::Initialize(__in IWTSVirtualChannelManager *pChannelMgr)
{
	HRESULT	hr;
	CComObject<UDVCPlugin> *pListenerCallback;
	CComPtr<UDVCPlugin> ptrListenerCallback;
	CComPtr<IWTSListener> ptrListener;
	WCHAR	enabledmsg[256];
	int		ret;

	running_args.enabled = 0;
	running_args.mode = 0;
	running_args.port = L"31337";
	running_args.namedpipename = L"\\\\.\\pipe\\UDVC_default";
	running_args.ip = L"127.0.0.1";

	if (!GetRegistrySettings())
	{
		DebugPrint(-1, L"[-] Could not access the registry settings");
	}

	if (!running_args.enabled)
	{
		DebugPrint(0, L"[*] Plugin disabled");
		return -1;
	}

	if ((ret = WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0)
	{
		DebugPrint(ret, L"WSAStartup() failed with error: %ld", ret);
		return -1;
	}

	if (running_args.mode == 0)
		wnsprintf(enabledmsg, 255, L"The UDVC plugin is enabled. When the server binary gets executed, it will listen on: %s:%s", running_args.ip, running_args.port);
	if (running_args.mode == 1)
		wnsprintf(enabledmsg, 255, L"The UDVC plugin is enabled. When the server binary gets executed, it will connect to: %s:%s", running_args.ip, running_args.port);
	if (running_args.mode == 2)
		wnsprintf(enabledmsg, 255, L"The UDVC plugin is enabled. When the server binary gets executed, it will listen on: %s", running_args.namedpipename);

	MessageBox(NULL, enabledmsg, L"UDVC plugin is enabled", MB_OK | MB_ICONWARNING);


	// Create an instance of the CSampleListenerCallback object.
	hr = CComObject<UDVCPlugin>::CreateInstance(&pListenerCallback);
	CHECK_QUIT_HR("CSampleListenerCallback::CreateInstance");
	ptrListenerCallback = pListenerCallback;

	// Attach the callback to the endpoint.
	hr = pChannelMgr->CreateListener(
		UDVC_CHANNEL_NAME,
		0,
		(UDVCPlugin*)ptrListenerCallback,
		&ptrListener);
	CHECK_QUIT_HR("CreateListener");

	return hr;
}

HRESULT STDMETHODCALLTYPE UDVCPlugin::Connected()
{
	return S_OK;
}

DWORD UDVCPlugin::ListenerThread(PVOID param)
{
	struct threadargs *threadarg = (struct threadargs *)param;
	ADDRINFOW	*result = NULL;
	ADDRINFOW	hints;
	SOCKET		s, c;
	HANDLE		hNamedPipe = NULL;
	int			ret;
	u_long		blocking = 0;

	if (threadarg->running_args->mode == 0)
	{
		DebugPrint(0, L"[*] Setting up server socket");

		ZeroMemory(&hints, sizeof(hints));
		hints.ai_family = AF_INET;
		hints.ai_socktype = SOCK_STREAM;
		hints.ai_protocol = IPPROTO_TCP;
		hints.ai_flags = AI_PASSIVE;

		if ((ret = GetAddrInfoW(threadarg->running_args->ip, threadarg->running_args->port, &hints, &result)) != 0) {
			DebugPrint(ret, L"[-] GetAddrInfoW() failed with error: %ld", ret);
			return -1;
		}

		if ((s = socket(result->ai_family, result->ai_socktype, result->ai_protocol)) == INVALID_SOCKET) {
			DebugPrint(WSAGetLastError(), L"[-] socket() failed with error: %ld", WSAGetLastError());
			FreeAddrInfoW(result);
			return -1;
		}
		threadarg->threadhandle->sockserver = s;

		if ((ret = bind(s, result->ai_addr, (int)result->ai_addrlen)) == SOCKET_ERROR) {
			DebugPrint(WSAGetLastError(), L"[-] bind() failed with error: %ld", WSAGetLastError());
			FreeAddrInfoW(result);
			closesocket(s);
			return -1;
		}

		FreeAddrInfoW(result);
		DebugPrint(0, L"[*] Listening on: %s:%s", threadarg->running_args->ip, threadarg->running_args->port);

		if ((ret = listen(s, SOMAXCONN)) == SOCKET_ERROR) {
			DebugPrint(WSAGetLastError(), L"[-] listen() failed with error: %ld", WSAGetLastError());
			closesocket(s);
			return -1;
		}

		if ((c = accept(s, NULL, NULL)) == INVALID_SOCKET) {
			DebugPrint(WSAGetLastError(), L"[-] accept() failed with error: %ld", WSAGetLastError());
			closesocket(s);
			return -1;
		}
		DebugPrint(0, L"[+] Client connected");

		closesocket(s);
		threadarg->threadhandle->sockserver = NULL;

		ret = ioctlsocket(c, FIONBIO, &blocking);
		if (ret != NO_ERROR)
		{
			DebugPrint(ret, L"[-] ioctlsocket() failed with error: %ld", ret);
			closesocket(c);
			return -1;
		}
		threadarg->threadhandle->sock = c;
	}
	if (threadarg->running_args->mode == 1)
	{
		DebugPrint(0, L"[*] Setting up client socket");

		ZeroMemory(&hints, sizeof(hints));
		hints.ai_family = AF_INET;
		hints.ai_socktype = SOCK_STREAM;
		hints.ai_protocol = IPPROTO_TCP;
		hints.ai_flags = AI_PASSIVE;

		if ((ret = GetAddrInfoW(threadarg->running_args->ip, threadarg->running_args->port, &hints, &result)) != 0) {
			DebugPrint(ret, L"[-] GetAddrInfoW() failed with error: %ld", ret);
			return -1;
		}

		if ((c = socket(result->ai_family, result->ai_socktype, result->ai_protocol)) == INVALID_SOCKET) {
			DebugPrint(WSAGetLastError(), L"[-] socket() failed with error: %ld", WSAGetLastError());
			FreeAddrInfoW(result);
			return -1;
		}

		if ((ret = connect(c, result->ai_addr, (int)result->ai_addrlen)) == SOCKET_ERROR) {
			DebugPrint(WSAGetLastError(), L"[-] connect() failed with error: %ld", WSAGetLastError());
			FreeAddrInfoW(result);
			closesocket(c);
			return -1;
		}
		FreeAddrInfoW(result);
		DebugPrint(0, L"[*] Connected to: %s:%s", threadarg->running_args->ip, threadarg->running_args->port);

		ret = ioctlsocket(c, FIONBIO, &blocking);
		if (ret != NO_ERROR)
		{
			DebugPrint(ret, L"[-] ioctlsocket() failed with error: %ld", ret);
			closesocket(c);
			return -1;
		}
		threadarg->threadhandle->sock = c;
	}
	if (threadarg->running_args->mode == 2)
	{
		DebugPrint(0, L"[*] Setting up named pipe");

		if ((hNamedPipe = CreateNamedPipe(threadarg->running_args->namedpipename,
			PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
			PIPE_TYPE_BYTE | PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS, 1, 4096, 4096,
			NMPWAIT_USE_DEFAULT_WAIT, NULL)) == INVALID_HANDLE_VALUE)
		{
			DebugPrint(GetLastError(), L"[-] CreateNamedPipe() failed with: %ld", GetLastError());
			return -1;
		}

		DebugPrint(0, L"[*] Listening on pipe: %s\n", threadarg->running_args->namedpipename);
		if (!ConnectNamedPipe(hNamedPipe, NULL))
		{
			DebugPrint(GetLastError(), L"[-] ConnectNamedPipe() failed with: %ld", GetLastError());
			return -1;
		}

		threadarg->threadhandle->pipe = hNamedPipe;
		DebugPrint(0, L"[+] Client connected to the pipe.");
	}

	return RsWcThread(param);
}

DWORD WINAPI UDVCPlugin::RsWcThread(PVOID param)
{
	struct threadargs *threadarg = (struct threadargs *)param;
	DWORD	dw;
	BOOL    bSucc;
	HANDLE  hEvent_pipe;
	BYTE	*readBuf;
	DWORD	heapsize = 4096;

	if ((readBuf = (BYTE *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, heapsize)) == NULL)
	{
		DebugPrint(GetLastError(), L"[-] Error allocating heap for read buffer %ld", GetLastError());
		return -1;
	}

	hEvent_pipe = CreateEvent(NULL, FALSE, FALSE, NULL);
	OVERLAPPED Overlapped_pipe = { 0 };
	Overlapped_pipe.hEvent = hEvent_pipe;

	while (TRUE)
	{
		if (threadarg->threadhandle->sock)
		{
			if ((dw = recv(threadarg->threadhandle->sock, (char *)readBuf, heapsize, 0)) == INVALID_SOCKET)
			{
				DebugPrint(WSAGetLastError(), L"[-] [RsWc] recv() failed with error %d, exiting thread...\n", WSAGetLastError());
				return -1;
			}
			if (dw == 0)
			{
				DebugPrint(WSAGetLastError(), L"[-] [RsWc] socket closed, exiting thread...\n", WSAGetLastError());
				return -1;
			}
		}
		if (threadarg->threadhandle->pipe)
		{
			bSucc = ReadFile(threadarg->threadhandle->pipe, readBuf, heapsize, &dw, &Overlapped_pipe);
			if (!bSucc)
			{
				if (GetLastError() == ERROR_IO_PENDING)
				{
					dw = WaitForSingleObject(Overlapped_pipe.hEvent, INFINITE);
					bSucc = GetOverlappedResult(threadarg->threadhandle->pipe, &Overlapped_pipe, &dw, FALSE);
				}
			}
			if (!bSucc)
			{
				DebugPrint(GetLastError(), L"[-] [RsWc] ReadFile()/WaitForSingleObject() error: %ld\n", GetLastError());
				return -1;
			}

			if (ResetEvent(Overlapped_pipe.hEvent) == FALSE)
			{
				DebugPrint(GetLastError(), L"[-] [RsWc] ResetEvent() failed with error = %d\n", GetLastError());
				return -1;
			}
		}

		if (threadarg->m_ptrChannel != NULL)
			threadarg->m_ptrChannel->Write(dw, readBuf, NULL);
		else
			return -1;
	}

	return 0;
}

// IWTSListenerCallback::OnNewChannelConnection implementation.
HRESULT UDVCPlugin::OnNewChannelConnection(__in IWTSVirtualChannel *pChannel,
	__in_opt BSTR data, __out BOOL *pbAccept, __out IWTSVirtualChannelCallback **ppCallback)
{
	HRESULT		hr;
	DWORD		dwThreadId;
	CComObject<UDVCPlugin> *pCallback;
	CComPtr<UDVCPlugin> ptrCallback;

	// Prevent C4100 "unreferenced parameter" warnings.
	data;

	*pbAccept = FALSE;

	hr = CComObject<UDVCPlugin>::CreateInstance(&pCallback);
	CHECK_QUIT_HR("UDVCPlugin::CreateInstance");
	ptrCallback = pCallback;

	ptrCallback->SetChannel(pChannel, &ta);

	ta.running_args = &running_args;
	ta.threadhandle = &threadhandle;
	ta.m_ptrChannel = pChannel;

	running_args.enabled = 0;
	running_args.mode = 0;
	running_args.port = L"31337";
	running_args.namedpipename = L"\\\\.\\pipe\\UDVC_default";
	running_args.ip = L"127.0.0.1";

	if (!GetRegistrySettings())
	{
		DebugPrint(-1, L"[-] Could not access the registry settings");
	}

	HANDLE hListenerThread = CreateThread(
		NULL,
		0,
		&UDVCPlugin::ListenerThread,
		&ta,
		0,
		&dwThreadId);

	ta.hThread = hListenerThread;

	*ppCallback = ptrCallback;
	(*ppCallback)->AddRef();

	*pbAccept = TRUE;

	return hr;
}

VOID UDVCPlugin::SetChannel(IWTSVirtualChannel *pChannel, struct threadargs *pTa)
{
	m_ptrChannel = pChannel;
	pta	= pTa;
}

HRESULT STDMETHODCALLTYPE UDVCPlugin::OnDataReceived(ULONG cbSize, __in_bcount(cbSize) BYTE *pBuffer)
{
	DWORD       ret, dw;
	HANDLE      hEvent;
	BOOL        bSucc;

	hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
	OVERLAPPED  Overlapped = { 0 };
	Overlapped.hEvent = hEvent;

	if (pta->threadhandle->sock)
	{
		if ((ret = send(pta->threadhandle->sock, (char *)pBuffer, cbSize, 0)) == SOCKET_ERROR)
		{
			DebugPrint(WSAGetLastError(), L"[-] [RsWc] send() failed with error %ld", WSAGetLastError());
			m_ptrChannel->Close();
			return -1;
		}
	}
	if (pta->threadhandle->pipe)
	{
		bSucc = WriteFile(pta->threadhandle->pipe, pBuffer, cbSize, &ret, &Overlapped);
		if (!bSucc)
		{
			if (GetLastError() == ERROR_IO_PENDING)
			{
				dw = WaitForSingleObject(Overlapped.hEvent, INFINITE);
				bSucc = GetOverlappedResult(pta->threadhandle->pipe, &Overlapped, &ret, FALSE);
			}
		}
		if (!bSucc)
		{
			DebugPrint(GetLastError(), L"[-] [RsWc] WriteFile()/WaitForSingleObject() error: %ld", GetLastError());
			m_ptrChannel->Close();
			return -1;
		}
	}

	return ret;
}

================================================
FILE: UDVC-Plugin/UDVC-Plugin.def
================================================
; UDVC-Plugin.def : Declares the module parameters.

LIBRARY

EXPORTS
	DllCanUnloadNow		PRIVATE
	DllGetClassObject	PRIVATE
	DllRegisterServer	PRIVATE
	DllUnregisterServer	PRIVATE
	DllInstall		PRIVATE


================================================
FILE: UDVC-Plugin/UDVC-Plugin.h
================================================
// TsClientPlgn.h : Declaration of the CTsClientPlgn

#pragma once
#include "stdafx.h"
#include "resource.h"       // main symbols

#include "UDVCPlugin_i.h"

// debug
#include <StrSafe.h>
#include <assert.h>


#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
#endif


// CTsClientPlgn
class ATL_NO_VTABLE CTsClientPlgn :
	public CComObjectRootEx<CComSingleThreadModel>,
	public CComCoClass<CTsClientPlgn, &CLSID_CompReg>,
	public IDispatchImpl<IComponentRegistrar, &IID_IComponentRegistrar, &LIBID_UDVCPluginLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
    public IWTSPlugin,
    public IWTSListenerCallback,
    public IWTSVirtualChannelCallback
{
public:
    CTsClientPlgn(): _hCurrentFile(INVALID_HANDLE_VALUE)
	{
	}

DECLARE_REGISTRY_RESOURCEID(IDR_UDVCCLIENTPLUGIN)


BEGIN_COM_MAP(CTsClientPlgn)
	COM_INTERFACE_ENTRY(IComponentRegistrar)
	COM_INTERFACE_ENTRY(IDispatch)
	COM_INTERFACE_ENTRY(IWTSPlugin)
	COM_INTERFACE_ENTRY(IWTSListenerCallback)
	COM_INTERFACE_ENTRY(IWTSVirtualChannelCallback)
END_COM_MAP()

	DECLARE_PROTECT_FINAL_CONSTRUCT()

	HRESULT FinalConstruct()
	{
		return S_OK;
	}

	void FinalRelease()
	{
	}

    // IWTSPlugin
public:
    /*
     *  Called immediately after instantiating the COM class
     */
    STDMETHOD(Initialize)(
        IWTSVirtualChannelManager *pChannelMgr
        );

    /*
     *  Called when the TS client is connected to the TS server
     */
    STDMETHOD(Connected)();

    /*
     *  Called when the TS client is disconnected to the TS server
     *  Might be followed by another Connected() call
     */
    STDMETHOD(Disconnected)(
        DWORD dwDisconnectCode
        );

    /*
     *  The last method called by the TS client before 
     *  terminating the object
     */
    STDMETHOD(Terminated)();

    // IWTSListenerCallback
public:
	VOID CTsClientPlgn::SetChannel(IWTSVirtualChannel *pChannel);
public:
    /*
     *  Called whenever a request for new channel connection
     *  from the server is received.
     */
    STDMETHOD(OnNewChannelConnection)(
        IWTSVirtualChannel *pChannel,
        BSTR data,           // optional data passed as part of the connect method
        BOOL *pbAccept,      // the callee should return TRUE if connection is accepted
        IWTSVirtualChannelCallback **ppCallback // connection related events
        );
    
    // IWTSVirtualChannelCallback
public:

    /*
     *  Called whenever a full message from the server is received
     *  The message is fully reassembled and has the exact size
     *  as the Write() call on the server
     */
    STDMETHOD(OnDataReceived)(
        ULONG cbSize,            // size of data in bytes
        BYTE *pBuffer            // data buffer
        );

    /*
     *  The channel is disconnected, all Write() calls will fail
     *  no more incomming data is expected. 
     */
    STDMETHOD(OnClose)();

private:

    HRESULT CleanState();


    HRESULT StartFile(
        __in_z LPWSTR szFileName,
        BOOL bDir);

    HRESULT WriteData(
        __in_bcount(usLen) PBYTE pData,
        USHORT usLen);

    HRESULT EndFile(BOOL bDir);

    CComPtr<IWTSListener> _spListener;
    CComPtr<IWTSVirtualChannel> _spChannel;

    HANDLE _hCurrentFile;

    WStringVector _vDirList;
};

//OBJECT_ENTRY_AUTO(__uuidof(CompReg), CTsClientPlgn)


// DEBUG:
#define DEBUG_PRINT_BUFFER_SIZE 1024


================================================
FILE: UDVC-Plugin/UDVC-Plugin.rgs
================================================
HKCR
{
	CLSID
	{
		UDVC-Plugin.UDVC-Plugin.1 = s 'UDVC-Plugin Class'
		{
			CLSID = s '{3C8458A3-2EBE-4840-BB07-3BA5BF810588}'
		}
		UDVC-Plugin.UDVC-Plugin = s 'UDVC-Plugin Class'
		{
			CLSID = s '{3C8458A3-2EBE-4840-BB07-3BA5BF810588}'
			CurVer = s 'UDVC-Plugin.UDVC-Plugin.1'
		}
		ForceRemove {3C8458A3-2EBE-4840-BB07-3BA5BF810588} = s 'UDVC-Plugin Class'
		{
			ProgID = s 'UDVC-Plugin.UDVC-Plugin.1'
			VersionIndependentProgID = s 'UDVC-Plugin.UDVC-Plugin'
			ForceRemove 'Programmable'
			InprocServer32 = s '%MODULE%'
			{
				val ThreadingModel = s 'Free'
			}
			'TypeLib' = s '{392B9DEE-7E00-4C58-831B-50C58EAA887F}'
		}		
	}		
}

HKCU
{ 
	Software
	{
		Microsoft
		{
			'Terminal Server Client'
			{
				Default
				{
					AddIns
					{
						UDVC-Plugin
						{
							val Name = s '{3C8458A3-2EBE-4840-BB07-3BA5BF810588}'
							val namedpipename = s '\\.\pipe\UDVC_default'
							val ip = s '127.0.0.1'
							val port = s '31337'
							val mode = d '0'
							val enabled = d '1'
						}
					}
				}
			}
		}
	}
}


================================================
FILE: UDVC-Plugin/UDVC-Plugin.vcxproj
================================================
<?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>
    <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>{9402DF45-A060-4881-9F64-D16E094B97A7}</ProjectGuid>
    <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
    <Keyword>AtlProj</Keyword>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <UseDebugLibraries>true</UseDebugLibraries>
    <PlatformToolset>v140</PlatformToolset>
    <CharacterSet>Unicode</CharacterSet>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <UseDebugLibraries>false</UseDebugLibraries>
    <PlatformToolset>v140</PlatformToolset>
    <CharacterSet>Unicode</CharacterSet>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <UseDebugLibraries>true</UseDebugLibraries>
    <PlatformToolset>v140</PlatformToolset>
    <CharacterSet>Unicode</CharacterSet>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <UseDebugLibraries>false</UseDebugLibraries>
    <PlatformToolset>v140</PlatformToolset>
    <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'">
    <IgnoreImportLibrary>true</IgnoreImportLibrary>
    <LinkIncremental>true</LinkIncremental>
    <OutDir>$(SolutionDir)$(Configuration)\$(Platform)\</OutDir>
    <IntDir>$(Platform)\$(Configuration)\</IntDir>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <IgnoreImportLibrary>true</IgnoreImportLibrary>
    <LinkIncremental>true</LinkIncremental>
    <OutDir>$(SolutionDir)$(Configuration)\$(Platform)\</OutDir>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <IgnoreImportLibrary>true</IgnoreImportLibrary>
    <LinkIncremental>false</LinkIncremental>
    <OutDir>$(SolutionDir)$(Configuration)\$(Platform)\</OutDir>
    <IntDir>$(Platform)\$(Configuration)\</IntDir>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <IgnoreImportLibrary>true</IgnoreImportLibrary>
    <LinkIncremental>false</LinkIncremental>
    <OutDir>$(SolutionDir)$(Configuration)\$(Platform)\</OutDir>
  </PropertyGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <ClCompile>
      <PrecompiledHeader>Use</PrecompiledHeader>
      <WarningLevel>Level3</WarningLevel>
      <Optimization>Disabled</Optimization>
      <PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <SDLCheck>true</SDLCheck>
    </ClCompile>
    <Midl>
      <MkTypLibCompatible>false</MkTypLibCompatible>
      <TargetEnvironment>Win32</TargetEnvironment>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <HeaderFileName>UDVCPlugin_i.h</HeaderFileName>
      <InterfaceIdentifierFileName>UDVCPlugin_i.c</InterfaceIdentifierFileName>
      <ProxyFileName>UDVCPlugin_p.c</ProxyFileName>
      <GenerateStublessProxies>true</GenerateStublessProxies>
      <TypeLibraryName>$(IntDir)UDVCPlugin.tlb</TypeLibraryName>
      <DllDataFileName />
      <ValidateAllParameters>true</ValidateAllParameters>
    </Midl>
    <ResourceCompile>
      <Culture>0x0409</Culture>
      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </ResourceCompile>
    <Link>
      <SubSystem>Windows</SubSystem>
      <ModuleDefinitionFile>.\UDVC-Plugin.def</ModuleDefinitionFile>
      <AdditionalDependencies>comsvcs.lib;%(AdditionalDependencies)</AdditionalDependencies>
      <RegisterOutput>true</RegisterOutput>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <ClCompile>
      <PrecompiledHeader>Use</PrecompiledHeader>
      <WarningLevel>Level3</WarningLevel>
      <Optimization>Disabled</Optimization>
      <PreprocessorDefinitions>_WINDOWS;_DEBUG;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <SDLCheck>true</SDLCheck>
    </ClCompile>
    <Midl>
      <MkTypLibCompatible>false</MkTypLibCompatible>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <HeaderFileName>UDVCPlugin_i.h</HeaderFileName>
      <InterfaceIdentifierFileName>UDVCPlugin_i.c</InterfaceIdentifierFileName>
      <ProxyFileName>UDVCPlugin_p.c</ProxyFileName>
      <GenerateStublessProxies>true</GenerateStublessProxies>
      <TypeLibraryName>$(IntDir)UDVCPlugin.tlb</TypeLibraryName>
      <DllDataFileName />
      <ValidateAllParameters>true</ValidateAllParameters>
    </Midl>
    <ResourceCompile>
      <Culture>0x0409</Culture>
      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </ResourceCompile>
    <Link>
      <SubSystem>Windows</SubSystem>
      <ModuleDefinitionFile>.\UDVC-Plugin.def</ModuleDefinitionFile>
      <AdditionalDependencies>comsvcs.lib;%(AdditionalDependencies)</AdditionalDependencies>
      <RegisterOutput>true</RegisterOutput>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <ClCompile>
      <PrecompiledHeader>Use</PrecompiledHeader>
      <WarningLevel>Level3</WarningLevel>
      <Optimization>MaxSpeed</Optimization>
      <PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <SDLCheck>true</SDLCheck>
    </ClCompile>
    <Midl>
      <MkTypLibCompatible>false</MkTypLibCompatible>
      <TargetEnvironment>Win32</TargetEnvironment>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <HeaderFileName>UDVCPlugin_i.h</HeaderFileName>
      <InterfaceIdentifierFileName>UDVCPlugin_i.c</InterfaceIdentifierFileName>
      <ProxyFileName>UDVCPlugin_p.c</ProxyFileName>
      <GenerateStublessProxies>true</GenerateStublessProxies>
      <TypeLibraryName>$(IntDir)UDVCPlugin.tlb</TypeLibraryName>
      <DllDataFileName />
      <ValidateAllParameters>true</ValidateAllParameters>
    </Midl>
    <ResourceCompile>
      <Culture>0x0409</Culture>
      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </ResourceCompile>
    <Link>
      <SubSystem>Windows</SubSystem>
      <ModuleDefinitionFile>.\UDVC-Plugin.def</ModuleDefinitionFile>
      <AdditionalDependencies>comsvcs.lib;%(AdditionalDependencies)</AdditionalDependencies>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <OptimizeReferences>true</OptimizeReferences>
      <RegisterOutput>true</RegisterOutput>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <ClCompile>
      <PrecompiledHeader>Use</PrecompiledHeader>
      <WarningLevel>Level3</WarningLevel>
      <Optimization>MaxSpeed</Optimization>
      <PreprocessorDefinitions>_WINDOWS;NDEBUG;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <SDLCheck>true</SDLCheck>
    </ClCompile>
    <Midl>
      <MkTypLibCompatible>false</MkTypLibCompatible>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <HeaderFileName>UDVCPlugin_i.h</HeaderFileName>
      <InterfaceIdentifierFileName>UDVCPlugin_i.c</InterfaceIdentifierFileName>
      <ProxyFileName>UDVCPlugin_p.c</ProxyFileName>
      <GenerateStublessProxies>true</GenerateStublessProxies>
      <TypeLibraryName>$(IntDir)UDVCPlugin.tlb</TypeLibraryName>
      <DllDataFileName />
      <ValidateAllParameters>true</ValidateAllParameters>
    </Midl>
    <ResourceCompile>
      <Culture>0x0409</Culture>
      <AdditionalIncludeDirectories>$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </ResourceCompile>
    <Link>
      <SubSystem>Windows</SubSystem>
      <ModuleDefinitionFile>.\UDVC-Plugin.def</ModuleDefinitionFile>
      <AdditionalDependencies>comsvcs.lib;%(AdditionalDependencies)</AdditionalDependencies>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <OptimizeReferences>true</OptimizeReferences>
      <RegisterOutput>true</RegisterOutput>
    </Link>
  </ItemDefinitionGroup>
  <ItemGroup>
    <ClCompile Include="compreg.cpp" />
    <ClCompile Include="UDVC-Plugin.cpp" />
    <ClCompile Include="dllmain.cpp">
      <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
      </PrecompiledHeader>
      <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</CompileAsManaged>
      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
      </PrecompiledHeader>
      <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsManaged>
      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
      </PrecompiledHeader>
      <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</CompileAsManaged>
      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
      </PrecompiledHeader>
    </ClCompile>
    <ClCompile Include="stdafx.cpp">
      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
    </ClCompile>
    <ClCompile Include="dllfunc.cpp" />
    <ClCompile Include="UDVCPlugin_i.c">
      <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
      </PrecompiledHeader>
      <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</CompileAsManaged>
      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
      </PrecompiledHeader>
      <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsManaged>
      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
      </PrecompiledHeader>
      <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</CompileAsManaged>
      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
      </PrecompiledHeader>
    </ClCompile>
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="compreg.h" />
    <ClInclude Include="dllmain.h" />
    <ClInclude Include="Resource.h" />
    <ClInclude Include="stdafx.h" />
    <ClInclude Include="targetver.h" />
    <ClInclude Include="UDVC-Plugin.h" />
    <ClInclude Include="UDVCPlugin_i.h" />
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="UDVC-Plugin.rc" />
  </ItemGroup>
  <ItemGroup>
    <Text Include="ReadMe.txt" />
  </ItemGroup>
  <ItemGroup>
    <None Include="UDVC-Plugin.def" />
    <None Include="UDVC-Plugin.rgs" />
  </ItemGroup>
  <ItemGroup>
    <Midl Include="UDVCPlugin.idl" />
  </ItemGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
  <ImportGroup Label="ExtensionTargets">
  </ImportGroup>
</Project>

================================================
FILE: UDVC-Plugin/UDVC-Plugin.vcxproj.filters
================================================
<?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="Generated Files">
      <UniqueIdentifier>{2467f173-a17f-4363-a3f3-5f66776727f8}</UniqueIdentifier>
      <SourceControlFiles>False</SourceControlFiles>
    </Filter>
  </ItemGroup>
  <ItemGroup>
    <ClCompile Include="stdafx.cpp">
      <Filter>Source Files</Filter>
    </ClCompile>
    <ClCompile Include="dllmain.cpp">
      <Filter>Source Files</Filter>
    </ClCompile>
    <ClCompile Include="compreg.cpp">
      <Filter>Source Files</Filter>
    </ClCompile>
    <ClCompile Include="UDVCPlugin_i.c">
      <Filter>Generated Files</Filter>
    </ClCompile>
    <ClCompile Include="dllfunc.cpp">
      <Filter>Source Files</Filter>
    </ClCompile>
    <ClCompile Include="UDVC-Plugin.cpp">
      <Filter>Source Files</Filter>
    </ClCompile>
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="stdafx.h">
      <Filter>Header Files</Filter>
    </ClInclude>
    <ClInclude Include="targetver.h">
      <Filter>Header Files</Filter>
    </ClInclude>
    <ClInclude Include="dllmain.h">
      <Filter>Header Files</Filter>
    </ClInclude>
    <ClInclude Include="compreg.h">
      <Filter>Header Files</Filter>
    </ClInclude>
    <ClInclude Include="UDVCPlugin_i.h">
      <Filter>Generated Files</Filter>
    </ClInclude>
    <ClInclude Include="UDVC-Plugin.h">
      <Filter>Header Files</Filter>
    </ClInclude>
    <ClInclude Include="Resource.h">
      <Filter>Header Files</Filter>
    </ClInclude>
  </ItemGroup>
  <ItemGroup>
    <ResourceCompile Include="UDVC-Plugin.rc">
      <Filter>Resource Files</Filter>
    </ResourceCompile>
  </ItemGroup>
  <ItemGroup>
    <Text Include="ReadMe.txt" />
  </ItemGroup>
  <ItemGroup>
    <None Include="UDVC-Plugin.rgs">
      <Filter>Resource Files</Filter>
    </None>
    <None Include="UDVC-Plugin.def">
      <Filter>Source Files</Filter>
    </None>
  </ItemGroup>
  <ItemGroup>
    <Midl Include="UDVCPlugin.idl">
      <Filter>Source Files</Filter>
    </Midl>
  </ItemGroup>
</Project>

================================================
FILE: UDVC-Plugin/UDVC-PluginPS.vcxproj
================================================
<?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>
    <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>{15DEE2D8-6972-49C0-9369-35730A29A2CF}</ProjectGuid>
    <Keyword>AtlPSProj</Keyword>
    <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
  </PropertyGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <UseDebugLibraries>true</UseDebugLibraries>
    <PlatformToolset>v140</PlatformToolset>
    <CharacterSet>Unicode</CharacterSet>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <UseDebugLibraries>false</UseDebugLibraries>
    <PlatformToolset>v140</PlatformToolset>
    <CharacterSet>Unicode</CharacterSet>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <UseDebugLibraries>true</UseDebugLibraries>
    <PlatformToolset>v140</PlatformToolset>
    <CharacterSet>Unicode</CharacterSet>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
    <ConfigurationType>DynamicLibrary</ConfigurationType>
    <UseDebugLibraries>false</UseDebugLibraries>
    <PlatformToolset>v140</PlatformToolset>
    <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'">
    <IntDir>$(Platform)\$(Configuration)PS\</IntDir>
    <OutDir>$(SolutionDir)$(Configuration)\$(Platform)\</OutDir>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <IntDir>$(Platform)\$(Configuration)PS\</IntDir>
    <OutDir>$(SolutionDir)$(Configuration)\$(Platform)\</OutDir>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <IntDir>$(Platform)\$(Configuration)PS\</IntDir>
    <OutDir>$(SolutionDir)$(Configuration)\$(Platform)\</OutDir>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <IntDir>$(Platform)\$(Configuration)PS\</IntDir>
    <OutDir>$(SolutionDir)$(Configuration)\$(Platform)\</OutDir>
  </PropertyGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <ClCompile>
      <PreprocessorDefinitions>WIN32;REGISTER_PROXY_DLL;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </ClCompile>
    <Link>
      <AdditionalDependencies>kernel32.lib;rpcns4.lib;rpcrt4.lib;oleaut32.lib;uuid.lib;ole32.lib;advapi32.lib;comsvcs.lib;%(AdditionalDependencies)</AdditionalDependencies>
      <ModuleDefinitionFile>UDVC-PluginPS.def</ModuleDefinitionFile>
      <RegisterOutput>true</RegisterOutput>
    </Link>
    <PreBuildEvent>
      <Command>if exist dlldata.c goto :END
echo Error: MIDL will not generate DLLDATA.C unless you have at least 1 interface in the main project.
Exit 1
:END
</Command>
      <Message>Checking for required files</Message>
    </PreBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <ClCompile>
      <PreprocessorDefinitions>REGISTER_PROXY_DLL;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </ClCompile>
    <Link>
      <AdditionalDependencies>kernel32.lib;rpcns4.lib;rpcrt4.lib;oleaut32.lib;uuid.lib;ole32.lib;advapi32.lib;comsvcs.lib;%(AdditionalDependencies)</AdditionalDependencies>
      <ModuleDefinitionFile>UDVC-PluginPS.def</ModuleDefinitionFile>
      <RegisterOutput>true</RegisterOutput>
    </Link>
    <PreBuildEvent>
      <Command>if exist dlldata.c goto :END
echo Error: MIDL will not generate DLLDATA.C unless you have at least 1 interface in the main project.
Exit 1
:END
</Command>
      <Message>Checking for required files</Message>
    </PreBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <ClCompile>
      <Optimization>MaxSpeed</Optimization>
      <PreprocessorDefinitions>WIN32;REGISTER_PROXY_DLL;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </ClCompile>
    <Link>
      <AdditionalDependencies>kernel32.lib;rpcns4.lib;rpcrt4.lib;oleaut32.lib;uuid.lib;ole32.lib;advapi32.lib;comsvcs.lib;%(AdditionalDependencies)</AdditionalDependencies>
      <ModuleDefinitionFile>UDVC-PluginPS.def</ModuleDefinitionFile>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <OptimizeReferences>true</OptimizeReferences>
      <RegisterOutput>true</RegisterOutput>
    </Link>
    <PreBuildEvent>
      <Command>if exist dlldata.c goto :END
echo Error: MIDL will not generate DLLDATA.C unless you have at least 1 interface in the main project.
Exit 1
:END
</Command>
      <Message>Checking for required files</Message>
    </PreBuildEvent>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <ClCompile>
      <Optimization>MaxSpeed</Optimization>
      <PreprocessorDefinitions>REGISTER_PROXY_DLL;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </ClCompile>
    <Link>
      <AdditionalDependencies>kernel32.lib;rpcns4.lib;rpcrt4.lib;oleaut32.lib;uuid.lib;ole32.lib;advapi32.lib;comsvcs.lib;%(AdditionalDependencies)</AdditionalDependencies>
      <ModuleDefinitionFile>UDVC-PluginPS.def</ModuleDefinitionFile>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <OptimizeReferences>true</OptimizeReferences>
      <RegisterOutput>true</RegisterOutput>
    </Link>
    <PreBuildEvent>
      <Command>if exist dlldata.c goto :END
echo Error: MIDL will not generate DLLDATA.C unless you have at least 1 interface in the main project.
Exit 1
:END
</Command>
      <Message>Checking for required files</Message>
    </PreBuildEvent>
  </ItemDefinitionGroup>
  <ItemGroup>
    <None Include="UDVC-Pluginps.def" />
  </ItemGroup>
  <ItemGroup>
    <ClCompile Include="dlldata.c" />
    <ClCompile Include="UDVCPlugin_i.c" />
    <ClCompile Include="UDVCPlugin_p.c" />
  </ItemGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
  <ImportGroup Label="ExtensionTargets">
  </ImportGroup>
</Project>

================================================
FILE: UDVC-Plugin/UDVC-PluginPS.vcxproj.filters
================================================
<?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>{3ae88138-7c28-4919-a9b2-4b5e1473c72b}</UniqueIdentifier>
    </Filter>
    <Filter Include="Generated Files">
      <UniqueIdentifier>{d3ce00e0-04ef-4a7b-ad63-435441b697a5}</UniqueIdentifier>
      <SourceControlFiles>False</SourceControlFiles>
    </Filter>
  </ItemGroup>
  <ItemGroup>
    <None Include="UDVC-Pluginps.def" />
  </ItemGroup>
  <ItemGroup>
    <ClCompile Include="UDVCPlugin_i.c">
      <Filter>Generated Files</Filter>
    </ClCompile>
    <ClCompile Include="UDVCPlugin_p.c">
      <Filter>Generated Files</Filter>
    </ClCompile>
    <ClCompile Include="dlldata.c">
      <Filter>Generated Files</Filter>
    </ClCompile>
  </ItemGroup>
</Project>

================================================
FILE: UDVC-Plugin/UDVC-Pluginps.def
================================================

LIBRARY

EXPORTS
	DllGetClassObject		PRIVATE
	DllCanUnloadNow			PRIVATE
	DllRegisterServer		PRIVATE
	DllUnregisterServer		PRIVATE


================================================
FILE: UDVC-Plugin/UDVCPlugin.idl
================================================
// UDVCPlugin.idl : IDL source for UDVC-Plugin
//

// This file will be processed by the MIDL tool to
// produce the type library (UDVCPlugin.tlb) and marshalling code.

import "oaidl.idl";
import "ocidl.idl";

[
	object,
	uuid(a817e7a2-43fa-11d0-9e44-00aa00b6770a),
	dual,	
	pointer_default(unique)
]
interface IComponentRegistrar : IDispatch
{
	[id(1)]	HRESULT Attach([in] BSTR bstrPath);
	[id(2)]	HRESULT RegisterAll();
	[id(3)]	HRESULT UnregisterAll();
	[id(4)]	HRESULT GetComponents([out] SAFEARRAY(BSTR)* pbstrCLSIDs, [out] SAFEARRAY(BSTR)* pbstrDescriptions);
	[id(5)]	HRESULT RegisterComponent([in] BSTR bstrCLSID);
	[id(6)] HRESULT UnregisterComponent([in] BSTR bstrCLSID);
};

[
	uuid(392B9DEE-7E00-4C58-831B-50C58EAA887F),
	version(1.0),
	custom(a817e7a1-43fa-11d0-9e44-00aa00b6770a,"{3C8458A3-2EBE-4840-BB07-3BA5BF810588}")
]
library UDVCPluginLib
{
	importlib("stdole2.tlb");
	[
		uuid(3C8458A3-2EBE-4840-BB07-3BA5BF810588)		
	]
	coclass CompReg
	{
		[default] interface IComponentRegistrar;
	};
};



================================================
FILE: UDVC-Plugin/compreg.cpp
================================================
// compreg.cpp : Implementation of CCompReg

#include "stdafx.h"
#include "compreg.h"


// CCompReg


================================================
FILE: UDVC-Plugin/compreg.h
================================================
// compreg.h : Declaration of the CCompReg

#pragma once

#include "resource.h"       // main symbols
#include "UDVCPlugin_i.h"
 


================================================
FILE: UDVC-Plugin/dllfunc.cpp
================================================
/*
* MIT License
*
* Copyright(c) 2018 Balazs Bucsay
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files(the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

#include "stdafx.h"
#include "resource.h"
#include "UDVCPlugin_i.h"
#include "dllmain.h"
#include "compreg.h"


using namespace ATL;

// Used to determine whether the DLL can be unloaded by OLE.
STDAPI DllCanUnloadNow(void)
{
			return _AtlModule.DllCanUnloadNow();
	}

// Returns a class factory to create an object of the requested type.
_Check_return_
STDAPI DllGetClassObject(_In_ REFCLSID rclsid, _In_ REFIID riid, _Outptr_ LPVOID* ppv)
{
		return _AtlModule.DllGetClassObject(rclsid, riid, ppv);
}

// DllRegisterServer - Adds entries to the system registry.
STDAPI DllRegisterServer(void)
{
	// registers object, typelib and all interfaces in typelib
	HRESULT hr = _AtlModule.DllRegisterServer();
		return hr;
}

// DllUnregisterServer - Removes entries from the system registry.
STDAPI DllUnregisterServer(void)
{
	HRESULT hr = _AtlModule.DllUnregisterServer();
		return hr;
}

// DllInstall - Adds/Removes entries to the system registry per user per machine.
STDAPI DllInstall(BOOL bInstall, _In_opt_  LPCWSTR pszCmdLine)
{
	HRESULT hr = E_FAIL;
	static const wchar_t szUserSwitch[] = L"user";

	if (pszCmdLine != NULL)
	{
		if (_wcsnicmp(pszCmdLine, szUserSwitch, _countof(szUserSwitch)) == 0)
		{
			ATL::AtlSetPerUserRegistration(true);
		}
	}

	if (bInstall)
	{	
		hr = DllRegisterServer();
		if (FAILED(hr))
		{
			DllUnregisterServer();
		}
	}
	else
	{
		hr = DllUnregisterServer();
	}

	return hr;
}




================================================
FILE: UDVC-Plugin/dllmain.cpp
================================================
/*
* MIT License
*
* Copyright(c) 2018 Balazs Bucsay
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files(the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

#include "stdafx.h"
#include "resource.h"
#include "UDVCPlugin_i.h"
#include "dllmain.h"
#include "compreg.h"

CUDVCPluginModule _AtlModule;

// DLL Entry Point
extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
	hInstance;
	return _AtlModule.DllMain(dwReason, lpReserved); 
}


================================================
FILE: UDVC-Plugin/dllmain.h
================================================
// dllmain.h : Declaration of module class.

class CUDVCPluginModule : public ATL::CAtlDllModuleT< CUDVCPluginModule >
{
public :
	DECLARE_LIBID(LIBID_UDVCPluginLib)
	DECLARE_REGISTRY_APPID_RESOURCEID(IDR_UDVCPLUGIN, "{B8DC075B-7F8D-4B06-8733-7EB586CA06F0}")
};

extern class CUDVCPluginModule _AtlModule;


================================================
FILE: UDVC-Plugin/stdafx.cpp
================================================
/*
* MIT License
*
* Copyright(c) 2018 Balazs Bucsay
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files(the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

#include "stdafx.h"


================================================
FILE: UDVC-Plugin/stdafx.h
================================================
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently,
// but are changed infrequently

#pragma once

#ifndef STRICT
#define STRICT
#endif

#include "targetver.h"

#define _ATL_APARTMENT_THREADED
#define _ATL_NO_AUTOMATIC_NAMESPACE

#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS	// some CString constructors will be explicit
#define _ATL_REGISTER_PER_USER  // This setting must be consistent with the project's RGS file


#include "resource.h"
//#include <afx.h>
#include <atlbase.h>
#include <atlcom.h>
#include <atlctl.h>

using namespace ATL;

// adtn'l includes
#include <ShlObj.h>
#include <TsVirtualChannels.h>
#include <IntSafe.h>

#include <fstream>
#include <vector>

#include <winsock2.h>
#include <Ws2tcpip.h>
#include <windows.h>

typedef std::basic_ofstream<BYTE> ByteFile;
typedef std::basic_string<WCHAR> WString;
typedef std::vector<WString> WStringVector;


================================================
FILE: UDVC-Plugin/targetver.h
================================================
#pragma once

// Including SDKDDKVer.h defines the highest available Windows platform.

// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.

#include <SDKDDKVer.h>


================================================
FILE: UDVC-Plugin.sln
================================================

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UDVC-Plugin", "UDVC-Plugin\UDVC-Plugin.vcxproj", "{9402DF45-A060-4881-9F64-D16E094B97A7}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UDVC-PluginPS", "UDVC-Plugin\UDVC-PluginPS.vcxproj", "{15DEE2D8-6972-49C0-9369-35730A29A2CF}"
	ProjectSection(ProjectDependencies) = postProject
		{9402DF45-A060-4881-9F64-D16E094B97A7} = {9402DF45-A060-4881-9F64-D16E094B97A7}
	EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UDVC-Server", "UDVC-Server\UDVC-Server.vcxproj", "{C7E1D0A7-0ADA-4DF4-99DA-8527E856670F}"
EndProject
Global
	GlobalSection(SolutionConfigurationPlatforms) = preSolution
		Debug|x64 = Debug|x64
		Debug|x86 = Debug|x86
		Release|x64 = Release|x64
		Release|x86 = Release|x86
	EndGlobalSection
	GlobalSection(ProjectConfigurationPlatforms) = postSolution
		{9402DF45-A060-4881-9F64-D16E094B97A7}.Debug|x64.ActiveCfg = Debug|x64
		{9402DF45-A060-4881-9F64-D16E094B97A7}.Debug|x64.Build.0 = Debug|x64
		{9402DF45-A060-4881-9F64-D16E094B97A7}.Debug|x86.ActiveCfg = Debug|Win32
		{9402DF45-A060-4881-9F64-D16E094B97A7}.Debug|x86.Build.0 = Debug|Win32
		{9402DF45-A060-4881-9F64-D16E094B97A7}.Release|x64.ActiveCfg = Release|x64
		{9402DF45-A060-4881-9F64-D16E094B97A7}.Release|x64.Build.0 = Release|x64
		{9402DF45-A060-4881-9F64-D16E094B97A7}.Release|x86.ActiveCfg = Release|Win32
		{9402DF45-A060-4881-9F64-D16E094B97A7}.Release|x86.Build.0 = Release|Win32
		{15DEE2D8-6972-49C0-9369-35730A29A2CF}.Debug|x64.ActiveCfg = Debug|x64
		{15DEE2D8-6972-49C0-9369-35730A29A2CF}.Debug|x86.ActiveCfg = Debug|Win32
		{15DEE2D8-6972-49C0-9369-35730A29A2CF}.Release|x64.ActiveCfg = Release|x64
		{15DEE2D8-6972-49C0-9369-35730A29A2CF}.Release|x86.ActiveCfg = Release|Win32
		{C7E1D0A7-0ADA-4DF4-99DA-8527E856670F}.Debug|x64.ActiveCfg = Debug|x64
		{C7E1D0A7-0ADA-4DF4-99DA-8527E856670F}.Debug|x64.Build.0 = Debug|x64
		{C7E1D0A7-0ADA-4DF4-99DA-8527E856670F}.Debug|x86.ActiveCfg = Debug|Win32
		{C7E1D0A7-0ADA-4DF4-99DA-8527E856670F}.Debug|x86.Build.0 = Debug|Win32
		{C7E1D0A7-0ADA-4DF4-99DA-8527E856670F}.Release|x64.ActiveCfg = Release|x64
		{C7E1D0A7-0ADA-4DF4-99DA-8527E856670F}.Release|x64.Build.0 = Release|x64
		{C7E1D0A7-0ADA-4DF4-99DA-8527E856670F}.Release|x86.ActiveCfg = Release|Win32
		{C7E1D0A7-0ADA-4DF4-99DA-8527E856670F}.Release|x86.Build.0 = Release|Win32
	EndGlobalSection
	GlobalSection(SolutionProperties) = preSolution
		HideSolutionNode = FALSE
	EndGlobalSection
EndGlobal


================================================
FILE: UDVC-Server/UDVC-Server.cpp
================================================
/*
 * MIT License
 *
 * Copyright(c) 2018-2020 Balazs Bucsay
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files(the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions :
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include <winsock2.h>
#include <Ws2tcpip.h>
#include <windows.h>
#include <wtsapi32.h>
#include <pchannel.h>
#include <crtdbg.h>
#include <stdio.h>


#pragma comment(lib, "wtsapi32.lib")
#pragma comment(lib, "Ws2_32.lib")

#define UDVC_CHANNEL_NAME "UniversalDVC"

DWORD OpenDynamicChannel(LPCSTR szChannelName, HANDLE *phFile);
DWORD WINAPI RcWsThread(PVOID param);
DWORD WINAPI RsWcThread(PVOID param);

struct arguments {
	DWORD	mode; // 0 socket; 1 namedpiep
	WCHAR	*namedpipename;
	WCHAR	*ip;
	WCHAR	*port;
	BYTE	priority;
} running_args;

struct threadhandles {
	HANDLE	hRDP = NULL;
	SOCKET	sock = NULL;
	HANDLE	pipe = NULL;
};

HANDLE      hEvent_RDP_global;

VOID usage(WCHAR *cmdname)
{
	wprintf(L"Usage: %s [-s | -c [-p port [-i ip]] | -m [-n name]] [-0 | -1 | -2 | -3]\n"
		"Socket server mode -s (default)\n"
		"\t-p port\t  port to bind the listener (default: 31337)\n"
		"\t-i ip\t  ip to bind the listener (default: 127.0.0.1)\n\n"
		"OR \n"
		"Socket client mode -c:\n"
		"\t-p port\t  port to connect to\n"
		"\t-i ip\t  ip to connect to\n\n"
		"Named pipe mode -m:\n"
		"\t-n name\t  name of the named pipe (by default: \"\\\\.\\pipe\\UDVC_{RDP SESSION NUMBER}\")\n\n"
		"Data transfer priority parameters:\n"
		"\t-0\t  real time\t\t(WTS_CHANNEL_OPTION_DYNAMIC_PRI_REAL)\n"
		"\t-1\t  high priority\t\t(WTS_CHANNEL_OPTION_DYNAMIC_PRI_HIGH) - default\n"
		"\t-2\t  medium priority\t(WTS_CHANNEL_OPTION_DYNAMIC_PRI_MED)\n"
		"\t-3\t  low priority\t\t(WTS_CHANNEL_OPTION_DYNAMIC_PRI_LOW)\n", cmdname);

	return;
}

BOOL parse_argv(INT argc, __in_ecount(argc) WCHAR **argv)
{
	int num = 0;

	while (num < argc - 1)
	{
		num++;

		if (wcsncmp(argv[num], L"-", 1))
		{
			wprintf(L"[-] Invalid argument: %s\n", argv[num]);
			usage(argv[0]);
			return FALSE;
		}

		switch (argv[num][1])
		{
			case 'h':
			case '?':
				usage(argv[0]);
				return FALSE;
			case 'c':
				running_args.mode = 1;
				break;
			case 'm':
				running_args.mode = 2;
				break;
			case 'n':
				num++;

				if (wcsncmp(argv[num], L"\\\\.\\pipe\\", 9))
				{
					wprintf(L"[-] Named pipe name has to start with: \\\\.\\pipe\\\n");
					usage(argv[0]);
					return FALSE;
				}
				running_args.namedpipename = argv[num];
				break;

			case 's':
				running_args.mode = 0;
				break;
			case 'p':
				num++;

				running_args.port = argv[num];
				break;
			case 'i':
				num++;

				running_args.ip = argv[num];
				break;

			case '0':
				running_args.priority = WTS_CHANNEL_OPTION_DYNAMIC_PRI_REAL;
				break;
			case '1':
				running_args.priority = WTS_CHANNEL_OPTION_DYNAMIC_PRI_HIGH;
				break;
			case '2':
				running_args.priority = WTS_CHANNEL_OPTION_DYNAMIC_PRI_MED;
				break;
			case '3':
				running_args.priority = WTS_CHANNEL_OPTION_DYNAMIC_PRI_LOW;
				break;

			default:
				wprintf(L"[-] Invalid argument: %s\n", argv[num]);
				usage(argv[0]);
				return FALSE;
		}
	}
	return TRUE;
}

ULONG GetCurrentSessionId(void) {
	LPTSTR	pBuf;
	DWORD	len;
	ULONG	ret;

	if (!WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, WTSSessionId, &pBuf, &len))
	{
		return -1;
	}

	ret = (ULONG)*pBuf;
	WTSFreeMemory(pBuf);
	
	return ret;
}

INT _cdecl wmain(INT argc, __in_ecount(argc) WCHAR **argv)
{
	HANDLE	hFile;
	WSADATA	wsaData;
	ADDRINFOW *result = NULL;
	ADDRINFOW hints;
	SOCKET	s, c;
	WCHAR	tempnamepipename[24];
	HANDLE	hNamedPipe = NULL;
	ULONG	sessionId;
	int		ret;

	struct threadhandles threadhandle;

	sessionId = GetCurrentSessionId();
	wsprintf(tempnamepipename, L"\\\\.\\pipe\\UDVC_%08X", sessionId);

	running_args.mode = 0;
	running_args.port = L"31337";
	running_args.priority = 4;
	running_args.namedpipename = tempnamepipename;
	running_args.ip = L"127.0.0.1";

	wprintf(L"Universal Dynamic Virtual Channel server application\n\n");

	if (argc > 1)
		if (!parse_argv(argc, argv))
			return -1;

	
	if ((ret = OpenDynamicChannel(UDVC_CHANNEL_NAME, &hFile)) != ERROR_SUCCESS)
	{
		if (ret == 31)
			wprintf(L"[-] Could not open Dynamic Virtual Channel, plugin was not loaded on the client side: %ld\n", ret);
		else
			wprintf(L"[-] Could not open Dynamic Virtual Channel: %ld\n", ret);
		return -1;
	}

	if (running_args.mode == 0)
	{
		wprintf(L"[*] Setting up server socket\n");
		if ((ret = WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0)
		{ 
			wprintf(L"[-] WSAStartup() failed with error: %ld\n", ret);
			return -1;
		}

		ZeroMemory(&hints, sizeof(hints));
		hints.ai_family = AF_INET;
		hints.ai_socktype = SOCK_STREAM;
		hints.ai_protocol = IPPROTO_TCP;
		hints.ai_flags = AI_PASSIVE;

		if ((ret = GetAddrInfoW(running_args.ip, running_args.port, &hints, &result)) != 0) {
			wprintf(L"[-] GetAddrInfoW() failed with error: %ld\n", ret);
			WSACleanup();
			return -1;
		}

		if ((s = socket(result->ai_family, result->ai_socktype, result->ai_protocol)) == INVALID_SOCKET) {
			wprintf(L"[-] socket() failed with error: %ld\n", WSAGetLastError());
			FreeAddrInfoW(result);
			WSACleanup();
			return -1;
		}

		if ((ret = bind(s, result->ai_addr, (int)result->ai_addrlen)) == SOCKET_ERROR) {
			wprintf(L"[-] bind() failed with error: %ld\n", WSAGetLastError());
			FreeAddrInfoW(result);
			closesocket(s);
			WSACleanup();
			return -1;
		}
		FreeAddrInfoW(result);
		wprintf(L"[*] Listening on: %s:%s\n", running_args.ip, running_args.port);

		if ((ret = listen(s, SOMAXCONN)) == SOCKET_ERROR) {
			wprintf(L"[-] listen() failed with error: %ld\n", WSAGetLastError());
			closesocket(s);
			WSACleanup();
			return -1;
		}

		if ((c = accept(s, NULL, NULL)) == INVALID_SOCKET) {
			wprintf(L"[-] accept() failed with error: %ld\n", WSAGetLastError());
			closesocket(s);
			WSACleanup();
			return -1;
		}
		wprintf(L"[+] Client connected\n");

		closesocket(s);

		u_long blocking = 0;
		ret = ioctlsocket(c, FIONBIO, &blocking);
		if (ret != NO_ERROR)
		{
			wprintf(L"[-] ioctlsocket() failed with error: %ld\n", ret);
			closesocket(c);
			WSACleanup();
			return -1;
		}
		threadhandle.sock = c;
	}
	if (running_args.mode == 1)
	{
		wprintf(L"[*] Setting up client socket\n");
		if ((ret = WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0)
		{
			wprintf(L"[-] WSAStartup() failed with error: %ld\n", ret);
			return -1;
		}

		ZeroMemory(&hints, sizeof(hints));
		hints.ai_family = AF_INET;
		hints.ai_socktype = SOCK_STREAM;
		hints.ai_protocol = IPPROTO_TCP;
		hints.ai_flags = AI_PASSIVE;

		if ((ret = GetAddrInfoW(running_args.ip, running_args.port, &hints, &result)) != 0) {
			wprintf(L"[-] GetAddrInfoW() failed with error: %ld\n", ret);
			WSACleanup();
			return -1;
		}

		if ((c = socket(result->ai_family, result->ai_socktype, result->ai_protocol)) == INVALID_SOCKET) {
			wprintf(L"[-] socket() failed with error: %ld\n", WSAGetLastError());
			FreeAddrInfoW(result);
			WSACleanup();
			return -1;
		}

		if ((ret = connect(c, result->ai_addr, (int)result->ai_addrlen)) == SOCKET_ERROR) {
			wprintf(L"[-] connect() failed with error: %ld\n", WSAGetLastError());
			FreeAddrInfoW(result);
			closesocket(c);
			WSACleanup();
			return -1;
		}
		FreeAddrInfoW(result);
		wprintf(L"[*] Connected to: %s:%s\n", running_args.ip, running_args.port);

		u_long blocking = 0;
		ret = ioctlsocket(c, FIONBIO, &blocking);
		if (ret != NO_ERROR)
		{
			wprintf(L"[-] ioctlsocket() failed with error: %ld\n", ret);
			closesocket(c);
			WSACleanup();
			return -1;
		}
		threadhandle.sock = c;
	}
	if (running_args.mode == 2)
	{
		wprintf(L"[*] Setting up named pipe\n");

		if ((hNamedPipe = CreateNamedPipe(running_args.namedpipename, 
			PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
			PIPE_TYPE_BYTE | PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS, 1, 4096, 4096, 
			NMPWAIT_USE_DEFAULT_WAIT, NULL)) == INVALID_HANDLE_VALUE)
		{
			wprintf(L"[-] CreateNamedPipe() failed with: %ld", GetLastError());
			return -1;
		}

		wprintf(L"[*] Listening on pipe: %s\n", running_args.namedpipename);
		if (!ConnectNamedPipe(hNamedPipe, NULL))
		{
			wprintf(L"[-] ConnectNamedPipe() failed with: %ld", GetLastError());
			return -1;
		}

		threadhandle.pipe = hNamedPipe;
		wprintf(L"[+] Client connected to the pipe.\n");
	}

	threadhandle.hRDP = hFile;

	wprintf(L"[*] Starting thread RsWc\n");
	DWORD dwThreadId;
	HANDLE hReadThread = CreateThread(
		NULL,
		0,
		RsWcThread,
		&threadhandle,
		0,
		&dwThreadId);

	wprintf(L"[*] Starting thread RcWs\n");
	HANDLE hWriteThread = CreateThread(
		NULL,
		0,
		RcWsThread,
		&threadhandle,
		0,
		&dwThreadId);

	HANDLE ah[] = { hReadThread, hWriteThread };
	printf("[*] Waiting for threads to exit...\n");
	WaitForMultipleObjects(2, ah, TRUE, INFINITE);

	if (running_args.mode)
	{
		if ((ret = shutdown(c, SD_BOTH)) == SOCKET_ERROR) {
			wprintf(L"[-] shutdown() failed with error: %d\n", WSAGetLastError());
			closesocket(c);
			WSACleanup();
			return -1;
		}
		closesocket(c);
		WSACleanup();
	}
	else
	{
		CloseHandle(hNamedPipe);
	}

	CloseHandle(hReadThread);
	CloseHandle(hWriteThread);
	CloseHandle(hFile);

	return 0;
}

/*
*  Open a dynamic channel with the name given in szChannelName.
*  The output file handle can be used in ReadFile/WriteFile calls.
*/
DWORD OpenDynamicChannel(LPCSTR szChannelName, HANDLE *phFile)
{
	HANDLE	hWTSHandle = NULL;
	HANDLE	hWTSFileHandle;
	PVOID	vcFileHandlePtr = NULL;
	DWORD	len;
	DWORD	rc = ERROR_SUCCESS;
	BOOL	fSucc;

	hWTSHandle = WTSVirtualChannelOpenEx(WTS_CURRENT_SESSION, (LPSTR)szChannelName,
		WTS_CHANNEL_OPTION_DYNAMIC | running_args.priority);
	if (NULL == hWTSHandle)
	{
		rc = GetLastError();
		goto exitpt;
	}

	fSucc = WTSVirtualChannelQuery(hWTSHandle, WTSVirtualFileHandle,
		&vcFileHandlePtr, &len);
	if (!fSucc)
	{
		rc = GetLastError();
		goto exitpt;
	}
	if (len != sizeof(HANDLE))
	{
		rc = ERROR_INVALID_PARAMETER;
		goto exitpt;
	}

	hWTSFileHandle = *(HANDLE *)vcFileHandlePtr;

	fSucc = DuplicateHandle(GetCurrentProcess(), hWTSFileHandle, 
		GetCurrentProcess(), phFile, 0, FALSE, DUPLICATE_SAME_ACCESS);

	if (!fSucc)
	{
		rc = GetLastError();
		goto exitpt;
	}

	rc = ERROR_SUCCESS;

exitpt:
	if (vcFileHandlePtr)
	{
		WTSFreeMemory(vcFileHandlePtr);
	}
	if (hWTSHandle)
	{
		WTSVirtualChannelClose(hWTSHandle);
	}

	return rc;
}

/* 
 * Thread that reads the socket or named pipe and writes the stream to the 
 * RDP virtual channel. 
 */
DWORD WINAPI RsWcThread(PVOID param)
{
	struct threadhandles *handles = (struct threadhandles *)param;
	DWORD   dwWritten;
	DWORD	dw;
	BOOL    bSucc;
	HANDLE  hEvent_rdp, hEvent_pipe;
	char	*readBuf;
	DWORD	heapsize = 4096;

	if ((readBuf = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, heapsize)) == NULL)
	{
		wprintf(L"[-] Error allocating heap for read buffer %ld\n", GetLastError());
		return -1;
	}

	hEvent_rdp = CreateEvent(NULL, FALSE, FALSE, NULL);
	OVERLAPPED Overlapped = { 0 };
	Overlapped.hEvent = hEvent_rdp;

	hEvent_pipe = CreateEvent(NULL, FALSE, FALSE, NULL);
	OVERLAPPED Overlapped_pipe = { 0 };
	Overlapped_pipe.hEvent = hEvent_pipe;

	while (TRUE)
	{	
		if (handles->sock)
		{
			if ((dw = recv(handles->sock, readBuf, heapsize, 0)) == SOCKET_ERROR)
			{
				wprintf(L"[-] [RsWc] recv() failed with error %d, exiting thread...\n", WSAGetLastError());
				SetEvent(hEvent_RDP_global);
				return -1;
			}
			if (dw == 0)
			{
				wprintf(L"[-] [RsWc] socket closed, exiting thread...\n");
				SetEvent(hEvent_RDP_global);
				return -1;
			}
		}
		if (handles->pipe)
		{
			bSucc = ReadFile(handles->pipe, readBuf, heapsize, &dw, &Overlapped_pipe);
			if (!bSucc)
			{
				if (GetLastError() == ERROR_IO_PENDING)
				{
					dw = WaitForSingleObject(Overlapped_pipe.hEvent, INFINITE);
					bSucc = GetOverlappedResult(handles->pipe, &Overlapped_pipe, &dw, FALSE);
				}
			}
			if (!bSucc)
			{
				wprintf(L"[-] [RsWc] ReadFile()/WaitForSingleObject() error: %ld\n", GetLastError());
				return -1;
			}

			if (ResetEvent(Overlapped_pipe.hEvent) == FALSE)
			{
				wprintf(L"[-] [RsWc] ResetEvent() failed with error = %ld\n", GetLastError());
				return -1;
			}
		}

		bSucc = WriteFile(handles->hRDP, readBuf, dw, &dwWritten, &Overlapped);
		if (!bSucc)
		{
			if (GetLastError() == ERROR_IO_PENDING)
			{
				dw = WaitForSingleObject(Overlapped.hEvent, INFINITE);
				bSucc = GetOverlappedResult(handles->hRDP, &Overlapped, &dwWritten, FALSE);
			}
		}
		if (!bSucc)
		{
			wprintf(L"[-] [RsWc] WriteFile()/WaitForSingleObject() error: %ld\n", GetLastError());
			return -1;
		}
	}
	return 0;
}

/* 
 * Thread that reads the RDP virtual channel and writes the stream to the 
 * socket or named pipe. 
 */
DWORD WINAPI RcWsThread(PVOID param)
{
	struct threadhandles *handles = (struct threadhandles *)param;
	BYTE        ReadBuffer[CHANNEL_PDU_LENGTH];
	CHANNEL_PDU_HEADER *pHdr = (CHANNEL_PDU_HEADER *)ReadBuffer;
	PBYTE		pData;
	DWORD       dwRead, ret, Flags, dw;
	BOOL        bSucc;
	char		*bufWrite;
	DWORD		bufWritelen;

	hEvent_RDP_global = CreateEvent(NULL, FALSE, FALSE, NULL);
	OVERLAPPED  Overlapped = { 0 };
	DWORD TotalRead = 0;

	Overlapped.hEvent = hEvent_RDP_global;
	while (TRUE)
	{
		bSucc = ReadFile(handles->hRDP, ReadBuffer, sizeof(ReadBuffer), &dwRead, &Overlapped);
		if (!bSucc)
		{
			if (GetLastError() == ERROR_IO_PENDING)
			{
				dw = WaitForSingleObject(Overlapped.hEvent, INFINITE);
				bSucc = GetOverlappedResult(handles->hRDP, &Overlapped, &dwRead, FALSE);
			}
		}
		pData = (PBYTE)(pHdr + 1);

		if (!bSucc)
		{
			wprintf(L"[-] [RcWs] ReadFile()/WaitForSingleObject() error: %ld\n", GetLastError());
			if (handles->sock)
				closesocket(handles->sock);
			return -1;
		}

		/*
		// Event was created with bManualReset FALSE, no need to reset it.
		if ((ret = ResetEvent(Overlapped.hEvent)) == FALSE)
		{
			wprintf(L"[-] [RcWs] ResetEvent() failed with error = %ld\n", GetLastError());
			return -1;
		}*/

		// no need to pass the header.
		bufWrite = (char *)(pHdr + 1);
		/*
		WSAdata.len = pHdr->length;
		pHdr->length stores the full length of the packet, we only need that 
		was received. Ignoring the header flags as well, we just proxy the 
		bytes. This is not that nice though.
		*/
		bufWritelen = dwRead - sizeof(CHANNEL_PDU_HEADER);
		Flags = 0;

		if (handles->sock)
		{
			if ((ret = send(handles->sock, bufWrite, bufWritelen, 0)) == SOCKET_ERROR)
			{
				wprintf(L"[-] [RsWc] send() failed with error %ld\n", WSAGetLastError());
				return -1;
			}
		}
		if (handles->pipe)
		{
			bSucc = WriteFile(handles->pipe, bufWrite, bufWritelen, &ret, &Overlapped);
			if (!bSucc)
			{
				if (GetLastError() == ERROR_IO_PENDING)
				{
					dw = WaitForSingleObject(Overlapped.hEvent, INFINITE);
					bSucc = GetOverlappedResult(handles->pipe, &Overlapped, &ret, FALSE);
				}
			}
			if (!bSucc)
			{
				wprintf(L"[-] [RsWc] WriteFile()/WaitForSingleObject() error: %ld\n", GetLastError());
				return -1;
			}
		}
	}
	return 0;
}


================================================
FILE: UDVC-Server/UDVC-Server.vcxproj
================================================
<?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>
    <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>{C7E1D0A7-0ADA-4DF4-99DA-8527E856670F}</ProjectGuid>
    <Keyword>Win32Proj</Keyword>
    <RootNamespace>UDVCServer</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)$(Configuration)\$(Platform)\</OutDir>
    <IntDir>$(Platform)\$(Configuration)\</IntDir>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <LinkIncremental>true</LinkIncremental>
    <OutDir>$(SolutionDir)$(Configuration)\$(Platform)\</OutDir>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <LinkIncremental>false</LinkIncremental>
    <OutDir>$(SolutionDir)$(Configuration)\$(Platform)\</OutDir>
    <IntDir>$(Platform)\$(Configuration)\</IntDir>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <LinkIncremental>false</LinkIncremental>
    <OutDir>$(SolutionDir)$(Configuration)\$(Platform)\</OutDir>
  </PropertyGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <ClCompile>
      <PrecompiledHeader>NotUsing</PrecompiledHeader>
      <WarningLevel>Level3</WarningLevel>
      <Optimization>Disabled</Optimization>
      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <SDLCheck>true</SDLCheck>
    </ClCompile>
    <Link>
      <SubSystem>Console</SubSystem>
      <GenerateDebugInformation>true</GenerateDebugInformation>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <ClCompile>
      <PrecompiledHeader>NotUsing</PrecompiledHeader>
      <WarningLevel>Level3</WarningLevel>
      <Optimization>Disabled</Optimization>
      <PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <SDLCheck>true</SDLCheck>
    </ClCompile>
    <Link>
      <SubSystem>Console</SubSystem>
      <GenerateDebugInformation>true</GenerateDebugInformation>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <ClCompile>
      <WarningLevel>Level3</WarningLevel>
      <PrecompiledHeader>NotUsing</PrecompiledHeader>
      <Optimization>MaxSpeed</Optimization>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <IntrinsicFunctions>true</IntrinsicFunctions>
      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <SDLCheck>true</SDLCheck>
    </ClCompile>
    <Link>
      <SubSystem>Console</SubSystem>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <OptimizeReferences>true</OptimizeReferences>
      <GenerateDebugInformation>true</GenerateDebugInformation>
    </Link>
  </ItemDefinitionGroup>
  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <ClCompile>
      <WarningLevel>Level3</WarningLevel>
      <PrecompiledHeader>NotUsing</PrecompiledHeader>
      <Optimization>MaxSpeed</Optimization>
      <FunctionLevelLinking>true</FunctionLevelLinking>
      <IntrinsicFunctions>true</IntrinsicFunctions>
      <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
      <SDLCheck>true</SDLCheck>
    </ClCompile>
    <Link>
      <SubSystem>Console</SubSystem>
      <EnableCOMDATFolding>true</EnableCOMDATFolding>
      <OptimizeReferences>true</OptimizeReferences>
      <GenerateDebugInformation>true</GenerateDebugInformation>
    </Link>
  </ItemDefinitionGroup>
  <ItemGroup>
    <Text Include="ReadMe.txt" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="targetver.h" />
  </ItemGroup>
  <ItemGroup>
    <ClCompile Include="UDVC-Server.cpp" />
  </ItemGroup>
  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
  <ImportGroup Label="ExtensionTargets">
  </ImportGroup>
</Project>

================================================
FILE: UDVC-Server/UDVC-Server.vcxproj.filters
================================================
<?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>
  </ItemGroup>
  <ItemGroup>
    <Text Include="ReadMe.txt" />
  </ItemGroup>
  <ItemGroup>
    <ClInclude Include="targetver.h">
      <Filter>Header Files</Filter>
    </ClInclude>
  </ItemGroup>
  <ItemGroup>
    <ClCompile Include="UDVC-Server.cpp">
      <Filter>Source Files</Filter>
    </ClCompile>
  </ItemGroup>
</Project>

================================================
FILE: UDVC-Server/targetver.h
================================================
#pragma once

// Including SDKDDKVer.h defines the highest available Windows platform.

// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.

#include <SDKDDKVer.h>
Download .txt
gitextract_jle45i16/

├── .gitattributes
├── .gitignore
├── LICENSE.md
├── README.md
├── UDVC-Plugin/
│   ├── Resource.h
│   ├── UDVC-Plugin.cpp
│   ├── UDVC-Plugin.def
│   ├── UDVC-Plugin.h
│   ├── UDVC-Plugin.rc
│   ├── UDVC-Plugin.rgs
│   ├── UDVC-Plugin.vcxproj
│   ├── UDVC-Plugin.vcxproj.filters
│   ├── UDVC-PluginPS.vcxproj
│   ├── UDVC-PluginPS.vcxproj.filters
│   ├── UDVC-Pluginps.def
│   ├── UDVCPlugin.idl
│   ├── compreg.cpp
│   ├── compreg.h
│   ├── dllfunc.cpp
│   ├── dllmain.cpp
│   ├── dllmain.h
│   ├── stdafx.cpp
│   ├── stdafx.h
│   └── targetver.h
├── UDVC-Plugin.reg
├── UDVC-Plugin.sln
└── UDVC-Server/
    ├── UDVC-Server.cpp
    ├── UDVC-Server.vcxproj
    ├── UDVC-Server.vcxproj.filters
    └── targetver.h
Download .txt
SYMBOL INDEX (48 symbols across 7 files)

FILE: UDVC-Plugin/UDVC-Plugin.cpp
  type arguments (line 33) | struct arguments {
  type threadhandles (line 41) | struct threadhandles {
  type threadargs (line 47) | struct threadargs {
    type arguments (line 48) | struct arguments
    type threadhandles (line 49) | struct threadhandles
  class ATL_NO_VTABLE (line 60) | class ATL_NO_VTABLE
  function HRESULT (line 81) | HRESULT FinalConstruct()
  function FinalRelease (line 86) | void FinalRelease()
  function HRESULT (line 97) | HRESULT STDMETHODCALLTYPE Disconnected(DWORD dwDisconnectCode)
  function HRESULT (line 105) | HRESULT STDMETHODCALLTYPE Terminated()
  type threadargs (line 110) | struct threadargs
    type arguments (line 48) | struct arguments
    type threadhandles (line 49) | struct threadhandles
  function HRESULT (line 116) | HRESULT STDMETHODCALLTYPE OnClose()
  type threadargs (line 134) | struct threadargs
    type arguments (line 48) | struct arguments
    type threadhandles (line 49) | struct threadhandles
  type arguments (line 135) | struct arguments
  type threadhandles (line 136) | struct threadhandles
  function VOID (line 150) | VOID UDVCPlugin::DebugPrint(HRESULT hrDbg, __in_z LPWSTR fmt, ...)
  function LONG (line 185) | LONG UDVCPlugin::GetDWORDRegKey(HKEY hKey, WCHAR *strValueName, DWORD *n...
  function LONG (line 198) | LONG UDVCPlugin::GetStringRegKey(HKEY hKey, WCHAR *strValueName, WCHAR *...
  function BOOL (line 220) | BOOL UDVCPlugin::GetRegistrySettings()
  function HRESULT (line 282) | HRESULT UDVCPlugin::Initialize(__in IWTSVirtualChannelManager *pChannelMgr)
  function HRESULT (line 340) | HRESULT STDMETHODCALLTYPE UDVCPlugin::Connected()
  function DWORD (line 345) | DWORD UDVCPlugin::ListenerThread(PVOID param)
  function DWORD (line 478) | DWORD WINAPI UDVCPlugin::RsWcThread(PVOID param)
  function HRESULT (line 546) | HRESULT UDVCPlugin::OnNewChannelConnection(__in IWTSVirtualChannel *pCha...
  function VOID (line 598) | VOID UDVCPlugin::SetChannel(IWTSVirtualChannel *pChannel, struct threada...
  function HRESULT (line 604) | HRESULT STDMETHODCALLTYPE UDVCPlugin::OnDataReceived(ULONG cbSize, __in_...

FILE: UDVC-Plugin/UDVC-Plugin.h
  function _hCurrentFile (line 29) | _hCurrentFile(INVALID_HANDLE_VALUE)
  function BEGIN_COM_MAP (line 33) | DECLARE_REGISTRY_RESOURCEID(IDR_UDVCCLIENTPLUGIN)
  function FinalRelease (line 51) | void FinalRelease()

FILE: UDVC-Plugin/dllfunc.cpp
  function STDAPI (line 35) | STDAPI DllCanUnloadNow(void)
  function _Check_return_ (line 41) | _Check_return_
  function STDAPI (line 48) | STDAPI DllRegisterServer(void)
  function STDAPI (line 56) | STDAPI DllUnregisterServer(void)
  function STDAPI (line 63) | STDAPI DllInstall(BOOL bInstall, _In_opt_  LPCWSTR pszCmdLine)

FILE: UDVC-Plugin/dllmain.cpp
  function BOOL (line 34) | BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)

FILE: UDVC-Plugin/dllmain.h
  function class (line 3) | class CUDVCPluginModule : public ATL::CAtlDllModuleT< CUDVCPluginModule >

FILE: UDVC-Plugin/stdafx.h
  type std (line 40) | typedef std::basic_ofstream<BYTE> ByteFile;
  type std (line 41) | typedef std::basic_string<WCHAR> WString;
  type std (line 42) | typedef std::vector<WString> WStringVector;

FILE: UDVC-Server/UDVC-Server.cpp
  type arguments (line 43) | struct arguments {
  type threadhandles (line 51) | struct threadhandles {
  function VOID (line 59) | VOID usage(WCHAR *cmdname)
  function BOOL (line 80) | BOOL parse_argv(INT argc, __in_ecount(argc) WCHAR **argv)
  function ULONG (line 155) | ULONG GetCurrentSessionId(void) {
  function INT (line 171) | INT _cdecl wmain(INT argc, __in_ecount(argc) WCHAR **argv)
  function DWORD (line 401) | DWORD OpenDynamicChannel(LPCSTR szChannelName, HANDLE *phFile)
  function DWORD (line 461) | DWORD WINAPI RsWcThread(PVOID param)
  function DWORD (line 548) | DWORD WINAPI RcWsThread(PVOID param)
Condensed preview — 30 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (109K chars).
[
  {
    "path": ".gitattributes",
    "chars": 2518,
    "preview": "###############################################################################\n# Set default behavior to automatically "
  },
  {
    "path": ".gitignore",
    "chars": 3779,
    "preview": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User"
  },
  {
    "path": "LICENSE.md",
    "chars": 1070,
    "preview": "MIT License\n\nCopyright (c) 2020 Balazs Bucsay\n\nPermission is hereby granted, free of charge, to any person obtaining a c"
  },
  {
    "path": "README.md",
    "chars": 7694,
    "preview": "# Universal Dynamic Virtual Channel connector for Remote Desktop Services (UDVC) #\nTerminal Services (or Remote Desktop "
  },
  {
    "path": "UDVC-Plugin/Resource.h",
    "chars": 512,
    "preview": "//{{NO_DEPENDENCIES}}\n// Microsoft Visual C++ generated include file.\n// Used by UDVC-Plugin.rc\n//\n\n#define IDS_PROJNAME"
  },
  {
    "path": "UDVC-Plugin/UDVC-Plugin.cpp",
    "chars": 17912,
    "preview": "/*\n* MIT License\n*\n* Copyright(c) 2018-2020 Balazs Bucsay\n*\n* Permission is hereby granted, free of charge, to any perso"
  },
  {
    "path": "UDVC-Plugin/UDVC-Plugin.def",
    "chars": 200,
    "preview": "; UDVC-Plugin.def : Declares the module parameters.\n\nLIBRARY\n\nEXPORTS\n\tDllCanUnloadNow\t\tPRIVATE\n\tDllGetClassObject\tPRIVA"
  },
  {
    "path": "UDVC-Plugin/UDVC-Plugin.h",
    "chars": 3858,
    "preview": "// TsClientPlgn.h : Declaration of the CTsClientPlgn\n\n#pragma once\n#include \"stdafx.h\"\n#include \"resource.h\"       // ma"
  },
  {
    "path": "UDVC-Plugin/UDVC-Plugin.rgs",
    "chars": 1036,
    "preview": "HKCR\n{\n\tCLSID\n\t{\n\t\tUDVC-Plugin.UDVC-Plugin.1 = s 'UDVC-Plugin Class'\n\t\t{\n\t\t\tCLSID = s '{3C8458A3-2EBE-4840-BB07-3BA5BF81"
  },
  {
    "path": "UDVC-Plugin/UDVC-Plugin.vcxproj",
    "chars": 14528,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"14.0\" xmlns=\"http://schemas.micros"
  },
  {
    "path": "UDVC-Plugin/UDVC-Plugin.vcxproj.filters",
    "chars": 2768,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuil"
  },
  {
    "path": "UDVC-Plugin/UDVC-PluginPS.vcxproj",
    "chars": 8542,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"14.0\" xmlns=\"http://schemas.micros"
  },
  {
    "path": "UDVC-Plugin/UDVC-PluginPS.vcxproj.filters",
    "chars": 873,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuil"
  },
  {
    "path": "UDVC-Plugin/UDVC-Pluginps.def",
    "chars": 131,
    "preview": "\nLIBRARY\n\nEXPORTS\n\tDllGetClassObject\t\tPRIVATE\n\tDllCanUnloadNow\t\t\tPRIVATE\n\tDllRegisterServer\t\tPRIVATE\n\tDllUnregisterServe"
  },
  {
    "path": "UDVC-Plugin/UDVCPlugin.idl",
    "chars": 1013,
    "preview": "// UDVCPlugin.idl : IDL source for UDVC-Plugin\n//\n\n// This file will be processed by the MIDL tool to\n// produce the typ"
  },
  {
    "path": "UDVC-Plugin/compreg.cpp",
    "chars": 100,
    "preview": "// compreg.cpp : Implementation of CCompReg\n\n#include \"stdafx.h\"\n#include \"compreg.h\"\n\n\n// CCompReg\n"
  },
  {
    "path": "UDVC-Plugin/compreg.h",
    "chars": 130,
    "preview": "// compreg.h : Declaration of the CCompReg\n\n#pragma once\n\n#include \"resource.h\"       // main symbols\n#include \"UDVCPlug"
  },
  {
    "path": "UDVC-Plugin/dllfunc.cpp",
    "chars": 2533,
    "preview": "/*\n* MIT License\n*\n* Copyright(c) 2018 Balazs Bucsay\n*\n* Permission is hereby granted, free of charge, to any person obt"
  },
  {
    "path": "UDVC-Plugin/dllmain.cpp",
    "chars": 1430,
    "preview": "/*\n* MIT License\n*\n* Copyright(c) 2018 Balazs Bucsay\n*\n* Permission is hereby granted, free of charge, to any person obt"
  },
  {
    "path": "UDVC-Plugin/dllmain.h",
    "chars": 306,
    "preview": "// dllmain.h : Declaration of module class.\n\nclass CUDVCPluginModule : public ATL::CAtlDllModuleT< CUDVCPluginModule >\n{"
  },
  {
    "path": "UDVC-Plugin/stdafx.cpp",
    "chars": 1135,
    "preview": "/*\n* MIT License\n*\n* Copyright(c) 2018 Balazs Bucsay\n*\n* Permission is hereby granted, free of charge, to any person obt"
  },
  {
    "path": "UDVC-Plugin/stdafx.h",
    "chars": 940,
    "preview": "// stdafx.h : include file for standard system include files,\n// or project specific include files that are used frequen"
  },
  {
    "path": "UDVC-Plugin/targetver.h",
    "chars": 306,
    "preview": "#pragma once\n\n// Including SDKDDKVer.h defines the highest available Windows platform.\n\n// If you wish to build your app"
  },
  {
    "path": "UDVC-Plugin.sln",
    "chars": 2653,
    "preview": "\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio 14\nVisualStudioVersion = 14.0.25420.1\nMini"
  },
  {
    "path": "UDVC-Server/UDVC-Server.cpp",
    "chars": 15876,
    "preview": "/*\n * MIT License\n *\n * Copyright(c) 2018-2020 Balazs Bucsay\n *\n * Permission is hereby granted, free of charge, to any "
  },
  {
    "path": "UDVC-Server/UDVC-Server.vcxproj",
    "chars": 7730,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project DefaultTargets=\"Build\" ToolsVersion=\"14.0\" xmlns=\"http://schemas.micros"
  },
  {
    "path": "UDVC-Server/UDVC-Server.vcxproj.filters",
    "chars": 1123,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"4.0\" xmlns=\"http://schemas.microsoft.com/developer/msbuil"
  },
  {
    "path": "UDVC-Server/targetver.h",
    "chars": 306,
    "preview": "#pragma once\n\n// Including SDKDDKVer.h defines the highest available Windows platform.\n\n// If you wish to build your app"
  }
]

// ... and 2 more files (download for full content)

About this extraction

This page contains the full source code of the earthquake/UniversalDVC GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 30 files (98.6 KB), approximately 28.9k tokens, and a symbol index with 48 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!