├── .gitattributes
├── .gitignore
├── LICENSE
├── README.md
├── autoupdate.zip
├── autoupdate_v1.1.zip
├── autoupdate_v1.2.zip
├── bin
├── autoupdate.bat
├── autoupdate.ver
├── helper
│ ├── autoupdate__disable_autorun_on_startup.bat
│ ├── autoupdate__enable_autorun_on_startup.bat
│ └── autoupdate__info.txt
├── install.bat
├── uninstall.bat
└── update.bat
├── binary-download.md
├── res
├── RDPWInst.wxs
├── build_wxs.bat
├── clearres.bat
├── legacy.install.bat
├── rdpwrap-arm-kb.ini
├── rdpwrap-ini-kb.txt
└── rdpwrap.ini
├── src-installer
├── RDPWInst.dpr
├── RDPWInst.dproj
└── resource.res
├── src-rdpcheck
├── MainUnit.dfm
├── MainUnit.pas
├── RDP.ico
├── RDPCheck.dpr
├── RDPCheck.dproj
└── RDPCheck.res
├── src-rdpconfig
├── LicenseUnit.dfm
├── LicenseUnit.pas
├── MainUnit.dfm
├── MainUnit.pas
├── RDPConf.dpr
├── RDPConf.dproj
├── RDPConf.res
└── resource.res
├── src-x86-binarymaster
├── LiteINI.pas
├── rdpwrap.dpr
├── rdpwrap.dproj
└── rdpwrap.res
├── src-x86-x64-Fusix
├── Export.def
├── IniFile.cpp
├── IniFile.h
├── RDPWrap.cpp
├── RDPWrap.sln
├── RDPWrap.v11.suo
├── RDPWrap.vcxproj
├── RDPWrap.vcxproj.filters
├── ReadMe.txt
├── dllmain.cpp
├── stdafx.cpp
├── stdafx.h
└── targetver.h
└── technical.txt
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Plain text (Windows)
5 | *.txt diff=astextplain eol=crlf
6 | *.ini diff=astextplain eol=crlf
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Delphi local files (user-specific info)
2 | *.local
3 | *.identcache
4 |
5 | # Delphi history and backups
6 | __history/
7 | *.~*
8 |
9 | # Compiled binaries
10 | *.dcu
11 | *.exe
12 | *.dll
13 | *.msi
14 |
15 | # MSI local stuff
16 | *.wixobj
17 | *.wixpdb
18 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
203 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # RDP Wrapper & Autoupdate
2 |
3 | ### Automatic RDP Wrapper installer and updater // asmtron (2024-04-29)
4 |
5 | #### Info:
6 | The autoupdater first use and check the official rdpwrap.ini.
7 | If a new termsrv.dll is not supported in the offical rdpwrap.ini, autoupdate uses the updated rdpwrap.ini files from the community.
8 | Contributors: "sebaxakerhtc, asmtron, affinityv, DrDrrae, saurav-biswas"
9 | Extra rdpwrap.ini sources can also be defined...
10 |
11 | #### autoupdate.bat Options:
12 | - `-log` = redirect display output to the file autoupdate.log
13 | - `-taskadd` = add autorun of autoupdate.bat on startup in schedule task
14 | - `-taskremove` = remove autorun of autoupdate.bat on startup in schedule task
15 |
16 | #### [Download and Install](https://github.com/asmtron/rdpwrap/blob/master/binary-download.md)
17 |
18 | # RDP Wrapper Library by Stas'M
19 |
20 | [](https://t.me/rdpwrap)
21 | 
22 | [](https://github.com/stascorp/rdpwrap/releases)
23 | 
24 | 
25 | 
26 |
27 | The goal of this project is to enable Remote Desktop Host support and concurrent RDP sessions on reduced functionality systems for home usage.
28 |
29 | RDP Wrapper works as a layer between Service Control Manager and Terminal Services, so the original `termsrv.dll` file remains untouched. Also this method is very strong against Windows Update.
30 |
31 | [pVistaST]: http://stascorp.com/images/rdpwrap/pVistaST.jpg
32 | [pVistaHB]: http://stascorp.com/images/rdpwrap/pVistaHB.jpg
33 | [pWin7ST]: http://stascorp.com/images/rdpwrap/pWin7ST.jpg
34 | [pWin7HB]: http://stascorp.com/images/rdpwrap/pWin7HB.jpg
35 | [pWin8DP]: http://stascorp.com/images/rdpwrap/pWin8DP.jpg
36 | [pWin8CP]: http://stascorp.com/images/rdpwrap/pWin8CP.jpg
37 | [pWin8RP]: http://stascorp.com/images/rdpwrap/pWin8RP.jpg
38 | [pWin8]: http://stascorp.com/images/rdpwrap/pWin8.jpg
39 | [pWin81P]: http://stascorp.com/images/rdpwrap/pWin81P.jpg
40 | [pWin81]: http://stascorp.com/images/rdpwrap/pWin81.jpg
41 | [pWin10TP]: http://stascorp.com/images/rdpwrap/pWin10TP.jpg
42 | [pWin10PTP]: http://stascorp.com/images/rdpwrap/pWin10PTP.jpg
43 | [pWin10]: http://stascorp.com/images/rdpwrap/pWin10.jpg
44 |
45 | [fVistaST]: http://stascorp.com/images/rdpwrap/VistaST.png
46 | [fVistaHB]: http://stascorp.com/images/rdpwrap/VistaHB.png
47 | [fWin7ST]: http://stascorp.com/images/rdpwrap/Win7ST.png
48 | [fWin7HB]: http://stascorp.com/images/rdpwrap/Win7HB.png
49 | [fWin8DP]: http://stascorp.com/images/rdpwrap/Win8DP.png
50 | [fWin8CP]: http://stascorp.com/images/rdpwrap/Win8CP.png
51 | [fWin8RP]: http://stascorp.com/images/rdpwrap/Win8RP.png
52 | [fWin8]: http://stascorp.com/images/rdpwrap/Win8.png
53 | [fWin81P]: http://stascorp.com/images/rdpwrap/Win81P.png
54 | [fWin81]: http://stascorp.com/images/rdpwrap/Win81.png
55 | [fWin10TP]: http://stascorp.com/images/rdpwrap/Win10TP.png
56 | [fWin10PTP]: http://stascorp.com/images/rdpwrap/Win10PTP.png
57 | [fWin10]: http://stascorp.com/images/rdpwrap/Win10.png
58 |
59 | | NT Version | Screenshots |
60 | | ------------- | ----------- |
61 | | Windows Vista | [![Windows Vista Starter][pVistaST]][fVistaST] [![Windows Vista Home Basic][pVistaHB]][fVistaHB] |
62 | | Windows 7 | [![Windows 7 Starter][pWin7ST]][fWin7ST] [![Windows 7 Home Basic][pWin7HB]][fWin7HB] |
63 | | Windows 8 | [![Windows 8 Developer Preview][pWin8DP]][fWin8DP] [![Windows 8 Consumer Preview][pWin8CP]][fWin8CP] [![Windows 8 Release Preview][pWin8RP]][fWin8RP] [![Windows 8][pWin8]][fWin8] |
64 | | Windows 8.1 | [![Windows 8.1 Preview][pWin81P]][fWin81P] [![Windows 8.1][pWin81]][fWin81] |
65 | | Windows 10 | [![Windows 10 Technical Preview][pWin10TP]][fWin10TP] [![Windows 10 Pro Technical Preview][pWin10PTP]][fWin10PTP] [![Windows 10][pWin10]][fWin10] |
66 | ---
67 | [WinPPE]: https://forums.mydigitallife.net/threads/windows-product-policy-editor.39411/
68 |
69 | This solution was inspired by [Windows Product Policy Editor][WinPPE], big thanks to **kost** :)
70 |
71 | — binarymaster
72 |
73 | ### Attention:
74 | It's recommended to have original `termsrv.dll` file with the RDP Wrapper installation. If you have modified it before with other patchers, it may become unstable and crash in any moment.
75 |
76 | ### Information:
77 | - Source code is available, so you can build it on your own
78 | - RDP Wrapper does not patch `termsrv.dll`, it loads `termsrv` with different parameters
79 | - `RDPWInst` and `RDPChecker` can be redistributed without development folder and batch files
80 | - `RDPWInst` can be used for unattended installation / deployment
81 | - Windows 2000, XP and Server 2003 will not be supported
82 |
83 | ### Key features:
84 | - RDP host server on any Windows edition beginning from Vista
85 | - Console and remote sessions at the same time
86 | - Using the same user simultaneously for local and remote logon (see configuration app)
87 | - Up to [15 concurrent sessions](https://github.com/stascorp/rdpwrap/issues/192) (the actual limitation depends on your hardware and OS version)
88 | - Console and RDP session shadowing (using [Task Manager in Windows 7](http://cdn.freshdesk.com/data/helpdesk/attachments/production/1009641577/original/remote_control.png?1413476051) and lower, and [Remote Desktop Connection in Windows 8](http://woshub.com/rds-shadow-how-to-connect-to-a-user-session-in-windows-server-2012-r2/) and higher)
89 | - Full [multi-monitor support](https://github.com/stascorp/rdpwrap/issues/163) for RDP host
90 | - ...and if you find a new feature not listed here, [tell us](https://github.com/stascorp/rdpwrap/issues/new) ;)
91 |
92 | ### Porting to other platforms:
93 | - **ARM** for Windows RT (see links below)
94 | - **IA-64** for Itanium-based Windows Server? *Well, I have no idea* :)
95 |
96 | ### Building the binaries:
97 | - **x86 Delphi version** can be built with *Embarcadero RAD Studio 2010*
98 | - **x86/x64 C++ version** can be built with *Microsoft Visual Studio 2013*
99 |
100 | [andrewblock]: http://web.archive.org/web/20150810054558/http://andrewblock.net/enable-remote-desktop-on-windows-8-core/
101 | [mydigitallife]: http://forums.mydigitallife.info/threads/55935-RDP-Wrapper-Library-(works-with-Windows-8-1-Basic)
102 | [xda-dev]: http://forum.xda-developers.com/showthread.php?t=2093525&page=3
103 | [yt-updating]: http://www.youtube.com/watch?v=W9BpbEt1yJw
104 | [yt-offsets]: http://www.youtube.com/watch?v=FiD86tmRBtk
105 |
106 | ### Links:
107 | - Official GitHub repository:
108 |
https://github.com/stascorp/rdpwrap/
109 | - Official Telegram chat:
110 |
https://t.me/rdpwrap
111 | - Active discussion in the comments here:
112 |
[Enable remote desktop on Windows 8 core / basic - Andrew Block .net][andrewblock]
113 | - MDL Projects and Applications thread here:
114 |
[RDP Wrapper Library (works with Windows 8.1 Basic)][mydigitallife]
115 | - Some ideas about porting to ARM for Windows RT (post #23):
116 |
[\[Q\] Mod Windows RT to enable Remote Desktop][xda-dev]
117 | - Adding «Remote Desktop Users» group:
118 |
http://superuser.com/questions/680572/
119 |
120 | #### Tutorial videos:
121 | - [~~Updating RDP Wrapper INI file manually~~][yt-updating] (now use installer to update INI file)
122 | - [How to find offsets for new termsrv.dll versions][yt-offsets]
123 |
124 | ### Files in release package:
125 |
126 | | File name | Description |
127 | | --------- | ----------- |
128 | | `RDPWInst.exe` | RDP Wrapper Library installer/uninstaller |
129 | | `RDPCheck.exe` | Local RDP Checker (you can check the RDP is working) |
130 | | `RDPConf.exe` | RDP Wrapper Configuration |
131 | | `install.bat` | Quick install batch file |
132 | | `uninstall.bat` | Quick uninstall batch file |
133 | | `update.bat` | Quick update batch file |
134 |
135 | ### Frequently Asked Questions
136 |
137 | > Where can I download the installer or binaries?
138 |
139 | In the [GitHub Releases](https://github.com/stascorp/rdpwrap/releases) section.
140 |
141 | > Is it legal to use this application?
142 |
143 | There is no definitive answer, see [this discussion](https://github.com/stascorp/rdpwrap/issues/26).
144 |
145 | > The installer tries to access the Internet, is it normal behaviour?
146 |
147 | Yes, it works in online mode by default. You may disable it by removing `-o` flag in the `install.bat` file.
148 |
149 | > What is online install mode?
150 |
151 | Online install mode introduced in version 1.6.1. When you installing RDP Wrapper first time using this mode, it will download [latest INI file](https://github.com/stascorp/rdpwrap/blob/master/res/rdpwrap.ini) from GitHub. See [this discussion](https://github.com/stascorp/rdpwrap/issues/132).
152 |
153 | > What is INI file and why we need it?
154 |
155 | INI file was introduced in version 1.5. It stores system configuration for RDP Wrapper — general wrapping settings, binary patch codes, and per build specific data. When new `termsrv.dll` build comes out, developer adds support for it by updating INI file in repository.
156 |
157 | > Config Tool reports version 1.5, but I installed higher version. What's the matter?
158 |
159 | Beginning with version 1.5 the `rdpwrap.dll` is not updated anymore, since all settings are stored in INI file. Deal with it.
160 |
161 | > Config Tool shows `[not supported]` and RDP doesn't work. What can I do?
162 |
163 | Make sure you're connected to the Internet and run `update.bat`.
164 |
165 | > Update doesn't help, it still shows `[not supported]`.
166 |
167 | Visit [issues](https://github.com/stascorp/rdpwrap/issues) section, and check whether your `termsrv.dll` build is listed here. If you can't find such issue, create a new — specify your build version for adding to support.
168 |
169 | > Why `RDPCheck` doesn't allow to change resolution and other settings?
170 |
171 | `RDPCheck` is a very simple application and only for testing purposes. You need to use Microsoft Remote Desktop Client (`mstsc.exe`) if you want to customize the settings. You can use `127.0.0.1` or `127.0.0.2` address for loopback connection.
172 |
173 | ### Known issues:
174 | - Beginning with Windows 8 **on tablet PCs** inactive sessions will be logged out by system - [more info](https://github.com/stascorp/rdpwrap/issues/37)
175 | - Beginning with Windows 10 you can accidentally lock yourself from PC - [more info](https://github.com/stascorp/rdpwrap/issues/50)
176 | - Beginning with the Creators Update for Windows 10 Home, RDP Wrapper will no longer work, claiming that the listener is `[not listening]` because of `rfxvmt.dll` is missing - [more info](https://github.com/stascorp/rdpwrap/issues/194#issuecomment-323564111), [download links](https://github.com/stascorp/rdpwrap/issues/194#issuecomment-325627235)
177 | - Terminal Service does not start after installing some updates or "Access Denied" issue - [#215](https://github.com/stascorp/rdpwrap/issues/215), [#101](https://github.com/stascorp/rdpwrap/issues/101)
178 | - RDP Wrapper does not work with RemoteFX enabled hosts - [#127](https://github.com/stascorp/rdpwrap/issues/127), [#208](https://github.com/stascorp/rdpwrap/issues/208), [#216](https://github.com/stascorp/rdpwrap/issues/216)
179 | - RDP works, but termsrv.dll crashes on logon attempt - Windows Vista Starter RTM x86 (termsrv.dll `6.0.6000.16386`)
180 | - If Terminal Services hangs at startup, try to add **`rdpwrap.dll`** to antivirus exclusions. Also try to isolate RDP Wrapper from other shared services by the command:
181 |
`sc config TermService type= own`
182 | - RDP Wrapper can be removed by AVG Free Antivirus and [Norton Antivirus](https://github.com/stascorp/rdpwrap/issues/191) - first make sure you downloaded [official release](https://github.com/stascorp/rdpwrap/releases) from GitHub, then add it to exclusions.
183 |
184 | ---
185 |
186 | ### Change log:
187 |
188 | #### 2017.12.27
189 | - Version 1.6.2
190 | - Installer updated
191 | - Include updated INI file for latest Windows builds
192 | - Added check for supported Windows versions ([#155](https://github.com/stascorp/rdpwrap/issues/155))
193 | - Added feature to take INI file from current directory ([#300](https://github.com/stascorp/rdpwrap/issues/300))
194 | - Added feature to restore rfxvmt.dll (missing in Windows 10 Home [#194](https://github.com/stascorp/rdpwrap/issues/194))
195 | - RDP Config updated
196 | - Added feature to allow custom start programs ([#13 (comment)](https://github.com/stascorp/rdpwrap/issues/13#issuecomment-77651843))
197 | - MSI installation package added ([#14](https://github.com/stascorp/rdpwrap/issues/14))
198 |
199 | #### 2016.08.01
200 | - Version 1.6.1
201 | - Include updated INI file for latest Windows builds
202 | - Installer updated
203 | - Added online install mode
204 | - Added feature to keep settings on uninstall
205 | - RDP Config updated
206 | - Fixed update firewall rule on RDP port change
207 | - Added feature to hide users on logon
208 |
209 | #### 2015.08.12
210 | - Version 1.6
211 | - Added support for Windows 10
212 | - INI file has smaller size now - all comments are moved to KB file
213 | - Installer updated
214 | - Added workaround for 1056 error (although it isn't an error)
215 | - Added update support to installer
216 | - Newest RDPClip versions are included with installer
217 | - RDP Checker updated
218 | - Changed connect IP to 127.0.0.2
219 | - Updated some text messages
220 | - RDP Config updated
221 | - Added all possible shadowing modes
222 | - Also it will write settings to the group policy
223 |
224 | #### 2014.12.11
225 | - Version 1.5
226 | - Added INI config support
227 | - Configuration is stored in INI file now
228 | - We can extend version support without building new binaries
229 | - Added support for Windows 8.1 with KB3000850
230 | - Added support for Windows 10 Technical Preview Update 2
231 | - Installer updated
232 | - RDP Config updated
233 | - Diagnostics feature added to RDP Config
234 |
235 | #### 2014.11.14
236 | - Version 1.4
237 | - Added support for Windows 10 Technical Preview Update 1
238 | - Added support for Windows Vista SP2 with KB3003743
239 | - Added support for Windows 7 SP1 with KB3003743
240 | - Added new RDP Configuration Program
241 |
242 | #### 2014.10.21
243 | - Installer updated
244 | - Added feature to install RDP Wrapper to System32 directory
245 | - Fixed issue in the installer - NLA setting now remains unchanged
246 | - Local RDP Checker updated
247 | - SecurityLayer and UserAuthentification values changed on check start
248 | - RDP Checker restores values on exit
249 |
250 | #### 2014.10.20
251 | - Version 1.3
252 | - Added support for Windows 10 Technical Preview
253 | - Added support for Windows 7 with KB2984972
254 | - Added support for Windows 8 with KB2973501
255 | - Added extended support for Windows Vista (SP0, SP1 and SP2)
256 | - Added extended support for Windows 7 (SP0 and SP1)
257 | - Some improvements in the source code
258 | - Installer updated to v2.2
259 | - Fixed installation bug in Vista x64 (wrong expand path)
260 | - Local RDP Checker updated
261 | - Added description to error 0x708
262 |
263 | #### 2014.07.26
264 | - Version 1.2
265 | - Added support for Windows 8 Developer Preview
266 | - Added support for Windows 8 Consumer Preview
267 | - Added support for Windows 8 Release Preview
268 | - Added support for Windows 8.1 Preview
269 | - Added support for Windows 8.1
270 | - More details you will see in the source code
271 | - Installer updated to v2.1
272 |
273 | #### 2013.12.09
274 | - C++ port of RDP Wrapper was made by Fusix
275 | - x64 architecture is supported now
276 | - Added new command line installer v2.0
277 | - Added local RDP checker
278 | - Source code (C++ port, installer 2.0, local RDP checker) is also included
279 |
280 | #### 2013.10.25
281 | - Version 1.1 source code is available
282 |
283 | #### 2013.10.22
284 | - Version 1.1
285 | - Stable release
286 | - Improved wrapper (now it can wrap internal unexported termsrv.dll SL Policy function)
287 | - Added support for Windows 8 Single Language (tested on Acer Tablet PC with Intel Atom Z2760)
288 |
289 | #### 2013.10.19
290 | - Version 1.0
291 | - First [beta] version
292 | - Basic SL Policy wrapper
293 |
294 | ---
295 |
296 | #### Supported Terminal Services versions:
297 | - 6.0.X.X (Windows Vista / Server 2008)
298 | - 6.0.6000.16386 (Windows Vista)
299 | - 6.0.6001.18000 (Windows Vista SP1)
300 | - 6.0.6002.18005 (Windows Vista SP2)
301 | - 6.0.6002.19214 (Windows Vista SP2 with KB3003743 GDR)
302 | - 6.0.6002.23521 (Windows Vista SP2 with KB3003743 LDR)
303 | - 6.1.X.X (Windows 7 / Server 2008 R2)
304 | - 6.1.7600.16385 (Windows 7)
305 | - 6.1.7600.20890 (Windows 7 with KB2479710)
306 | - 6.1.7600.21316 (Windows 7 with KB2750090)
307 | - 6.1.7601.17514 (Windows 7 SP1)
308 | - 6.1.7601.21650 (Windows 7 SP1 with KB2479710)
309 | - 6.1.7601.21866 (Windows 7 SP1 with KB2647409)
310 | - 6.1.7601.22104 (Windows 7 SP1 with KB2750090)
311 | - 6.1.7601.18540 (Windows 7 SP1 with KB2984972 GDR)
312 | - 6.1.7601.22750 (Windows 7 SP1 with KB2984972 LDR)
313 | - 6.1.7601.18637 (Windows 7 SP1 with KB3003743 GDR)
314 | - 6.1.7601.22843 (Windows 7 SP1 with KB3003743 LDR)
315 | - 6.1.7601.23403 (Windows 7 SP1 with KB3125574)
316 | - 6.1.7601.24234 (Windows 7 SP1 with KB4462923)
317 | - 6.2.8102.0 (Windows 8 Developer Preview)
318 | - 6.2.8250.0 (Windows 8 Consumer Preview)
319 | - 6.2.8400.0 (Windows 8 Release Preview)
320 | - 6.2.9200.16384 (Windows 8 / Server 2012)
321 | - 6.2.9200.17048 (Windows 8 with KB2973501 GDR)
322 | - 6.2.9200.21166 (Windows 8 with KB2973501 LDR)
323 | - 6.3.9431.0 (Windows 8.1 Preview)
324 | - 6.3.9600.16384 (Windows 8.1 / Server 2012 R2)
325 | - 6.3.9600.17095 (Windows 8.1 with KB2959626)
326 | - 6.3.9600.17415 (Windows 8.1 with KB3000850)
327 | - 6.3.9600.18692 (Windows 8.1 with KB4022720)
328 | - 6.3.9600.18708 (Windows 8.1 with KB4025335)
329 | - 6.3.9600.18928 (Windows 8.1 with KB4088876)
330 | - 6.3.9600.19093 (Windows 8.1 with KB4343891)
331 | - 6.4.9841.0 (Windows 10 Technical Preview)
332 | - 6.4.9860.0 (Windows 10 Technical Preview Update 1)
333 | - 6.4.9879.0 (Windows 10 Technical Preview Update 2)
334 | - 10.0.9926.0 (Windows 10 Pro Technical Preview)
335 | - 10.0.10041.0 (Windows 10 Pro Technical Preview Update 1)
336 | - 10.0.10240.16384 (Windows 10 RTM)
337 | - 10.0.10586.0 (Windows 10 TH2 Release 151029-1700)
338 | - 10.0.10586.589 (Windows 10 TH2 Release 160906-1759 with KB3185614)
339 | - 10.0.11082.1000 (Windows 10 RS1 Release 151210-2021)
340 | - 10.0.11102.1000 (Windows 10 RS1 Release 160113-1800)
341 | - 10.0.14251.1000 (Windows 10 RS1 Release 160124-1059)
342 | - 10.0.14271.1000 (Windows 10 RS1 Release 160218-2310)
343 | - 10.0.14279.1000 (Windows 10 RS1 Release 160229-1700)
344 | - 10.0.14295.1000 (Windows 10 RS1 Release 160318-1628)
345 | - 10.0.14300.1000 (Windows Server 2016 Technical Preview 5)
346 | - 10.0.14316.1000 (Windows 10 RS1 Release 160402-2227)
347 | - 10.0.14328.1000 (Windows 10 RS1 Release 160418-1609)
348 | - 10.0.14332.1001 (Windows 10 RS1 Release 160422-1940)
349 | - 10.0.14342.1000 (Windows 10 RS1 Release 160506-1708)
350 | - 10.0.14352.1002 (Windows 10 RS1 Release 160522-1930)
351 | - 10.0.14366.0 (Windows 10 RS1 Release 160610-1700)
352 | - 10.0.14367.0 (Windows 10 RS1 Release 160613-1700)
353 | - 10.0.14372.0 (Windows 10 RS1 Release 160620-2342)
354 | - 10.0.14379.0 (Windows 10 RS1 Release 160627-1607)
355 | - 10.0.14383.0 (Windows 10 RS1 Release 160701-1839)
356 | - 10.0.14385.0 (Windows 10 RS1 Release 160706-1700)
357 | - 10.0.14388.0 (Windows 10 RS1 Release 160709-1635)
358 | - 10.0.14393.0 (Windows 10 RS1 Release 160715-1616)
359 | - 10.0.14393.1198 (Windows 10 RS1 Release Sec 170427-1353 with KB4019472)
360 | - 10.0.14393.1737 (Windows 10 RS1 Release Inmarket 170914-1249 with KB4041691)
361 | - 10.0.14393.2457 (Windows 10 RS1 Release Inmarket 180822-1743 with KB4343884)
362 | - 10.0.14901.1000 (Windows 10 RS Pre-Release 160805-1700)
363 | - 10.0.14905.1000 (Windows 10 RS Pre-Release 160811-1739)
364 | - 10.0.14915.1000 (Windows 10 RS Pre-Release 160826-1902)
365 | - 10.0.14926.1000 (Windows 10 RS Pre-Release 160910-1529)
366 | - 10.0.14931.1000 (Windows 10 RS Pre-Release 160916-1700)
367 | - 10.0.14936.1000 (Windows 10 RS Pre-Release 160923-1700)
368 | - 10.0.14942.1000 (Windows 10 RS Pre-Release 161003-1929)
369 | - 10.0.14946.1000 (Windows 10 RS Pre-Release 161007-1700)
370 | - 10.0.14951.1000 (Windows 10 RS Pre-Release 161014-1700)
371 | - 10.0.14955.1000 (Windows 10 RS Pre-Release 161020-1700)
372 | - 10.0.14959.1000 (Windows 10 RS Pre-Release 161026-1700)
373 | - 10.0.14965.1001 (Windows 10 RS Pre-Release 161104-1700)
374 | - 10.0.14971.1000 (Windows 10 RS Pre-Release 161111-1700)
375 | - 10.0.14986.1000 (Windows 10 Build 160101.0800)
376 | - 10.0.14997.1001 (Windows 10 Build 160101.0800)
377 | - 10.0.15002.1001 (Windows 10 Build 160101.0800)
378 | - 10.0.15007.1000 (Windows 10 Build 160101.0800)
379 | - 10.0.15014.1000 (Windows 10 Build 160101.0800)
380 | - 10.0.15019.1000 (Windows 10 RS Pre-Release 170121-1513)
381 | - 10.0.15025.1000 (Windows 10 RS Pre-Release 170127-1750)
382 | - 10.0.15031.0 (Windows 10 RS2 Release 170204-1546)
383 | - 10.0.15042.0 (Windows 10 RS2 Release 170219-2329)
384 | - 10.0.15046.0 (Windows 10 Build 160101.0800)
385 | - 10.0.15048.0 (Windows 10 Build 160101.0800)
386 | - 10.0.15055.0 (Windows 10 Build 160101.0800)
387 | - 10.0.15058.0 (Windows 10 Build 160101.0800)
388 | - 10.0.15061.0 (Windows 10 Build 160101.0800)
389 | - 10.0.15063.0 (Windows 10 Build 160101.0800)
390 | - 10.0.15063.296 (Windows 10 Build 160101.0800)
391 | - 10.0.15063.994 (Windows 10 Build 160101.0800)
392 | - 10.0.15063.1155 (Windows 10 Build 160101.0800)
393 | - 10.0.16179.1000 (Windows 10 Build 160101.0800)
394 | - 10.0.16184.1001 (Windows 10 Build 160101.0800)
395 | - 10.0.16199.1000 (Windows 10 Build 160101.0800)
396 | - 10.0.16215.1000 (Windows 10 Build 160101.0800)
397 | - 10.0.16232.1000 (Windows 10 Build 160101.0800)
398 | - 10.0.16237.1001 (Windows 10 Build 160101.0800)
399 | - 10.0.16241.1001 (Windows 10 Build 160101.0800)
400 | - 10.0.16251.0 (Windows 10 Build 160101.0800)
401 | - 10.0.16251.1000 (Windows 10 Build 160101.0800)
402 | - 10.0.16257.1 (Windows 10 Build 160101.0800)
403 | - 10.0.16257.1000 (Windows 10 Build 160101.0800)
404 | - 10.0.16273.1000 (Windows 10 Build 160101.0800)
405 | - 10.0.16275.1000 (Windows 10 Build 160101.0800)
406 | - 10.0.16278.1000 (Windows 10 Build 160101.0800)
407 | - 10.0.16281.1000 (Windows 10 Build 160101.0800)
408 | - 10.0.16288.1 (Windows 10 Build 160101.0800)
409 | - 10.0.16291.0 (Windows 10 Build 160101.0800)
410 | - 10.0.16294.1 (Windows 10 Build 160101.0800)
411 | - 10.0.16296.0 (Windows 10 Build 160101.0800)
412 | - 10.0.16299.0 (Windows 10 Build 160101.0800)
413 | - 10.0.16299.15 (Windows 10 Build 160101.0800)
414 | - 10.0.16353.1000 (Windows 10 Build 160101.0800)
415 | - 10.0.16362.1000 (Windows 10 Build 160101.0800)
416 | - 10.0.17004.1000 (Windows 10 Build 160101.0800)
417 | - 10.0.17017.1000 (Windows 10 Build 160101.0800)
418 | - 10.0.17025.1000 (Windows 10 Build 160101.0800)
419 | - 10.0.17035.1000 (Windows 10 Build 160101.0800)
420 | - 10.0.17046.1000 (Windows 10 Build 160101.0800)
421 | - 10.0.17063.1000 (Windows 10 Build 160101.0800)
422 | - 10.0.17115.1 (Windows 10 Build 160101.0800)
423 | - 10.0.17128.1 (Windows 10 Build 160101.0800)
424 | - 10.0.17133.1 (Windows 10 Build 160101.0800)
425 | - 10.0.17134.1 (Windows 10 Build 160101.0800)
426 | - 10.0.17723.1000 (Windows 10 Build 160101.0800)
427 | - 10.0.17763.1 (Windows 10 Build 160101.0800)
428 |
429 | #### Confirmed working on:
430 | - Windows Vista Starter (x86 - Service Pack 1 and higher)
431 | - Windows Vista Home Basic
432 | - Windows Vista Home Premium
433 | - Windows Vista Business
434 | - Windows Vista Enterprise
435 | - Windows Vista Ultimate
436 | - Windows Server 2008
437 | - Windows 7 Starter
438 | - Windows 7 Home Basic
439 | - Windows 7 Home Premium
440 | - Windows 7 Professional
441 | - Windows 7 Enterprise
442 | - Windows 7 Ultimate
443 | - Windows Server 2008 R2
444 | - Windows 8 Developer Preview
445 | - Windows 8 Consumer Preview
446 | - Windows 8 Release Preview
447 | - Windows 8
448 | - Windows 8 Single Language
449 | - Windows 8 Pro
450 | - Windows 8 Enterprise
451 | - Windows Server 2012
452 | - Windows 8.1 Preview
453 | - Windows 8.1
454 | - Windows 8.1 Connected (with Bing)
455 | - Windows 8.1 Single Language
456 | - Windows 8.1 Connected Single Language (with Bing)
457 | - Windows 8.1 Pro
458 | - Windows 8.1 Enterprise
459 | - Windows Server 2012 R2
460 | - Windows 10 Technical Preview
461 | - Windows 10 Pro Technical Preview
462 | - Windows 10 Home
463 | - Windows 10 Home Single Language
464 | - Windows 10 Pro
465 | - Windows 10 Enterprise
466 | - Windows Server 2016 Technical Preview
467 |
468 | #### Installation instructions:
469 | - Download latest release binaries and unpack files
470 | - Right-click on **`install.bat`** and select Run as Administrator
471 | - See command output for details
472 |
473 | #### To update INI file:
474 | - Right-click on **`update.bat`** and select Run as Administrator
475 | - See command output for details
476 |
477 | #### To uninstall:
478 | - Go to the directory where you extracted the files
479 | - Right-click on **`uninstall.bat`** and select Run as Administrator
480 | - See command output for details
481 |
--------------------------------------------------------------------------------
/autoupdate.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/asmtron/rdpwrap/d973562ba338608de61fad22d41c82e0ef8f5494/autoupdate.zip
--------------------------------------------------------------------------------
/autoupdate_v1.1.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/asmtron/rdpwrap/d973562ba338608de61fad22d41c82e0ef8f5494/autoupdate_v1.1.zip
--------------------------------------------------------------------------------
/autoupdate_v1.2.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/asmtron/rdpwrap/d973562ba338608de61fad22d41c82e0ef8f5494/autoupdate_v1.2.zip
--------------------------------------------------------------------------------
/bin/autoupdate.bat:
--------------------------------------------------------------------------------
1 |
392 |
393 |
447 |
453 |
454 |
--------------------------------------------------------------------------------
/bin/autoupdate.ver:
--------------------------------------------------------------------------------
1 | 1.3
2 |
--------------------------------------------------------------------------------
/bin/helper/autoupdate__disable_autorun_on_startup.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | if exist "%~dp0autoupdate.bat" (
3 | call "%~dp0autoupdate.bat" -taskremove
4 | ) else (
5 | if exist "%~dp0..\autoupdate.bat" (
6 | call "%~dp0..\autoupdate.bat" -taskremove
7 | )
8 | )
9 | pause
--------------------------------------------------------------------------------
/bin/helper/autoupdate__enable_autorun_on_startup.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | if exist "%~dp0autoupdate.bat" (
3 | call "%~dp0autoupdate.bat" -taskadd
4 | ) else (
5 | if exist "%~dp0..\autoupdate.bat" (
6 | call "%~dp0..\autoupdate.bat" -taskadd
7 | )
8 | )
9 | pause
--------------------------------------------------------------------------------
/bin/helper/autoupdate__info.txt:
--------------------------------------------------------------------------------
1 | _ _
2 | _ | | _ | | _
3 | ____ _ _| |_ ___ _ _ ____ _ | | ____| |_ ____ | | _ ____| |_
4 | / _ | | | | _)/ _ \| | | | _ \ / || |/ _ | _)/ _ ) | || \ / _ | _)
5 | ( ( | | |_| | |_| |_| | |_| | | | ( (_| ( ( | | |_( (/ / _| |_) ( ( | | |__
6 | \_||_|\____|\___\___/ \____| ||_/ \____|\_||_|\___\____(_|____/ \_||_|\___)
7 | |_|
8 |
9 | Automatic RDP Wrapper installer and updater v.1.1 asmtron (2023-10-18)
10 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11 | Options:
12 | -log = redirect display output to the file autoupdate.log
13 | -taskadd = add autorun of autoupdate.bat on startup in schedule task
14 | -taskremove = remove autorun of autoupdate.bat on startup in schedule task
15 |
16 | Info:
17 | The autoupdater first use and check the official rdpwrap.ini.
18 | If a new termsrv.dll is not supported in the offical rdpwrap.ini,
19 | autoupdate uses the updated rdpwrap.ini files from the community.
20 | contributors: "sebaxakerhtc, asmtron, affinityv, DrDrrae, saurav-biswas"
21 | Extra rdpwrap.ini sources can also be defined...
22 |
23 | { Special thanks to binarymaster and all other contributors }
24 |
25 |
26 |
27 |
28 | INSTALL of RDP Wrapper and Autoupdater
29 | ======================================
30 |
31 | 1. Create the directory: "%ProgramFiles%\RDP Wrapper"
32 | (usually C:\Program Files\RDP Wrapper)
33 |
34 |
35 | 2. Set in your Antivirus or Windows Defender an exclusion on the folder "%ProgramFiles%\RDP Wrapper" to prevent the deletion of RDP Wrapper files...
36 |
37 |
38 | 3. Copy the files from the archive "RDPWrap-v1.6.2.zip" (or newer) to the directory: "%ProgramFiles%\RDP Wrapper"
39 |
40 | DO NOT use other directories to install/extract the RDP Wrapper files.
41 | USE ONLY the directory: "%ProgramFiles%\RDP Wrapper" (usually C:\Program Files\RDP Wrapper)
42 |
43 |
44 | 4. Copy the files/folder from the archive "autoupdate.zip" (or newer) to the directory: "%ProgramFiles%\RDP Wrapper"
45 |
46 |
47 | 5. To enable autorun of autoupdate.bat on system startup, run the following helper batch file as administrator:
48 |
49 | "%ProgramFiles%\RDP Wrapper\helper\autoupdate__enable_autorun_on_startup.bat"
50 |
51 |
52 | 6. Now you can use the autoupdate batch file to install and update the RDP Wrapper. Please run autoupdate.bat as administrator:
53 |
54 | "%ProgramFiles%\RDP Wrapper\autoupdate.bat"
55 |
--------------------------------------------------------------------------------
/bin/install.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | if not exist "%~dp0RDPWInst.exe" goto :error
3 | "%~dp0RDPWInst" -i -o
4 | echo ______________________________________________________________
5 | echo.
6 | echo You can check RDP functionality with RDPCheck program.
7 | echo Also you can configure advanced settings with RDPConf program.
8 | echo.
9 | goto :anykey
10 | :error
11 | echo [-] Installer executable not found.
12 | echo Please extract all files from the downloaded package or check your anti-virus.
13 | :anykey
14 | pause
15 |
--------------------------------------------------------------------------------
/bin/uninstall.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | if not exist "%~dp0RDPWInst.exe" goto :error
3 | "%~dp0RDPWInst" -u
4 | echo.
5 | goto :anykey
6 | :error
7 | echo [-] Installer executable not found.
8 | echo Please extract all files from the downloaded package or check your anti-virus.
9 | :anykey
10 | pause
11 |
--------------------------------------------------------------------------------
/bin/update.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | if not exist "%~dp0RDPWInst.exe" goto :error
3 | "%~dp0RDPWInst" -w
4 | echo.
5 | goto :anykey
6 | :error
7 | echo [-] Installer executable not found.
8 | echo Please extract all files from the downloaded package or check your anti-virus.
9 | :anykey
10 | pause
11 |
--------------------------------------------------------------------------------
/binary-download.md:
--------------------------------------------------------------------------------
1 | INSTALL of RDP Wrapper and Autoupdater
2 | --------------------------------------
3 |
4 | 1. Create the directory: "%ProgramFiles%\RDP Wrapper"
5 |
6 | (usually C:\Program Files\RDP Wrapper)
7 |
8 | 3. Set in your Antivirus or Windows Defender an exclusion on the folder "%ProgramFiles%\RDP Wrapper" to prevent the deletion of RDP Wrapper files...
9 |
10 | 5. Download "RDPWrap-v1.6.2.zip" [LINK#1](https://github.com/stascorp/rdpwrap/releases) or [LINK#2](https://sabercathost.com/e2bm/RDPWrap-v1.6.2.zip) and extract all files to the "%ProgramFiles%\RDP Wrapper" directory
11 |
12 | DO NOT use other directories to install/extract the RDP Wrapper files.
13 | USE ONLY the "%ProgramFiles%\RDP Wrapper" directory
14 | (usually C:\Program Files\RDP Wrapper)
15 |
16 | 7. Download [autoupdate_v1.2.zip](https://github.com/asmtron/rdpwrap/raw/master/autoupdate_v1.2.zip) and extract all files to the "%ProgramFiles%\RDP Wrapper" directory
17 |
18 | 9. To enable autorun of autoupdate.bat on system startup, run the following helper batch file as administrator:
19 |
20 | "%ProgramFiles%\RDP Wrapper\helper\autoupdate__enable_autorun_on_startup.bat"
21 |
22 |
23 | 11. Now you can use the autoupdate batch file to install and update the RDP Wrapper. Please run autoupdate.bat as administrator:
24 |
25 | "%ProgramFiles%\RDP Wrapper\autoupdate.bat"
26 |
27 |
--------------------------------------------------------------------------------
/res/RDPWInst.wxs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
39 |
40 |
41 | NOT Installed AND NOT WIX_UPGRADE_DETECTED
42 | REMOVE AND NOT UPGRADINGPRODUCTCODE
43 | UPGRADINGPRODUCTCODE
44 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/res/build_wxs.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | "%ProgramFiles%\WiX Toolset v3.11\bin\candle" RDPWInst.wxs
3 | "%ProgramFiles%\WiX Toolset v3.11\bin\light" RDPWInst.wixobj
4 |
--------------------------------------------------------------------------------
/res/clearres.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | echo [FILENAMES]> clearres.txt
3 | echo Exe=%1>> clearres.txt
4 | echo SaveAs=%1>> clearres.txt
5 | echo Log=>> clearres.txt
6 | echo.>> clearres.txt
7 | echo [COMMANDS]>> clearres.txt
8 | echo -delete RCDATA,CHARTABLE,>> clearres.txt
9 | echo -delete RCDATA,DVCLAL,>> clearres.txt
10 | echo -delete RCDATA,PACKAGEINFO,>> clearres.txt
11 | echo -delete CURSORGROUP,32761,>> clearres.txt
12 | echo -delete CURSORGROUP,32762,>> clearres.txt
13 | echo -delete CURSORGROUP,32763,>> clearres.txt
14 | echo -delete CURSORGROUP,32764,>> clearres.txt
15 | echo -delete CURSORGROUP,32765,>> clearres.txt
16 | echo -delete CURSORGROUP,32766,>> clearres.txt
17 | echo -delete CURSORGROUP,32767,>> clearres.txt
18 | "C:\Program Files\Resource Hacker\ResHacker.exe" -script clearres.txt
19 | del clearres.txt
20 |
--------------------------------------------------------------------------------
/res/legacy.install.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal EnableDelayedExpansion
3 | echo RDP Wrapper Library Installer v1.0
4 | echo Copyright (C) Stas'M Corp. 2013
5 | echo.
6 |
7 | set PROCESSOR_ARCHITECTURE | find "x86" > nul
8 | if !errorlevel!==0 (
9 | goto WOW64CHK
10 | ) else (
11 | goto UNSUPPORTED
12 | )
13 |
14 | :WOW64CHK
15 | echo [*] Check if running WOW64 subsystem...
16 | set PROCESSOR_ARCHITEW6432 > nul
17 | if !errorlevel!==0 (
18 | goto UNSUPPORTED
19 | ) else (
20 | goto SUPPORTED
21 | )
22 |
23 | :SUPPORTED
24 | echo [+] Processor architecture is Intel x86 [supported]
25 | goto INSTALL
26 |
27 | :UNSUPPORTED
28 | echo [-] Unsupported processor architecture
29 | goto END
30 |
31 | :INSTALL
32 | echo [*] Installing...
33 | if not exist rdpwrap.dll (
34 | echo [-] Error: rdpwrap.dll file not found
35 | goto END
36 | )
37 | echo [*] Copying file to Program Files...
38 | md "%ProgramFiles%\RDP Wrapper"
39 | xcopy /y rdpwrap.dll "%ProgramFiles%\RDP Wrapper\"
40 | if not !errorlevel!==0 (
41 | echo [-] Failed to copy rdpwrap.dll to Program Files folder
42 | goto END
43 | )
44 | echo [*] Modifying registry...
45 | reg add "HKLM\SYSTEM\CurrentControlSet\Services\TermService\Parameters" /v ServiceDll /t REG_EXPAND_SZ /d "%ProgramFiles%\RDP Wrapper\rdpwrap.dll" /f
46 | if not !errorlevel!==0 (
47 | echo [-] Failed to modify registry
48 | goto END
49 | )
50 | echo [*] Setting firewall configuration...
51 | reg add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t REG_DWORD /d 0 /f
52 | netsh advfirewall firewall add rule name="Remote Desktop" dir=in protocol=tcp localport=3389 profile=any action=allow
53 | netsh advfirewall firewall add rule name="Remote Desktop" dir=in protocol=udp localport=3389 profile=any action=allow
54 | echo [*] Looking for TermService PID...
55 | tasklist /SVC /FI "SERVICES eq TermService" | find "PID" /V
56 | echo.
57 | if !errorlevel!==0 (
58 | goto DONE
59 | ) else (
60 | goto SVCSTART
61 | )
62 |
63 | :SVCSTART
64 | echo [*] TermService is stopped. Starting it...
65 | sc config TermService start= auto | find "1060" > nul
66 | if !errorlevel!==0 (
67 | echo [-] TermService is not installed. You need to install it manually.
68 | goto END
69 | ) else (
70 | net start TermService
71 | goto DONE
72 | )
73 |
74 | :DONE
75 | echo [+] Installation complete!
76 | echo Now reboot or restart service.
77 | echo.
78 | echo To reboot computer type:
79 | echo shutdown /r
80 | echo.
81 | echo To restart TermService type:
82 | echo taskkill /f /pid 1234 ^(replace 1234 with real PID which is shown above^)
83 | echo net start TermService
84 | echo.
85 | echo If second method is used, and there are another services sharing svchost.exe,
86 | echo you must start it too:
87 | echo net start Service1
88 | echo net start Service2
89 | echo etc.
90 | goto END
91 |
92 | :END
93 |
--------------------------------------------------------------------------------
/res/rdpwrap-arm-kb.ini:
--------------------------------------------------------------------------------
1 | ; RDP Wrapper Library configuration
2 | ; for Windows RT (ARMv7)
3 |
4 | ; This is experimental file
5 |
6 | [Main]
7 | Updated=2016-03-07
8 | LogFile=\rdpwrap.txt
9 |
10 | [SLPolicy]
11 | TerminalServices-RemoteConnectionManager-AllowRemoteConnections=1
12 | TerminalServices-RemoteConnectionManager-AllowMultipleSessions=1
13 | TerminalServices-RemoteConnectionManager-AllowAppServerMode=1
14 | TerminalServices-RemoteConnectionManager-AllowMultimon=1
15 | TerminalServices-RemoteConnectionManager-MaxUserSessions=0
16 | TerminalServices-RemoteConnectionManager-ce0ad219-4670-4988-98fb-89b14c2f072b-MaxSessions=0
17 | TerminalServices-RemoteConnectionManager-45344fe7-00e6-4ac6-9f01-d01fd4ffadfb-MaxSessions=2
18 | TerminalServices-RDP-7-Advanced-Compression-Allowed=1
19 | TerminalServices-RemoteConnectionManager-45344fe7-00e6-4ac6-9f01-d01fd4ffadfb-LocalOnly=0
20 | TerminalServices-RemoteConnectionManager-8dc86f1d-9969-4379-91c1-06fe1dc60575-MaxSessions=1000
21 | TerminalServices-DeviceRedirection-Licenses-TSEasyPrintAllowed=1
22 | TerminalServices-DeviceRedirection-Licenses-PnpRedirectionAllowed=1
23 | TerminalServices-DeviceRedirection-Licenses-TSMFPluginAllowed=1
24 | TerminalServices-RemoteConnectionManager-UiEffects-DWMRemotingAllowed=1
25 |
26 | [PatchCodes]
27 | Zero=00
28 | bjmp5=05E0
29 | CDefPolicy_Query_r3_r5=40F20013C5F8203305E0
30 | CDefPolicy_Query_r3_r0=40F20013C0F8203305E0
31 |
32 | [6.2.9200.16384]
33 | ; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled
34 | ; .text:10066DCC MOV.W R3, #0x11C
35 | ; .text:10066DD0 STR R3, [SP,#0x16C+var_13C]
36 | ; .text:10066DD2 LDR R3, =__imp_GetVersionExW
37 | ; .text:10066DD4 MOVS R4, #1 <- 0
38 | ; .text:10066DD6 ADD R0, SP, #0x16C+var_13C
39 | ; .text:10066DD8 LDR R3, [R3]
40 | SingleUserPatch.arm=1
41 | SingleUserOffset.arm=66DD4
42 | SingleUserCode.arm=Zero
43 | ; Patch CDefPolicy::Query
44 | ; Original
45 | ; .text:10059164 LDR.W R2, [R5,#0x324] ; D5 F8 24 23 ; [R5,#0x324] -> R2
46 | ; .text:10059168 LDR.W R3, [R5,#0x320] ; D5 F8 20 33 ; [R5,#0x320] -> R3
47 | ; .text:1005916C CMP R2, R3 ; 9A 42 ; compare
48 | ; .text:1005916E BNE loc_1005917A ; 04 D1 ; jump if (R2 != R3)
49 | ; Changed
50 | ; .text:10059164 MOVW R3, #0x100 ; 40 F2 00 13 ; 0x100 -> R3
51 | ; .text:10059168 STR.W R3, [R5,#0x320] ; C5 F8 20 33 ; R3 -> [R5,#0x320]
52 | ; .text:1005916C B loc_1005917A ; 05 E0 ; jump
53 | ; .text:1005916E BNE loc_1005917A ; 04 D1 ; / never executed /
54 | DefPolicyPatch.arm=1
55 | DefPolicyOffset.arm=59164
56 | DefPolicyCode.arm=CDefPolicy_Query_r3_r5
57 | ; Hook SLGetWindowsInformationDWORDWrapper
58 | SLPolicyInternal.arm=1
59 | SLPolicyOffset.arm=5F934
60 | SLPolicyFunc.arm=New_Win8SL
61 |
62 | [6.3.9600.16384]
63 | ; Patch CEnforcementCore::GetInstanceOfTSLicense
64 | ; .text:1008E6C2 BL _IsLicenseTypeLocalOnly_CSLQuery__SAJAAU_GUID__PAH_Z ; CSLQuery::IsLicenseTypeLocalOnly(_GUID &,int *)
65 | ; .text:1008E6C6 CMP R0, #0
66 | ; .text:1008E6C8 BLT loc_1008E6DA
67 | ; .text:1008E6CA LDR R3, [SP,#0x20+var_14]
68 | ; .text:1008E6CC CBZ R3, loc_1008E6DA ; 2B B1 ; jump if (R3 == 0)
69 | ; Changed
70 | ; .text:1008E6CC B loc_1008E6DA ; 05 E0 ; jump
71 | LocalOnlyPatch.arm=1
72 | LocalOnlyOffset.arm=8E6CC
73 | LocalOnlyCode.arm=bjmp5
74 | ; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled
75 | ; .text:10069E74 MOV.W R3, #0x11C
76 | ; .text:10069E78 STR R3, [SP,#0x164+var_13C]
77 | ; .text:10069E7A LDR R3, =__imp_GetVersionExW
78 | ; .text:10069E7C MOVS R4, #1 <- 0
79 | ; .text:10069E7E ADD R0, SP, #0x164+var_13C
80 | ; .text:10069E80 LDR R3, [R3]
81 | SingleUserPatch.arm=1
82 | SingleUserOffset.arm=69E7C
83 | SingleUserCode.arm=Zero
84 | ; Patch CDefPolicy::Query
85 | ; Original
86 | ; .text:10064D54 LDR.W R2, [R0,#0x324] ; D0 F8 24 23 ; [R0,#0x324] -> R2
87 | ; .text:10064D58 LDR.W R3, [R0,#0x320] ; D0 F8 20 33 ; [R0,#0x320] -> R3
88 | ; .text:10064D5C CMP R2, R3 ; 9A 42 ; compare
89 | ; .text:10064D5E BNE loc_10064D6A ; 04 D1 ; jump if (R2 != R3)
90 | ; Changed
91 | ; .text:10064D54 MOVW R3, #0x100 ; 40 F2 00 13 ; 0x100 -> R3
92 | ; .text:10064D58 STR.W R3, [R0,#0x320] ; C0 F8 20 33 ; R3 -> [R0,#0x320]
93 | ; .text:10064D5C B loc_10064D6A ; 05 E0 ; jump
94 | ; .text:10064D5E BNE loc_10064D6A ; 04 D1 ; / never executed /
95 | DefPolicyPatch.arm=1
96 | DefPolicyOffset.arm=64D54
97 | DefPolicyCode.arm=CDefPolicy_Query_r3_r0
98 | ; Hook CSLQuery::Initialize
99 | SLInitHook.arm=1
100 | SLInitOffset.arm=32188
101 | SLInitFunc.arm=New_CSLQuery_Initialize
102 |
103 | [6.3.9600.17095]
104 | ; Patch CEnforcementCore::GetInstanceOfTSLicense
105 | ; .text:1008E35A BL _IsLicenseTypeLocalOnly_CSLQuery__SAJAAU_GUID__PAH_Z ; CSLQuery::IsLicenseTypeLocalOnly(_GUID &,int *)
106 | ; .text:1008E35E CMP R0, #0
107 | ; .text:1008E360 BLT loc_1008E372
108 | ; .text:1008E362 LDR R3, [SP,#0x20+var_14]
109 | ; .text:1008E364 CBZ R3, loc_1008E372 ; 2B B1 ; jump if (R3 == 0)
110 | ; Changed
111 | ; .text:1008E364 B loc_1008E372 ; 05 E0 ; jump
112 | LocalOnlyPatch.arm=1
113 | LocalOnlyOffset.arm=8E364
114 | LocalOnlyCode.arm=bjmp5
115 | ; Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled
116 | ; .text:10069C2C MOV.W R3, #0x11C
117 | ; .text:10069C30 STR R3, [SP,#0x164+var_13C]
118 | ; .text:10069C32 LDR R3, =GetVersionExW
119 | ; .text:10069C34 MOVS R4, #1 <- 0
120 | ; .text:10069C36 ADD R0, SP, #0x164+var_13C
121 | ; .text:10069C38 LDR R3, [R3]
122 | SingleUserPatch.arm=1
123 | SingleUserOffset.arm=69C34
124 | SingleUserCode.arm=Zero
125 | ; Patch CDefPolicy::Query
126 | ; Original
127 | ; .text:100649E0 LDR.W R2, [R0,#0x324] ; D0 F8 24 23 ; [R0,#0x324] -> R2
128 | ; .text:100649E4 LDR.W R3, [R0,#0x320] ; D0 F8 20 33 ; [R0,#0x320] -> R3
129 | ; .text:100649E8 CMP R2, R3 ; 9A 42 ; compare
130 | ; .text:100649EA BNE loc_100649F6 ; 04 D1 ; jump if (R2 != R3)
131 | ; Changed
132 | ; .text:100649E0 MOVW R3, #0x100 ; 40 F2 00 13 ; 0x100 -> R3
133 | ; .text:100649E4 STR.W R3, [R0,#0x320] ; C0 F8 20 33 ; R3 -> [R0,#0x320]
134 | ; .text:100649E8 B loc_10064D6A ; 05 E0 ; jump
135 | ; .text:100649EA BNE loc_10064D6A ; 04 D1 ; / never executed /
136 | DefPolicyPatch.arm=1
137 | DefPolicyOffset.arm=649E0
138 | DefPolicyCode.arm=CDefPolicy_Query_r3_r0
139 | ; Hook CSLQuery::Initialize
140 | SLInitHook.arm=1
141 | SLInitOffset.arm=32E3C
142 | SLInitFunc.arm=New_CSLQuery_Initialize
143 |
144 | [SLInit]
145 | bServerSku=1
146 | bRemoteConnAllowed=1
147 | bFUSEnabled=1
148 | bAppServerAllowed=1
149 | bMultimonAllowed=1
150 | lMaxUserSessions=0
151 | ulMaxDebugSessions=0
152 | bInitialized=1
153 |
154 | [6.3.9600.16384-SLInit]
155 | bFUSEnabled.arm =A57E0
156 | lMaxUserSessions.arm =A57E4
157 | bAppServerAllowed.arm =A57E8
158 | bInitialized.arm =A57EC
159 | bMultimonAllowed.arm =A57F0
160 | bServerSku.arm =A57F4
161 | ulMaxDebugSessions.arm=A57F8
162 | bRemoteConnAllowed.arm=A57FC
163 |
164 | [6.3.9600.17095-SLInit]
165 | bFUSEnabled.arm =A67E0
166 | lMaxUserSessions.arm =A67E4
167 | bAppServerAllowed.arm =A67E8
168 | bInitialized.arm =A67EC
169 | bMultimonAllowed.arm =A67F0
170 | bServerSku.arm =A67F4
171 | ulMaxDebugSessions.arm=A67F8
172 | bRemoteConnAllowed.arm=A67FC
173 |
--------------------------------------------------------------------------------
/src-installer/RDPWInst.dproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {AF9BEAA3-99CD-4B2E-BE67-3F3BD27B961A}
4 | 12.0
5 | RDPWInst.dpr
6 | Release
7 | DCC32
8 |
9 |
10 | true
11 |
12 |
13 | true
14 | Base
15 | true
16 |
17 |
18 | true
19 | Base
20 | true
21 |
22 |
23 | ..\bin\
24 | WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;$(DCC_UnitAlias)
25 | ..\bin\RDPWInst.exe
26 | 00400000
27 | x86
28 |
29 |
30 | false
31 | RELEASE;$(DCC_Define)
32 | 0
33 | false
34 |
35 |
36 | DEBUG;$(DCC_Define)
37 |
38 |
39 |
40 | MainSource
41 |
42 |
43 | Base
44 |
45 |
46 | Cfg_1
47 | Base
48 |
49 |
50 | Cfg_2
51 | Base
52 |
53 |
54 |
55 |
56 | Delphi.Personality.12
57 |
58 |
59 |
60 |
61 | False
62 | True
63 | False
64 | -w
65 |
66 |
67 | False
68 | False
69 | 1
70 | 0
71 | 0
72 | 0
73 | False
74 | False
75 | False
76 | False
77 | False
78 | 1049
79 | 1251
80 |
81 |
82 |
83 |
84 | 1.0.0.0
85 |
86 |
87 |
88 |
89 |
90 | 1.0.0.0
91 |
92 |
93 |
94 | Embarcadero C++Builder Office 2000 Servers Package
95 | Embarcadero C++Builder Office XP Servers Package
96 | Microsoft Office 2000 Sample Automation Server Wrapper Components
97 | Microsoft Office XP Sample Automation Server Wrapper Components
98 |
99 |
100 | RDPWInst.dpr
101 |
102 |
103 |
104 | 12
105 |
106 |
107 |
--------------------------------------------------------------------------------
/src-installer/resource.res:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/asmtron/rdpwrap/d973562ba338608de61fad22d41c82e0ef8f5494/src-installer/resource.res
--------------------------------------------------------------------------------
/src-rdpcheck/MainUnit.dfm:
--------------------------------------------------------------------------------
1 | object Frm: TFrm
2 | Left = 0
3 | Top = 0
4 | BorderIcons = [biSystemMenu, biMinimize]
5 | BorderStyle = bsSingle
6 | Caption = 'Local RDP Checker'
7 | ClientHeight = 480
8 | ClientWidth = 640
9 | Color = clBtnFace
10 | Font.Charset = DEFAULT_CHARSET
11 | Font.Color = clWindowText
12 | Font.Height = -11
13 | Font.Name = 'Tahoma'
14 | Font.Style = []
15 | OldCreateOrder = False
16 | Position = poDesktopCenter
17 | OnCreate = FormCreate
18 | PixelsPerInch = 96
19 | TextHeight = 13
20 | object RDP: TMsRdpClient2
21 | Left = 0
22 | Top = 0
23 | Width = 640
24 | Height = 480
25 | TabOrder = 0
26 | OnDisconnected = RDPDisconnected
27 | ControlData = {0003000008000200000000000B0000000B000000}
28 | end
29 | end
30 |
--------------------------------------------------------------------------------
/src-rdpcheck/MainUnit.pas:
--------------------------------------------------------------------------------
1 | {
2 | Copyright 2015 Stas'M Corp.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | }
16 |
17 | unit MainUnit;
18 |
19 | interface
20 |
21 | uses
22 | Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
23 | Dialogs, OleServer, MSTSCLib_TLB, OleCtrls, Registry;
24 |
25 | type
26 | TFrm = class(TForm)
27 | RDP: TMsRdpClient2;
28 | procedure RDPDisconnected(ASender: TObject; discReason: Integer);
29 | procedure FormCreate(Sender: TObject);
30 | private
31 | { Private declarations }
32 | public
33 | { Public declarations }
34 | end;
35 |
36 | var
37 | Frm: TFrm;
38 | SecurityLayer, UserAuthentication: DWORD;
39 |
40 | implementation
41 |
42 | {$R *.dfm}
43 |
44 | procedure TFrm.FormCreate(Sender: TObject);
45 | var
46 | Reg: TRegistry;
47 | begin
48 | RDP.DisconnectedText := 'Disconnected.';
49 | RDP.ConnectingText := 'Connecting...';
50 | RDP.ConnectedStatusText := 'Connected.';
51 | RDP.UserName := '';
52 | RDP.Server := '127.0.0.2';
53 | Reg := TRegistry.Create;
54 | Reg.RootKey := HKEY_LOCAL_MACHINE;
55 |
56 | if Reg.OpenKey('\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp', True) then
57 | begin
58 | try
59 | SecurityLayer := Reg.ReadInteger('SecurityLayer');
60 | UserAuthentication := Reg.ReadInteger('UserAuthentication');
61 | Reg.WriteInteger('SecurityLayer', 0);
62 | Reg.WriteInteger('UserAuthentication', 0);
63 | except
64 |
65 | end;
66 | Reg.CloseKey;
67 | end;
68 |
69 | if Reg.OpenKeyReadOnly('\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp') then begin
70 | try
71 | RDP.AdvancedSettings2.RDPPort := Reg.ReadInteger('PortNumber');
72 | except
73 |
74 | end;
75 | Reg.CloseKey;
76 | end;
77 | Reg.Free;
78 | Sleep(1000);
79 | RDP.Connect;
80 | end;
81 |
82 | procedure TFrm.RDPDisconnected(ASender: TObject; discReason: Integer);
83 | var
84 | ErrStr: String;
85 | Reg: TRegistry;
86 | begin
87 | case discReason of
88 | 1: ErrStr := 'Local disconnection.';
89 | 2: ErrStr := 'Disconnected by user.';
90 | 3: ErrStr := 'Disconnected by server.';
91 | $904: ErrStr := 'Socket closed.';
92 | $C08: ErrStr := 'Decompress error.';
93 | $108: ErrStr := 'Connection timed out.';
94 | $C06: ErrStr := 'Decryption error.';
95 | $104: ErrStr := 'DNS name lookup failure.';
96 | $508: ErrStr := 'DNS lookup failed.';
97 | $B06: ErrStr := 'Encryption error.';
98 | $604: ErrStr := 'Windows Sockets gethostbyname() call failed.';
99 | $208: ErrStr := 'Host not found error.';
100 | $408: ErrStr := 'Internal error.';
101 | $906: ErrStr := 'Internal security error.';
102 | $A06: ErrStr := 'Internal security error.';
103 | $506: ErrStr := 'The encryption method specified is not valid.';
104 | $804: ErrStr := 'Bad IP address specified.';
105 | $606: ErrStr := 'Server security data is not valid.';
106 | $406: ErrStr := 'Security data is not valid.';
107 | $308: ErrStr := 'The IP address specified is not valid.';
108 | $808: ErrStr := 'License negotiation failed.';
109 | $908: ErrStr := 'Licensing time-out.';
110 | $106: ErrStr := 'Out of memory.';
111 | $206: ErrStr := 'Out of memory.';
112 | $306: ErrStr := 'Out of memory.';
113 | $706: ErrStr := 'Failed to unpack server certificate.';
114 | $204: ErrStr := 'Socket connection failed.';
115 | $404: ErrStr := 'Windows Sockets recv() call failed.';
116 | $704: ErrStr := 'Time-out occurred.';
117 | $608: ErrStr := 'Internal timer error.';
118 | $304: ErrStr := 'Windows Sockets send() call failed.';
119 | $B07: ErrStr := 'The account is disabled.';
120 | $E07: ErrStr := 'The account is expired.';
121 | $D07: ErrStr := 'The account is locked out.';
122 | $C07: ErrStr := 'The account is restricted.';
123 | $1B07: ErrStr := 'The received certificate is expired.';
124 | $1607: ErrStr := 'The policy does not support delegation of credentials to the target server.';
125 | $2107: ErrStr := 'The server authentication policy does not allow connection requests using saved credentials. The user must enter new credentials.';
126 | $807: ErrStr := 'Login failed.';
127 | $1807: ErrStr := 'No authority could be contacted for authentication. The domain name of the authenticating party could be wrong, the domain could be unreachable, or there might have been a trust relationship failure.';
128 | $A07: ErrStr := 'The specified user has no account.';
129 | $F07: ErrStr := 'The password is expired.';
130 | $1207: ErrStr := 'The user password must be changed before logging on for the first time.';
131 | $1707: ErrStr := 'Delegation of credentials to the target server is not allowed unless mutual authentication has been achieved.';
132 | $2207: ErrStr := 'The smart card is blocked.';
133 | $1C07: ErrStr := 'An incorrect PIN was presented to the smart card.';
134 | $B09: ErrStr := 'Network Level Authentication is required, run RDPCheck as administrator.';
135 | $708: ErrStr := 'RDP is working, but the client doesn''t allow loopback connections. Try to connect to your PC from another device in the network.';
136 | else ErrStr := 'Unknown code 0x'+IntToHex(discReason, 1);
137 | end;
138 | if (discReason > 2) then
139 | MessageBox(Handle, PWideChar(ErrStr), 'Disconnected', mb_Ok or mb_IconError);
140 |
141 | Reg := TRegistry.Create;
142 | Reg.RootKey := HKEY_LOCAL_MACHINE;
143 |
144 | if Reg.OpenKey('\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp', True) then
145 | begin
146 | try
147 | Reg.WriteInteger('SecurityLayer', SecurityLayer);
148 | Reg.WriteInteger('UserAuthentication', UserAuthentication);
149 | except
150 |
151 | end;
152 | Reg.CloseKey;
153 | end;
154 |
155 | Reg.Free;
156 |
157 | Halt(0);
158 | end;
159 |
160 | end.
161 |
--------------------------------------------------------------------------------
/src-rdpcheck/RDP.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/asmtron/rdpwrap/d973562ba338608de61fad22d41c82e0ef8f5494/src-rdpcheck/RDP.ico
--------------------------------------------------------------------------------
/src-rdpcheck/RDPCheck.dpr:
--------------------------------------------------------------------------------
1 | {
2 | Copyright 2014 Stas'M Corp.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | }
16 |
17 | program RDPCheck;
18 |
19 | uses
20 | Forms,
21 | MainUnit in 'MainUnit.pas' {Frm};
22 |
23 | {$R *.res}
24 |
25 | begin
26 | Application.Initialize;
27 | Application.MainFormOnTaskbar := True;
28 | Application.Title := 'Local RDP Checker';
29 | Application.CreateForm(TFrm, Frm);
30 | Application.Run;
31 | end.
32 |
--------------------------------------------------------------------------------
/src-rdpcheck/RDPCheck.dproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {90AE83F6-26B8-45D4-92FE-CF4ACCDE9F68}
4 | 12.0
5 | RDPCheck.dpr
6 | Release
7 | DCC32
8 |
9 |
10 | true
11 |
12 |
13 | true
14 | Base
15 | true
16 |
17 |
18 | true
19 | Base
20 | true
21 |
22 |
23 | ..\bin\
24 | WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;$(DCC_UnitAlias)
25 | ..\bin\RDPCheck.exe
26 | 00400000
27 | x86
28 |
29 |
30 | false
31 | RELEASE;$(DCC_Define)
32 | 0
33 | false
34 |
35 |
36 | DEBUG;$(DCC_Define)
37 |
38 |
39 |
40 | MainSource
41 |
42 |
43 |
44 |
45 |
46 | Base
47 |
48 |
49 | Cfg_1
50 | Base
51 |
52 |
53 | Cfg_2
54 | Base
55 |
56 |
57 |
58 |
59 | Delphi.Personality.12
60 |
61 |
62 |
63 |
64 | False
65 | True
66 | False
67 |
68 |
69 | True
70 | False
71 | 2
72 | 2
73 | 0
74 | 0
75 | False
76 | False
77 | False
78 | False
79 | False
80 | 1033
81 | 1252
82 |
83 |
84 | Stas'M Corp.
85 | Local RDP Checker
86 | 2.2.0.0
87 | RDPCheck
88 | Copyright © Stas'M Corp. 2015
89 | Stas'M Corp.
90 | RDPCheck.exe
91 | RDP Host Support
92 | 1.6.0.0
93 | http://stascorp.com
94 |
95 |
96 | Embarcadero C++Builder Office 2000 Servers Package
97 | Embarcadero C++Builder Office XP Servers Package
98 | Microsoft Office 2000 Sample Automation Server Wrapper Components
99 | Microsoft Office XP Sample Automation Server Wrapper Components
100 |
101 |
102 | RDPCheck.dpr
103 |
104 |
105 |
106 | 12
107 |
108 |
109 |
--------------------------------------------------------------------------------
/src-rdpcheck/RDPCheck.res:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/asmtron/rdpwrap/d973562ba338608de61fad22d41c82e0ef8f5494/src-rdpcheck/RDPCheck.res
--------------------------------------------------------------------------------
/src-rdpconfig/LicenseUnit.dfm:
--------------------------------------------------------------------------------
1 | object LicenseForm: TLicenseForm
2 | Left = 0
3 | Top = 0
4 | BorderIcons = []
5 | BorderStyle = bsDialog
6 | Caption = 'License Agreement'
7 | ClientHeight = 344
8 | ClientWidth = 386
9 | Color = clBtnFace
10 | Font.Charset = DEFAULT_CHARSET
11 | Font.Color = clWindowText
12 | Font.Height = -11
13 | Font.Name = 'Tahoma'
14 | Font.Style = []
15 | OldCreateOrder = False
16 | Position = poOwnerFormCenter
17 | PixelsPerInch = 96
18 | TextHeight = 13
19 | object mText: TMemo
20 | Left = 8
21 | Top = 8
22 | Width = 370
23 | Height = 297
24 | ReadOnly = True
25 | ScrollBars = ssBoth
26 | TabOrder = 0
27 | WordWrap = False
28 | end
29 | object bAccept: TButton
30 | Left = 115
31 | Top = 311
32 | Width = 75
33 | Height = 25
34 | Caption = '&Accept'
35 | ModalResult = 1
36 | TabOrder = 1
37 | end
38 | object bDecline: TButton
39 | Left = 196
40 | Top = 311
41 | Width = 75
42 | Height = 25
43 | Caption = '&Decline'
44 | ModalResult = 2
45 | TabOrder = 2
46 | end
47 | end
48 |
--------------------------------------------------------------------------------
/src-rdpconfig/LicenseUnit.pas:
--------------------------------------------------------------------------------
1 | {
2 | Copyright 2014 Stas'M Corp.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | }
16 |
17 | unit LicenseUnit;
18 |
19 | interface
20 |
21 | uses
22 | Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
23 | Dialogs, StdCtrls;
24 |
25 | type
26 | TLicenseForm = class(TForm)
27 | mText: TMemo;
28 | bAccept: TButton;
29 | bDecline: TButton;
30 | private
31 | { Private declarations }
32 | public
33 | { Public declarations }
34 | end;
35 |
36 | var
37 | LicenseForm: TLicenseForm;
38 |
39 | implementation
40 |
41 | {$R *.dfm}
42 |
43 | end.
44 |
--------------------------------------------------------------------------------
/src-rdpconfig/MainUnit.dfm:
--------------------------------------------------------------------------------
1 | object MainForm: TMainForm
2 | Left = 0
3 | Top = 0
4 | BorderStyle = bsDialog
5 | Caption = 'RDP Wrapper Configuration'
6 | ClientHeight = 314
7 | ClientWidth = 404
8 | Color = clBtnFace
9 | Font.Charset = DEFAULT_CHARSET
10 | Font.Color = clWindowText
11 | Font.Height = -11
12 | Font.Name = 'Tahoma'
13 | Font.Style = []
14 | OldCreateOrder = False
15 | Position = poDesktopCenter
16 | OnCloseQuery = FormCloseQuery
17 | OnCreate = FormCreate
18 | OnDestroy = FormDestroy
19 | PixelsPerInch = 96
20 | TextHeight = 13
21 | object bOK: TButton
22 | Left = 40
23 | Top = 281
24 | Width = 75
25 | Height = 25
26 | Caption = 'OK'
27 | ModalResult = 1
28 | TabOrder = 4
29 | OnClick = bOKClick
30 | end
31 | object bCancel: TButton
32 | Left = 121
33 | Top = 281
34 | Width = 75
35 | Height = 25
36 | Caption = 'Cancel'
37 | ModalResult = 2
38 | TabOrder = 5
39 | OnClick = bCancelClick
40 | end
41 | object bApply: TButton
42 | Left = 202
43 | Top = 281
44 | Width = 75
45 | Height = 25
46 | Caption = 'Apply'
47 | Enabled = False
48 | TabOrder = 6
49 | OnClick = bApplyClick
50 | end
51 | object rgNLA: TRadioGroup
52 | Left = 202
53 | Top = 89
54 | Width = 194
55 | Height = 73
56 | Caption = 'Authentication Mode'
57 | Items.Strings = (
58 | 'GUI Authentication Only'
59 | 'Default RDP Authentication'
60 | 'Network Level Authentication')
61 | TabOrder = 2
62 | OnClick = cbAllowTSConnectionsClick
63 | end
64 | object rgShadow: TRadioGroup
65 | Left = 202
66 | Top = 168
67 | Width = 194
68 | Height = 105
69 | Caption = 'Session Shadowing Mode'
70 | Items.Strings = (
71 | 'Disable Shadowing'
72 | 'Full access with user'#39's permission'
73 | 'Full access without permission'
74 | 'View only with user'#39's permission'
75 | 'View only without permission')
76 | TabOrder = 3
77 | OnClick = cbAllowTSConnectionsClick
78 | end
79 | object bLicense: TButton
80 | Left = 283
81 | Top = 281
82 | Width = 87
83 | Height = 25
84 | Caption = 'View license...'
85 | TabOrder = 7
86 | OnClick = bLicenseClick
87 | end
88 | object gbDiag: TGroupBox
89 | Left = 8
90 | Top = 6
91 | Width = 388
92 | Height = 77
93 | Caption = 'Diagnostics'
94 | TabOrder = 0
95 | object lListener: TLabel
96 | Left = 11
97 | Top = 55
98 | Width = 70
99 | Height = 13
100 | Caption = 'Listener state:'
101 | end
102 | object lService: TLabel
103 | Left = 11
104 | Top = 36
105 | Width = 67
106 | Height = 13
107 | Caption = 'Service state:'
108 | end
109 | object lsListener: TLabel
110 | Left = 91
111 | Top = 55
112 | Width = 44
113 | Height = 13
114 | Caption = 'Unknown'
115 | end
116 | object lsService: TLabel
117 | Left = 91
118 | Top = 36
119 | Width = 44
120 | Height = 13
121 | Caption = 'Unknown'
122 | end
123 | object lsTSVer: TLabel
124 | Left = 226
125 | Top = 36
126 | Width = 44
127 | Height = 13
128 | Caption = 'Unknown'
129 | end
130 | object lsWrapper: TLabel
131 | Left = 91
132 | Top = 17
133 | Width = 44
134 | Height = 13
135 | Caption = 'Unknown'
136 | end
137 | object lsWrapVer: TLabel
138 | Left = 226
139 | Top = 17
140 | Width = 44
141 | Height = 13
142 | Caption = 'Unknown'
143 | end
144 | object lTSVer: TLabel
145 | Left = 202
146 | Top = 36
147 | Width = 20
148 | Height = 13
149 | Caption = 'ver.'
150 | end
151 | object lWrapper: TLabel
152 | Left = 11
153 | Top = 17
154 | Width = 74
155 | Height = 13
156 | Caption = 'Wrapper state:'
157 | end
158 | object lWrapVer: TLabel
159 | Left = 202
160 | Top = 17
161 | Width = 20
162 | Height = 13
163 | Caption = 'ver.'
164 | end
165 | object lsSuppVer: TLabel
166 | Left = 202
167 | Top = 55
168 | Width = 70
169 | Height = 13
170 | Caption = '[support level]'
171 | end
172 | end
173 | object gbGeneral: TGroupBox
174 | Left = 8
175 | Top = 89
176 | Width = 188
177 | Height = 184
178 | Caption = 'General Settings'
179 | TabOrder = 1
180 | object lRDPPort: TLabel
181 | Left = 8
182 | Top = 44
183 | Width = 47
184 | Height = 13
185 | Caption = 'RDP port:'
186 | end
187 | object cbAllowTSConnections: TCheckBox
188 | Left = 8
189 | Top = 18
190 | Width = 132
191 | Height = 17
192 | Caption = 'Enable Remote Desktop'
193 | TabOrder = 0
194 | OnClick = cbAllowTSConnectionsClick
195 | end
196 | object cbSingleSessionPerUser: TCheckBox
197 | Left = 8
198 | Top = 69
199 | Width = 129
200 | Height = 17
201 | Caption = 'Single session per user'
202 | TabOrder = 2
203 | OnClick = cbAllowTSConnectionsClick
204 | end
205 | object cbHideUsers: TCheckBox
206 | Left = 8
207 | Top = 92
208 | Width = 149
209 | Height = 17
210 | Caption = 'Hide users on logon screen'
211 | TabOrder = 3
212 | OnClick = cbAllowTSConnectionsClick
213 | end
214 | object seRDPPort: TSpinEdit
215 | Left = 61
216 | Top = 41
217 | Width = 62
218 | Height = 22
219 | MaxValue = 65535
220 | MinValue = 0
221 | TabOrder = 1
222 | Value = 0
223 | OnChange = seRDPPortChange
224 | end
225 | object cbCustomPrg: TCheckBox
226 | Left = 8
227 | Top = 115
228 | Width = 169
229 | Height = 17
230 | Caption = 'Allow to start custom programs'
231 | TabOrder = 4
232 | OnClick = cbAllowTSConnectionsClick
233 | end
234 | end
235 | object Timer: TTimer
236 | Interval = 250
237 | OnTimer = TimerTimer
238 | Left = 352
239 | Top = 27
240 | end
241 | end
242 |
--------------------------------------------------------------------------------
/src-rdpconfig/MainUnit.pas:
--------------------------------------------------------------------------------
1 | {
2 | Copyright 2017 Stas'M Corp.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | }
16 |
17 | unit MainUnit;
18 |
19 | interface
20 |
21 | uses
22 | Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
23 | Dialogs, StdCtrls, Spin, ExtCtrls, Registry, WinSvc;
24 |
25 | type
26 | TMainForm = class(TForm)
27 | bOK: TButton;
28 | bCancel: TButton;
29 | bApply: TButton;
30 | cbSingleSessionPerUser: TCheckBox;
31 | rgNLA: TRadioGroup;
32 | cbAllowTSConnections: TCheckBox;
33 | rgShadow: TRadioGroup;
34 | seRDPPort: TSpinEdit;
35 | lRDPPort: TLabel;
36 | lService: TLabel;
37 | lListener: TLabel;
38 | lWrapper: TLabel;
39 | lsListener: TLabel;
40 | lsService: TLabel;
41 | lsWrapper: TLabel;
42 | Timer: TTimer;
43 | lTSVer: TLabel;
44 | lsTSVer: TLabel;
45 | lWrapVer: TLabel;
46 | lsWrapVer: TLabel;
47 | bLicense: TButton;
48 | gbDiag: TGroupBox;
49 | lsSuppVer: TLabel;
50 | cbHideUsers: TCheckBox;
51 | gbGeneral: TGroupBox;
52 | cbCustomPrg: TCheckBox;
53 | procedure FormCreate(Sender: TObject);
54 | procedure cbAllowTSConnectionsClick(Sender: TObject);
55 | procedure seRDPPortChange(Sender: TObject);
56 | procedure bApplyClick(Sender: TObject);
57 | procedure bCancelClick(Sender: TObject);
58 | procedure bOKClick(Sender: TObject);
59 | procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
60 | procedure bLicenseClick(Sender: TObject);
61 | procedure TimerTimer(Sender: TObject);
62 | procedure FormDestroy(Sender: TObject);
63 | private
64 | { Private declarations }
65 | public
66 | { Public declarations }
67 | function ExecWait(Cmdline: String): Boolean;
68 | procedure ReadSettings;
69 | procedure WriteSettings;
70 | end;
71 | FILE_VERSION = record
72 | Version: record case Boolean of
73 | True: (dw: DWORD);
74 | False: (w: record
75 | Minor, Major: Word;
76 | end;)
77 | end;
78 | Release, Build: Word;
79 | bDebug, bPrerelease, bPrivate, bSpecial: Boolean;
80 | end;
81 | WTS_SESSION_INFOW = record
82 | SessionId: DWORD;
83 | Name: packed array [0..33] of WideChar;
84 | State: DWORD;
85 | end;
86 | WTS_SESSION = Array[0..0] of WTS_SESSION_INFOW;
87 | PWTS_SESSION_INFOW = ^WTS_SESSION;
88 |
89 | const
90 | winstadll = 'winsta.dll';
91 | var
92 | MainForm: TMainForm;
93 | Ready: Boolean = False;
94 | Arch: Byte;
95 | OldWow64RedirectionValue: LongBool;
96 | OldPort: Word;
97 | INI: String;
98 |
99 | function WinStationEnumerateW(hServer: THandle;
100 | var ppSessionInfo: PWTS_SESSION_INFOW; var pCount: DWORD): BOOL; stdcall;
101 | external winstadll name 'WinStationEnumerateW';
102 | function WinStationFreeMemory(P: Pointer): BOOL; stdcall; external winstadll;
103 |
104 | implementation
105 |
106 | {$R *.dfm}
107 | {$R resource.res}
108 |
109 | uses
110 | LicenseUnit;
111 |
112 | function ExpandPath(Path: String): String;
113 | var
114 | Str: Array[0..511] of Char;
115 | begin
116 | Result := '';
117 | FillChar(Str, 512, 0);
118 | if Arch = 64 then
119 | Path := StringReplace(Path, '%ProgramFiles%', '%ProgramW6432%', [rfReplaceAll, rfIgnoreCase]);
120 | if ExpandEnvironmentStrings(PWideChar(Path), Str, 512) > 0 then
121 | Result := Str;
122 | end;
123 |
124 | function DisableWowRedirection: Boolean;
125 | type
126 | TFunc = function(var Wow64FsEnableRedirection: LongBool): LongBool; stdcall;
127 | var
128 | hModule: THandle;
129 | Wow64DisableWow64FsRedirection: TFunc;
130 | begin
131 | Result := False;
132 | hModule := GetModuleHandle(kernel32);
133 | if hModule <> 0 then
134 | Wow64DisableWow64FsRedirection := GetProcAddress(hModule, 'Wow64DisableWow64FsRedirection')
135 | else
136 | Exit;
137 | if @Wow64DisableWow64FsRedirection <> nil then
138 | Result := Wow64DisableWow64FsRedirection(OldWow64RedirectionValue);
139 | end;
140 |
141 | function RevertWowRedirection: Boolean;
142 | type
143 | TFunc = function(var Wow64RevertWow64FsRedirection: LongBool): LongBool; stdcall;
144 | var
145 | hModule: THandle;
146 | Wow64RevertWow64FsRedirection: TFunc;
147 | begin
148 | Result := False;
149 | hModule := GetModuleHandle(kernel32);
150 | if hModule <> 0 then
151 | Wow64RevertWow64FsRedirection := GetProcAddress(hModule, 'Wow64RevertWow64FsRedirection')
152 | else
153 | Exit;
154 | if @Wow64RevertWow64FsRedirection <> nil then
155 | Result := Wow64RevertWow64FsRedirection(OldWow64RedirectionValue);
156 | end;
157 |
158 | function GetFileVersion(const FileName: TFileName; var FileVersion: FILE_VERSION): Boolean;
159 | type
160 | VS_VERSIONINFO = record
161 | wLength, wValueLength, wType: Word;
162 | szKey: Array[1..16] of WideChar;
163 | Padding1: Word;
164 | Value: VS_FIXEDFILEINFO;
165 | Padding2, Children: Word;
166 | end;
167 | PVS_VERSIONINFO = ^VS_VERSIONINFO;
168 | const
169 | VFF_DEBUG = 1;
170 | VFF_PRERELEASE = 2;
171 | VFF_PRIVATE = 8;
172 | VFF_SPECIAL = 32;
173 | var
174 | hFile: HMODULE;
175 | hResourceInfo: HRSRC;
176 | VersionInfo: PVS_VERSIONINFO;
177 | begin
178 | Result := False;
179 |
180 | hFile := LoadLibraryEx(PWideChar(FileName), 0, LOAD_LIBRARY_AS_DATAFILE);
181 | if hFile = 0 then
182 | Exit;
183 |
184 | hResourceInfo := FindResource(hFile, PWideChar(1), PWideChar($10));
185 | if hResourceInfo = 0 then
186 | Exit;
187 |
188 | VersionInfo := Pointer(LoadResource(hFile, hResourceInfo));
189 | if VersionInfo = nil then
190 | Exit;
191 |
192 | FileVersion.Version.dw := VersionInfo.Value.dwFileVersionMS;
193 | FileVersion.Release := Word(VersionInfo.Value.dwFileVersionLS shr 16);
194 | FileVersion.Build := Word(VersionInfo.Value.dwFileVersionLS);
195 | FileVersion.bDebug := (VersionInfo.Value.dwFileFlags and VFF_DEBUG) = VFF_DEBUG;
196 | FileVersion.bPrerelease := (VersionInfo.Value.dwFileFlags and VFF_PRERELEASE) = VFF_PRERELEASE;
197 | FileVersion.bPrivate := (VersionInfo.Value.dwFileFlags and VFF_PRIVATE) = VFF_PRIVATE;
198 | FileVersion.bSpecial := (VersionInfo.Value.dwFileFlags and VFF_SPECIAL) = VFF_SPECIAL;
199 |
200 | FreeLibrary(hFile);
201 | Result := True;
202 | end;
203 |
204 | function IsWrapperInstalled(var WrapperPath: String): ShortInt;
205 | var
206 | TermServiceHost,
207 | TermServicePath: String;
208 | Reg: TRegistry;
209 | begin
210 | Result := -1;
211 | WrapperPath := '';
212 | Reg := TRegistry.Create;
213 | Reg.RootKey := HKEY_LOCAL_MACHINE;
214 | if not Reg.OpenKeyReadOnly('\SYSTEM\CurrentControlSet\Services\TermService') then begin
215 | Reg.Free;
216 | Exit;
217 | end;
218 | TermServiceHost := Reg.ReadString('ImagePath');
219 | Reg.CloseKey;
220 | if Pos('svchost.exe', LowerCase(TermServiceHost)) = 0 then
221 | begin
222 | Result := 2;
223 | Reg.Free;
224 | Exit;
225 | end;
226 | if not Reg.OpenKeyReadOnly('\SYSTEM\CurrentControlSet\Services\TermService\Parameters') then
227 | begin
228 | Reg.Free;
229 | Exit;
230 | end;
231 | TermServicePath := Reg.ReadString('ServiceDll');
232 | Reg.CloseKey;
233 | Reg.Free;
234 | if (Pos('termsrv.dll', LowerCase(TermServicePath)) = 0)
235 | and (Pos('rdpwrap.dll', LowerCase(TermServicePath)) = 0) then
236 | begin
237 | Result := 2;
238 | Exit;
239 | end;
240 |
241 | if Pos('rdpwrap.dll', LowerCase(TermServicePath)) > 0 then begin
242 | WrapperPath := TermServicePath;
243 | Result := 1;
244 | end else
245 | Result := 0;
246 | end;
247 |
248 | function GetTermSrvState: ShortInt;
249 | type
250 | SERVICE_STATUS_PROCESS = record
251 | dwServiceType,
252 | dwCurrentState,
253 | dwControlsAccepted,
254 | dwWin32ExitCode,
255 | dwServiceSpecificExitCode,
256 | dwCheckPoint,
257 | dwWaitHint,
258 | dwProcessId,
259 | dwServiceFlags: DWORD;
260 | end;
261 | PSERVICE_STATUS_PROCESS = ^SERVICE_STATUS_PROCESS;
262 | const
263 | SvcName = 'TermService';
264 | var
265 | hSC: SC_HANDLE;
266 | hSvc: THandle;
267 | lpServiceStatusProcess: PSERVICE_STATUS_PROCESS;
268 | Buf: Pointer;
269 | cbBufSize, pcbBytesNeeded: Cardinal;
270 | begin
271 | Result := -1;
272 | hSC := OpenSCManager(nil, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT);
273 | if hSC = 0 then
274 | Exit;
275 |
276 | hSvc := OpenService(hSC, PWideChar(SvcName), SERVICE_QUERY_STATUS);
277 | if hSvc = 0 then
278 | begin
279 | CloseServiceHandle(hSC);
280 | Exit;
281 | end;
282 |
283 | if QueryServiceStatusEx(hSvc, SC_STATUS_PROCESS_INFO, nil, 0, pcbBytesNeeded) then
284 | Exit;
285 |
286 | cbBufSize := pcbBytesNeeded;
287 | GetMem(Buf, cbBufSize);
288 |
289 | if not QueryServiceStatusEx(hSvc, SC_STATUS_PROCESS_INFO, Buf, cbBufSize, pcbBytesNeeded) then begin
290 | FreeMem(Buf, cbBufSize);
291 | CloseServiceHandle(hSvc);
292 | CloseServiceHandle(hSC);
293 | Exit;
294 | end else begin
295 | lpServiceStatusProcess := Buf;
296 | Result := ShortInt(lpServiceStatusProcess^.dwCurrentState);
297 | end;
298 | FreeMem(Buf, cbBufSize);
299 | CloseServiceHandle(hSvc);
300 | CloseServiceHandle(hSC);
301 | end;
302 |
303 | function IsListenerWorking: Boolean;
304 | var
305 | pCount: DWORD;
306 | SessionInfo: PWTS_SESSION_INFOW;
307 | I: Integer;
308 | begin
309 | Result := False;
310 | if not WinStationEnumerateW(0, SessionInfo, pCount) then
311 | Exit;
312 | for I := 0 to pCount - 1 do
313 | if SessionInfo^[I].Name = 'RDP-Tcp' then begin
314 | Result := True;
315 | Break;
316 | end;
317 | WinStationFreeMemory(SessionInfo);
318 | end;
319 |
320 | function ExtractResText(ResName: String): String;
321 | var
322 | ResStream: TResourceStream;
323 | Str: TStringList;
324 | begin
325 | ResStream := TResourceStream.Create(HInstance, ResName, RT_RCDATA);
326 | Str := TStringList.Create;
327 | try
328 | Str.LoadFromStream(ResStream);
329 | except
330 |
331 | end;
332 | ResStream.Free;
333 | Result := Str.Text;
334 | Str.Free;
335 | end;
336 |
337 | function TMainForm.ExecWait(Cmdline: String): Boolean;
338 | var
339 | si: STARTUPINFO;
340 | pi: PROCESS_INFORMATION;
341 | begin
342 | Result := False;
343 | ZeroMemory(@si, sizeof(si));
344 | si.cb := sizeof(si);
345 | si.dwFlags := STARTF_USESHOWWINDOW;
346 | si.wShowWindow := SW_HIDE;
347 | UniqueString(Cmdline);
348 | if not CreateProcess(nil, PWideChar(Cmdline), nil, nil, True, 0, nil, nil, si, pi) then begin
349 | MessageBox(Handle,
350 | PWideChar('CreateProcess error (code: ' + IntToStr(GetLastError) + ').'),
351 | 'Error', MB_ICONERROR or MB_OK);
352 | Exit;
353 | end;
354 | CloseHandle(pi.hThread);
355 | WaitForSingleObject(pi.hProcess, INFINITE);
356 | CloseHandle(pi.hProcess);
357 | Result := True;
358 | end;
359 |
360 | procedure TMainForm.ReadSettings;
361 | var
362 | Reg: TRegistry;
363 | SecurityLayer, UserAuthentication: Integer;
364 | begin
365 | Reg := TRegistry.Create;
366 | Reg.RootKey := HKEY_LOCAL_MACHINE;
367 | Reg.OpenKeyReadOnly('\SYSTEM\CurrentControlSet\Control\Terminal Server');
368 | try
369 | cbAllowTSConnections.Checked := not Reg.ReadBool('fDenyTSConnections');
370 | except
371 |
372 | end;
373 | try
374 | cbSingleSessionPerUser.Checked := Reg.ReadBool('fSingleSessionPerUser');
375 | except
376 |
377 | end;
378 | try
379 | cbCustomPrg.Checked := Reg.ReadBool('HonorLegacySettings');
380 | except
381 |
382 | end;
383 | Reg.CloseKey;
384 |
385 | Reg.OpenKeyReadOnly('\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp');
386 | seRDPPort.Value := 3389;
387 | try
388 | seRDPPort.Value := Reg.ReadInteger('PortNumber');
389 | except
390 |
391 | end;
392 | OldPort := seRDPPort.Value;
393 | SecurityLayer := 0;
394 | UserAuthentication := 0;
395 | try
396 | SecurityLayer := Reg.ReadInteger('SecurityLayer');
397 | UserAuthentication := Reg.ReadInteger('UserAuthentication');
398 | except
399 |
400 | end;
401 | if (SecurityLayer = 0) and (UserAuthentication = 0) then
402 | rgNLA.ItemIndex := 0;
403 | if (SecurityLayer = 1) and (UserAuthentication = 0) then
404 | rgNLA.ItemIndex := 1;
405 | if (SecurityLayer = 2) and (UserAuthentication = 1) then
406 | rgNLA.ItemIndex := 2;
407 | try
408 | rgShadow.ItemIndex := Reg.ReadInteger('Shadow');
409 | except
410 |
411 | end;
412 | Reg.CloseKey;
413 | Reg.OpenKeyReadOnly('\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System');
414 | try
415 | cbHideUsers.Checked := Reg.ReadBool('dontdisplaylastusername');
416 | except
417 |
418 | end;
419 | Reg.CloseKey;
420 | Reg.Free;
421 | end;
422 |
423 | procedure TMainForm.WriteSettings;
424 | var
425 | Reg: TRegistry;
426 | SecurityLayer, UserAuthentication: Integer;
427 | begin
428 | Reg := TRegistry.Create;
429 | Reg.RootKey := HKEY_LOCAL_MACHINE;
430 | Reg.OpenKey('\SYSTEM\CurrentControlSet\Control\Terminal Server', True);
431 | try
432 | Reg.WriteBool('fDenyTSConnections', not cbAllowTSConnections.Checked);
433 | except
434 |
435 | end;
436 | try
437 | Reg.WriteBool('fSingleSessionPerUser', cbSingleSessionPerUser.Checked);
438 | except
439 |
440 | end;
441 | try
442 | Reg.WriteBool('HonorLegacySettings', cbCustomPrg.Checked);
443 | except
444 |
445 | end;
446 | Reg.CloseKey;
447 |
448 | Reg.OpenKey('\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp', True);
449 | try
450 | Reg.WriteInteger('PortNumber', seRDPPort.Value);
451 | except
452 |
453 | end;
454 | if OldPort <> seRDPPort.Value then
455 | begin
456 | OldPort := seRDPPort.Value;
457 | ExecWait('netsh advfirewall firewall set rule name="Remote Desktop" new localport=' + IntToStr(OldPort));
458 | end;
459 | case rgNLA.ItemIndex of
460 | 0: begin
461 | SecurityLayer := 0;
462 | UserAuthentication := 0;
463 | end;
464 | 1: begin
465 | SecurityLayer := 1;
466 | UserAuthentication := 0;
467 | end;
468 | 2: begin
469 | SecurityLayer := 2;
470 | UserAuthentication := 1;
471 | end;
472 | else begin
473 | SecurityLayer := -1;
474 | UserAuthentication := -1;
475 | end;
476 | end;
477 | if SecurityLayer >= 0 then begin
478 | try
479 | Reg.WriteInteger('SecurityLayer', SecurityLayer);
480 | Reg.WriteInteger('UserAuthentication', UserAuthentication);
481 | except
482 |
483 | end;
484 | end;
485 | if rgShadow.ItemIndex >= 0 then begin
486 | try
487 | Reg.WriteInteger('Shadow', rgShadow.ItemIndex);
488 | except
489 |
490 | end;
491 | end;
492 | Reg.CloseKey;
493 | Reg.OpenKey('\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services', True);
494 | if rgShadow.ItemIndex >= 0 then begin
495 | try
496 | Reg.WriteInteger('Shadow', rgShadow.ItemIndex);
497 | except
498 |
499 | end;
500 | end;
501 | Reg.CloseKey;
502 | Reg.OpenKey('\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System', True);
503 | try
504 | Reg.WriteBool('dontdisplaylastusername', cbHideUsers.Checked);
505 | except
506 |
507 | end;
508 | Reg.CloseKey;
509 | Reg.Free;
510 | end;
511 |
512 | function CheckSupport(FV: FILE_VERSION): Byte;
513 | var
514 | VerTxt: String;
515 | begin
516 | Result := 0;
517 | if (FV.Version.w.Major = 6) and (FV.Version.w.Minor = 0) then
518 | Result := 1;
519 | if (FV.Version.w.Major = 6) and (FV.Version.w.Minor = 1) then
520 | Result := 1;
521 | VerTxt := Format('%d.%d.%d.%d',
522 | [FV.Version.w.Major, FV.Version.w.Minor, FV.Release, FV.Build]);
523 | if Pos('[' + VerTxt + ']', INI) > 0 then
524 | Result := 2;
525 | end;
526 |
527 | procedure TMainForm.TimerTimer(Sender: TObject);
528 | var
529 | WrapperPath, INIPath: String;
530 | FV: FILE_VERSION;
531 | L: TStringList;
532 | CheckSupp: Boolean;
533 | begin
534 | CheckSupp := False;
535 | case IsWrapperInstalled(WrapperPath) of
536 | -1: begin
537 | lsWrapper.Caption := 'Unknown';
538 | lsWrapper.Font.Color := clGrayText;
539 | end;
540 | 0: begin
541 | lsWrapper.Caption := 'Not installed';
542 | lsWrapper.Font.Color := clGrayText;
543 | end;
544 | 1: begin
545 | lsWrapper.Caption := 'Installed';
546 | lsWrapper.Font.Color := clGreen;
547 | CheckSupp := True;
548 | INIPath := ExtractFilePath(ExpandPath(WrapperPath)) + 'rdpwrap.ini';
549 | if not FileExists(INIPath) then
550 | CheckSupp := False;
551 | end;
552 | 2: begin
553 | lsWrapper.Caption := '3rd-party';
554 | lsWrapper.Font.Color := clRed;
555 | end;
556 | end;
557 | case GetTermSrvState of
558 | -1, 0: begin
559 | lsService.Caption := 'Unknown';
560 | lsService.Font.Color := clGrayText;
561 | end;
562 | SERVICE_STOPPED: begin
563 | lsService.Caption := 'Stopped';
564 | lsService.Font.Color := clRed;
565 | end;
566 | SERVICE_START_PENDING: begin
567 | lsService.Caption := 'Starting...';
568 | lsService.Font.Color := clGrayText;
569 | end;
570 | SERVICE_STOP_PENDING: begin
571 | lsService.Caption := 'Stopping...';
572 | lsService.Font.Color := clGrayText;
573 | end;
574 | SERVICE_RUNNING: begin
575 | lsService.Caption := 'Running';
576 | lsService.Font.Color := clGreen;
577 | end;
578 | SERVICE_CONTINUE_PENDING: begin
579 | lsService.Caption := 'Resuming...';
580 | lsService.Font.Color := clGrayText;
581 | end;
582 | SERVICE_PAUSE_PENDING: begin
583 | lsService.Caption := 'Suspending...';
584 | lsService.Font.Color := clGrayText;
585 | end;
586 | SERVICE_PAUSED: begin
587 | lsService.Caption := 'Suspended';
588 | lsService.Font.Color := clWindowText;
589 | end;
590 | end;
591 | if IsListenerWorking then begin
592 | lsListener.Caption := 'Listening';
593 | lsListener.Font.Color := clGreen;
594 | end else begin
595 | lsListener.Caption := 'Not listening';
596 | lsListener.Font.Color := clRed;
597 | end;
598 | if WrapperPath = '' then begin
599 | lsWrapVer.Caption := 'N/A';
600 | lsWrapVer.Font.Color := clGrayText;
601 | end else
602 | if not GetFileVersion(ExpandPath(WrapperPath), FV) then begin
603 | lsWrapVer.Caption := 'N/A';
604 | lsWrapVer.Font.Color := clGrayText;
605 | end else begin
606 | lsWrapVer.Caption :=
607 | IntToStr(FV.Version.w.Major)+'.'+
608 | IntToStr(FV.Version.w.Minor)+'.'+
609 | IntToStr(FV.Release)+'.'+
610 | IntToStr(FV.Build);
611 | lsWrapVer.Font.Color := clWindowText;
612 | end;
613 | if not GetFileVersion('termsrv.dll', FV) then begin
614 | lsTSVer.Caption := 'N/A';
615 | lsTSVer.Font.Color := clGrayText;
616 | end else begin
617 | lsTSVer.Caption :=
618 | IntToStr(FV.Version.w.Major)+'.'+
619 | IntToStr(FV.Version.w.Minor)+'.'+
620 | IntToStr(FV.Release)+'.'+
621 | IntToStr(FV.Build);
622 | lsTSVer.Font.Color := clWindowText;
623 | lsSuppVer.Visible := CheckSupp;
624 | if CheckSupp then begin
625 | if INI = '' then begin
626 | L := TStringList.Create;
627 | try
628 | L.LoadFromFile(INIPath);
629 | except
630 |
631 | end;
632 | INI := L.Text;
633 | L.Free;
634 | end;
635 | case CheckSupport(FV) of
636 | 0: begin
637 | lsSuppVer.Caption := '[not supported]';
638 | lsSuppVer.Font.Color := clRed;
639 | end;
640 | 1: begin
641 | lsSuppVer.Caption := '[supported partially]';
642 | lsSuppVer.Font.Color := clOlive;
643 | end;
644 | 2: begin
645 | lsSuppVer.Caption := '[fully supported]';
646 | lsSuppVer.Font.Color := clGreen;
647 | end;
648 | end;
649 | end;
650 | end;
651 | end;
652 |
653 | procedure TMainForm.bLicenseClick(Sender: TObject);
654 | begin
655 | LicenseForm.mText.Text := ExtractResText('LICENSE');
656 | if LicenseForm.ShowModal <> mrOk then
657 | Halt(0);
658 | end;
659 |
660 | procedure TMainForm.cbAllowTSConnectionsClick(Sender: TObject);
661 | begin
662 | if Ready then
663 | bApply.Enabled := True;
664 | end;
665 |
666 | procedure TMainForm.seRDPPortChange(Sender: TObject);
667 | begin
668 | if Ready then
669 | bApply.Enabled := True;
670 | end;
671 |
672 | procedure TMainForm.FormCreate(Sender: TObject);
673 | var
674 | SI: TSystemInfo;
675 | begin
676 | GetNativeSystemInfo(SI);
677 | case SI.wProcessorArchitecture of
678 | 0: Arch := 32;
679 | 6: Arch := 64; // Itanium-based x64
680 | 9: Arch := 64; // Intel/AMD x64
681 | else Arch := 0;
682 | end;
683 | if Arch = 64 then
684 | DisableWowRedirection;
685 | ReadSettings;
686 | Ready := True;
687 | end;
688 |
689 | procedure TMainForm.FormDestroy(Sender: TObject);
690 | begin
691 | if Arch = 64 then
692 | RevertWowRedirection;
693 | end;
694 |
695 | procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
696 | begin
697 | if bApply.Enabled then
698 | CanClose := MessageBox(Handle, 'Settings are not saved. Do you want to exit?',
699 | 'Warning', mb_IconWarning or mb_YesNo) = mrYes;
700 | end;
701 |
702 | procedure TMainForm.bOKClick(Sender: TObject);
703 | begin
704 | if bApply.Enabled then begin
705 | WriteSettings;
706 | bApply.Enabled := False;
707 | end;
708 | Close;
709 | end;
710 |
711 | procedure TMainForm.bCancelClick(Sender: TObject);
712 | begin
713 | Close;
714 | end;
715 |
716 | procedure TMainForm.bApplyClick(Sender: TObject);
717 | begin
718 | WriteSettings;
719 | bApply.Enabled := False;
720 | end;
721 |
722 | end.
723 |
--------------------------------------------------------------------------------
/src-rdpconfig/RDPConf.dpr:
--------------------------------------------------------------------------------
1 | {
2 | Copyright 2014 Stas'M Corp.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | }
16 |
17 | program RDPConf;
18 |
19 | uses
20 | Forms,
21 | MainUnit in 'MainUnit.pas' {MainForm},
22 | LicenseUnit in 'LicenseUnit.pas' {LicenseForm};
23 |
24 | {$R *.res}
25 |
26 | begin
27 | Application.Initialize;
28 | Application.MainFormOnTaskbar := True;
29 | Application.Title := 'Remote Desktop Protocol Configuration';
30 | Application.CreateForm(TMainForm, MainForm);
31 | Application.CreateForm(TLicenseForm, LicenseForm);
32 | Application.Run;
33 | end.
34 |
--------------------------------------------------------------------------------
/src-rdpconfig/RDPConf.dproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {A7CB4C30-85F5-4D96-B510-6F0CDCF7C2DA}
4 | 12.0
5 | RDPConf.dpr
6 | Debug
7 | DCC32
8 |
9 |
10 | true
11 |
12 |
13 | true
14 | Base
15 | true
16 |
17 |
18 | true
19 | Base
20 | true
21 |
22 |
23 | ..\bin\
24 | WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;$(DCC_UnitAlias)
25 | ..\bin\RDPConf.exe
26 | 00400000
27 | x86
28 |
29 |
30 | false
31 | RELEASE;$(DCC_Define)
32 | 0
33 | false
34 |
35 |
36 | DEBUG;$(DCC_Define)
37 |
38 |
39 |
40 | MainSource
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | Base
50 |
51 |
52 | Cfg_1
53 | Base
54 |
55 |
56 | Cfg_2
57 | Base
58 |
59 |
60 |
61 |
62 | Delphi.Personality.12
63 |
64 |
65 |
66 |
67 | RDPConf.dpr
68 |
69 |
70 | False
71 | True
72 | False
73 |
74 |
75 | False
76 | False
77 | 1
78 | 0
79 | 0
80 | 0
81 | False
82 | False
83 | False
84 | False
85 | False
86 | 1033
87 | 1252
88 |
89 |
90 | Stas'M Corp.
91 | RDP Configuration Program
92 | 1.0.0.0
93 | RDPConf
94 | Copyright © Stas'M Corp. 2014
95 | Stas'M Corp.
96 | RDPConf.exe
97 | RDP Host Support
98 | 1.4.0.0
99 | http://stascorp.com
100 |
101 |
102 | Embarcadero C++Builder Office 2000 Servers Package
103 | Embarcadero C++Builder Office XP Servers Package
104 | Microsoft Office 2000 Sample Automation Server Wrapper Components
105 | Microsoft Office XP Sample Automation Server Wrapper Components
106 |
107 |
108 |
109 | 12
110 |
111 |
112 |
--------------------------------------------------------------------------------
/src-rdpconfig/RDPConf.res:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/asmtron/rdpwrap/d973562ba338608de61fad22d41c82e0ef8f5494/src-rdpconfig/RDPConf.res
--------------------------------------------------------------------------------
/src-rdpconfig/resource.res:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/asmtron/rdpwrap/d973562ba338608de61fad22d41c82e0ef8f5494/src-rdpconfig/resource.res
--------------------------------------------------------------------------------
/src-x86-binarymaster/LiteINI.pas:
--------------------------------------------------------------------------------
1 | {
2 | Copyright 2014 Stas'M Corp.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | }
16 |
17 | unit LiteINI;
18 |
19 | interface
20 |
21 | uses
22 | SysUtils;
23 |
24 | type
25 | SList = Array of String;
26 | INIValue = record
27 | Name: String;
28 | Value: String;
29 | end;
30 | INISection = record
31 | Name: String;
32 | Values: Array of INIValue;
33 | end;
34 | INIFile = Array of INISection;
35 |
36 | procedure SListClear(var List: SList);
37 | function SListAppend(var List: SList; S: String): Integer;
38 | function SListFind(List: SList; Value: String): Integer;
39 | function INIFindSection(INI: INIFile; Section: String): Integer;
40 | function INIFindValue(INI: INIFile; Section: Integer; Value: String): Integer;
41 | function INIAddSection(var INI: INIFile; Section: String): Integer;
42 | function INIAddValue(var INI: INIFile; Section: Integer; ValueName, Value: String): Integer;
43 | procedure INIUnload(var INI: INIFile);
44 | procedure INILoad(var INI: INIFile; FileName: String);
45 | function INISectionExists(INI: INIFile; Section: String): Boolean;
46 | function INIValueExists(INI: INIFile; Section: String; Value: String): Boolean;
47 | function INIReadSectionLowAPI(INI: INIFile; Section: Integer; var List: SList): Boolean;
48 | function INIReadSection(INI: INIFile; Section: String): SList;
49 | function INIReadStringLowAPI(INI: INIFile; Section, Value: Integer; var Str: String): Boolean;
50 | function INIReadString(INI: INIFile; Section, Value, Default: String): String;
51 | function INIReadInt(INI: INIFile; Section, Value: String; Default: Integer): Integer;
52 | function INIReadDWord(INI: INIFile; Section, Value: String; Default: Cardinal): Cardinal;
53 | function INIReadIntHex(INI: INIFile; Section, Value: String; Default: Integer): Integer;
54 | function INIReadDWordHex(INI: INIFile; Section, Value: String; Default: Cardinal): Cardinal;
55 | function INIReadBool(INI: INIFile; Section, Value: String; Default: Boolean): Boolean;
56 | function INIReadBytes(INI: INIFile; Section, Value: String): TBytes;
57 | function INIReadBytesDef(INI: INIFile; Section, Value: String; Default: TBytes): TBytes;
58 |
59 | implementation
60 |
61 | procedure SListClear(var List: SList);
62 | begin
63 | SetLength(List, 0);
64 | end;
65 |
66 | function SListAppend(var List: SList; S: String): Integer;
67 | begin
68 | SetLength(List, Length(List) + 1);
69 | List[Length(List) - 1] := S;
70 | Result := Length(List) - 1;
71 | end;
72 |
73 | function SListFind(List: SList; Value: String): Integer;
74 | var
75 | I: Integer;
76 | begin
77 | Result := -1;
78 | for I := 0 to Length(List) - 1 do
79 | if List[I] = Value then begin
80 | Result := I;
81 | Break;
82 | end;
83 | end;
84 |
85 | function INIFindSection(INI: INIFile; Section: String): Integer;
86 | var
87 | I: Integer;
88 | begin
89 | Result := -1;
90 | for I := 0 to Length(INI) - 1 do
91 | if INI[I].Name = Section then begin
92 | Result := I;
93 | Exit;
94 | end;
95 | end;
96 |
97 | function INIFindValue(INI: INIFile; Section: Integer; Value: String): Integer;
98 | var
99 | I: Integer;
100 | begin
101 | Result := -1;
102 | if (Section < 0) or (Section >= Length(INI)) then
103 | Exit;
104 | for I := 0 to Length(INI[Section].Values) - 1 do
105 | if INI[Section].Values[I].Name = Value then begin
106 | Result := I;
107 | Exit;
108 | end;
109 | end;
110 |
111 | function INIAddSection(var INI: INIFile; Section: String): Integer;
112 | begin
113 | Result := INIFindSection(INI, Section);
114 | if Result >= 0 then
115 | Exit;
116 | Result := Length(INI);
117 | SetLength(INI, Result + 1);
118 | INI[Result].Name := Section;
119 | SetLength(INI[Result].Values, 0);
120 | end;
121 |
122 | function INIAddValue(var INI: INIFile; Section: Integer; ValueName, Value: String): Integer;
123 | var
124 | I: Integer;
125 | begin
126 | Result := -1;
127 | if (Section < 0) or (Section >= Length(INI)) then
128 | Exit;
129 | I := INIFindValue(INI, Section, ValueName);
130 | if I = -1 then begin
131 | Result := Length(INI[Section].Values);
132 | SetLength(INI[Section].Values, Result + 1);
133 | INI[Section].Values[Result].Name := ValueName;
134 | INI[Section].Values[Result].Value := Value;
135 | end else begin
136 | INI[Section].Values[I].Value := Value;
137 | Result := I;
138 | end;
139 | end;
140 |
141 | procedure INIUnload(var INI: INIFile);
142 | begin
143 | SetLength(INI, 0);
144 | end;
145 |
146 | procedure INILoad(var INI: INIFile; FileName: String);
147 | var
148 | F: TextFile;
149 | S, ValueName, Value: String;
150 | INIList: SList;
151 | I, Sect: Integer;
152 | begin
153 | INIUnload(INI);
154 | if not FileExists(FileName) then
155 | Exit;
156 | AssignFile(F, FileName);
157 | Reset(F);
158 | // Read and filter lines
159 | while not EOF(F) do begin
160 | Readln(F, S);
161 | if (Pos(';', S) <> 1)
162 | and (Pos('#', S) <> 1)
163 | and (
164 | ((Pos('[', S) > 0) and (Pos(']', S) > 0)) or
165 | (Pos('=', S) > 0)
166 | )
167 | then
168 | SListAppend(INIList, S);
169 | end;
170 | CloseFile(F);
171 | // Parse 2 (parse format)
172 | Sect := -1;
173 | for I := 0 to Length(INIList) - 1 do begin
174 | S := Trim(INIList[I]);
175 | if Length(S) >= 2 then
176 | if (S[1] = '[') and (S[Length(S)] = ']') then begin
177 | S := Trim(Copy(S, 2, Length(S) - 2));
178 | Sect := INIAddSection(INI, S);
179 | Continue;
180 | end;
181 | S := INIList[I];
182 | if Pos('=', S) > 0 then begin
183 | ValueName := Trim(Copy(S, 1, Pos('=', S) - 1));
184 | Value := Copy(S, Pos('=', S) + 1, Length(S) - Pos('=', S));
185 | if Sect = -1 then
186 | Sect := INIAddSection(INI, '');
187 | INIAddValue(INI, Sect, ValueName, Value);
188 | end;
189 | end;
190 | end;
191 |
192 | function INISectionExists(INI: INIFile; Section: String): Boolean;
193 | begin
194 | Result := INIFindSection(INI, Section) > -1;
195 | end;
196 |
197 | function INIValueExists(INI: INIFile; Section: String; Value: String): Boolean;
198 | var
199 | Sect: Integer;
200 | begin
201 | Sect := INIFindSection(INI, Section);
202 | Result := INIFindValue(INI, Sect, Value) > -1;
203 | end;
204 |
205 | function INIReadSectionLowAPI(INI: INIFile; Section: Integer; var List: SList): Boolean;
206 | var
207 | I: Integer;
208 | begin
209 | Result := False;
210 | SetLength(List, 0);
211 | if (Section < 0) or (Section >= Length(INI)) then
212 | Exit;
213 | for I := 0 to Length(INI[Section].Values) - 1 do
214 | SListAppend(List, INI[Section].Values[I].Name);
215 | Result := True;
216 | end;
217 |
218 | function INIReadSection(INI: INIFile; Section: String): SList;
219 | var
220 | Sect: Integer;
221 | begin
222 | Sect := INIFindSection(INI, Section);
223 | INIReadSectionLowAPI(INI, Sect, Result);
224 | end;
225 |
226 | function INIReadStringLowAPI(INI: INIFile; Section, Value: Integer; var Str: String): Boolean;
227 | begin
228 | Result := False;
229 | if (Section < 0) or (Section >= Length(INI)) then
230 | Exit;
231 | if (Value < 0) or (Value >= Length(INI[Section].Values)) then
232 | Exit;
233 | Str := INI[Section].Values[Value].Value;
234 | Result := True;
235 | end;
236 |
237 | function INIReadString(INI: INIFile; Section, Value, Default: String): String;
238 | var
239 | Sect, Val: Integer;
240 | begin
241 | Sect := INIFindSection(INI, Section);
242 | Val := INIFindValue(INI, Sect, Value);
243 | if not INIReadStringLowAPI(INI, Sect, Val, Result) then
244 | Result := Default;
245 | end;
246 |
247 | function INIReadInt(INI: INIFile; Section, Value: String; Default: Integer): Integer;
248 | var
249 | S: String;
250 | E: Integer;
251 | begin
252 | S := INIReadString(INI, Section, Value, '');
253 | Val(S, Result, E);
254 | if E <> 0 then
255 | Result := Default;
256 | end;
257 |
258 | function INIReadDWord(INI: INIFile; Section, Value: String; Default: Cardinal): Cardinal;
259 | var
260 | S: String;
261 | E: Integer;
262 | begin
263 | S := INIReadString(INI, Section, Value, '');
264 | Val(S, Result, E);
265 | if E <> 0 then
266 | Result := Default;
267 | end;
268 |
269 | function INIReadIntHex(INI: INIFile; Section, Value: String; Default: Integer): Integer;
270 | var
271 | S: String;
272 | E: Integer;
273 | begin
274 | S := INIReadString(INI, Section, Value, '');
275 | Val('$'+S, Result, E);
276 | if E <> 0 then
277 | Result := Default;
278 | end;
279 |
280 | function INIReadDWordHex(INI: INIFile; Section, Value: String; Default: Cardinal): Cardinal;
281 | var
282 | S: String;
283 | E: Integer;
284 | begin
285 | S := INIReadString(INI, Section, Value, '');
286 | Val('$'+S, Result, E);
287 | if E <> 0 then
288 | Result := Default;
289 | end;
290 |
291 | function INIReadBool(INI: INIFile; Section, Value: String; Default: Boolean): Boolean;
292 | var
293 | S: String;
294 | I: Cardinal;
295 | E: Integer;
296 | begin
297 | S := INIReadString(INI, Section, Value, '');
298 | Val(S, I, E);
299 | if E <> 0 then
300 | Result := Default
301 | else
302 | Result := I > 0;
303 | end;
304 |
305 | function StringToBytes(S: String; var B: TBytes): Boolean;
306 | var
307 | I: Integer;
308 | begin
309 | Result := False;
310 | if Odd(Length(S)) then
311 | Exit;
312 | SetLength(B, Length(S) div 2);
313 | for I := 0 to Length(B) - 1 do begin
314 | B[I] := 0;
315 | case S[(I*2)+2] of
316 | '0': ;
317 | '1': B[I] := B[I] or $1;
318 | '2': B[I] := B[I] or $2;
319 | '3': B[I] := B[I] or $3;
320 | '4': B[I] := B[I] or $4;
321 | '5': B[I] := B[I] or $5;
322 | '6': B[I] := B[I] or $6;
323 | '7': B[I] := B[I] or $7;
324 | '8': B[I] := B[I] or $8;
325 | '9': B[I] := B[I] or $9;
326 | 'A','a': B[I] := B[I] or $A;
327 | 'B','b': B[I] := B[I] or $B;
328 | 'C','c': B[I] := B[I] or $C;
329 | 'D','d': B[I] := B[I] or $D;
330 | 'E','e': B[I] := B[I] or $E;
331 | 'F','f': B[I] := B[I] or $F;
332 | else Exit;
333 | end;
334 | case S[(I*2)+1] of
335 | '0': ;
336 | '1': B[I] := B[I] or $10;
337 | '2': B[I] := B[I] or $20;
338 | '3': B[I] := B[I] or $30;
339 | '4': B[I] := B[I] or $40;
340 | '5': B[I] := B[I] or $50;
341 | '6': B[I] := B[I] or $60;
342 | '7': B[I] := B[I] or $70;
343 | '8': B[I] := B[I] or $80;
344 | '9': B[I] := B[I] or $90;
345 | 'A','a': B[I] := B[I] or $A0;
346 | 'B','b': B[I] := B[I] or $B0;
347 | 'C','c': B[I] := B[I] or $C0;
348 | 'D','d': B[I] := B[I] or $D0;
349 | 'E','e': B[I] := B[I] or $E0;
350 | 'F','f': B[I] := B[I] or $F0;
351 | else Exit;
352 | end;
353 | end;
354 | Result := True;
355 | end;
356 |
357 | function INIReadBytes(INI: INIFile; Section, Value: String): TBytes;
358 | var
359 | S: String;
360 | begin
361 | S := INIReadString(INI, Section, Value, '');
362 | if not StringToBytes(S, Result) then
363 | SetLength(Result, 0);
364 | end;
365 |
366 | function INIReadBytesDef(INI: INIFile; Section, Value: String; Default: TBytes): TBytes;
367 | var
368 | S: String;
369 | begin
370 | S := INIReadString(INI, Section, Value, '');
371 | if not StringToBytes(S, Result) then
372 | Result := Default;
373 | end;
374 |
375 | end.
376 |
--------------------------------------------------------------------------------
/src-x86-binarymaster/rdpwrap.dpr:
--------------------------------------------------------------------------------
1 | {
2 | Copyright 2014 Stas'M Corp.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | }
16 |
17 | library rdpwrap;
18 |
19 | uses
20 | SysUtils,
21 | Windows,
22 | TlHelp32,
23 | LiteINI;
24 |
25 | {$R rdpwrap.res}
26 |
27 | // Hook core definitions
28 |
29 | type
30 | OldCode = packed record
31 | One: DWORD;
32 | two: Word;
33 | end;
34 |
35 | far_jmp = packed record
36 | PushOp: Byte;
37 | PushArg: Pointer;
38 | RetOp: Byte;
39 | end;
40 |
41 | mov_far_jmp = packed record
42 | MovOp: Byte;
43 | MovArg: Byte;
44 | PushOp: Byte;
45 | PushArg: Pointer;
46 | RetOp: Byte;
47 | end;
48 |
49 | TTHREADENTRY32 = packed record
50 | dwSize: DWORD;
51 | cntUsage: DWORD;
52 | th32ThreadID: DWORD;
53 | th32OwnerProcessID: DWORD;
54 | tpBasePri: LongInt;
55 | tpDeltaPri: LongInt;
56 | dwFlags: DWORD;
57 | end;
58 | //IntArray = Array of Integer;
59 | FILE_VERSION = record
60 | Version: record case Boolean of
61 | True: (dw: DWORD);
62 | False: (w: record
63 | Minor, Major: Word;
64 | end;)
65 | end;
66 | Release, Build: Word;
67 | bDebug, bPrerelease, bPrivate, bSpecial: Boolean;
68 | end;
69 |
70 | const
71 | THREAD_SUSPEND_RESUME = 2;
72 | TH32CS_SNAPTHREAD = 4;
73 | var
74 | INI: INIFile;
75 | LogFile: String = '\rdpwrap.txt';
76 | bw: {$if CompilerVersion>=16} NativeUInt {$else} DWORD {$endif};
77 | IsHooked: Boolean = False;
78 |
79 | // Unhooked import
80 |
81 | function OpenThread(dwDesiredAccess: DWORD; bInheritHandle: BOOL;
82 | dwThreadId: DWORD): DWORD; stdcall; external kernel32;
83 |
84 | function CreateToolhelp32Snapshot(dwFlags, th32ProcessID: DWORD): DWORD;
85 | stdcall; external kernel32;
86 |
87 | function Thread32First(hSnapshot: THandle; var lpte: TTHREADENTRY32): bool;
88 | stdcall; external kernel32;
89 |
90 | function Thread32Next(hSnapshot: THandle; var lpte: TTHREADENTRY32): bool;
91 | stdcall; external kernel32;
92 |
93 | // Wrapped import
94 |
95 | var
96 | TSMain: function(dwArgc: DWORD; lpszArgv: PWideChar): DWORD; stdcall;
97 | TSGlobals: function(lpGlobalData: Pointer): DWORD; stdcall;
98 |
99 | // Hooked import and vars
100 |
101 | var
102 | SLGetWindowsInformationDWORD: function(pwszValueName: PWideChar;
103 | pdwValue: PDWORD): HRESULT; stdcall;
104 | TermSrvBase: Pointer;
105 | FV: FILE_VERSION;
106 |
107 | var
108 | Stub_SLGetWindowsInformationDWORD: far_jmp;
109 | Old_SLGetWindowsInformationDWORD: OldCode;
110 |
111 | // Main code
112 |
113 | procedure WriteLog(S: AnsiString);
114 | var
115 | F: TextFile;
116 | begin
117 | if not FileExists(LogFile) then
118 | Exit;
119 | AssignFile(F, LogFile);
120 | Append(F);
121 | Write(F, S+#13#10);
122 | CloseFile(F);
123 | end;
124 |
125 | function GetModuleHandleEx(dwFlags: DWORD; lpModuleName: PWideChar;
126 | var phModule: HMODULE): BOOL; stdcall; external kernel32 name 'GetModuleHandleExW';
127 |
128 | function GetCurrentModule: HMODULE;
129 | const
130 | GET_MODULE_HANDLE_EX_FLAG_PIN = 1;
131 | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT = 2;
132 | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS = 4;
133 | begin
134 | Result := 0;
135 | GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, @GetCurrentModule, Result);
136 | end;
137 |
138 | function GetBinaryPath: String;
139 | var
140 | Buf: Array[0..511] of Byte;
141 | begin
142 | ZeroMemory(@Buf[0], Length(Buf));
143 | GetModuleFileName(GetCurrentModule, PWideChar(@Buf[0]), Length(Buf));
144 | Result := PWideChar(@Buf[0]);
145 | end;
146 |
147 | procedure StopThreads;
148 | var
149 | h, CurrTh, ThrHandle, CurrPr: DWORD;
150 | Thread: TTHREADENTRY32;
151 | begin
152 | CurrTh := GetCurrentThreadId;
153 | CurrPr := GetCurrentProcessId;
154 | h := CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
155 | if h <> INVALID_HANDLE_VALUE then
156 | begin
157 | Thread.dwSize := SizeOf(TTHREADENTRY32);
158 | if Thread32First(h, Thread) then
159 | repeat
160 | if (Thread.th32ThreadID <> CurrTh) and
161 | (Thread.th32OwnerProcessID = CurrPr) then
162 | begin
163 | ThrHandle := OpenThread(THREAD_SUSPEND_RESUME, false,
164 | Thread.th32ThreadID);
165 | if ThrHandle > 0 then
166 | begin
167 | SuspendThread(ThrHandle);
168 | CloseHandle(ThrHandle);
169 | end;
170 | end;
171 | until not Thread32Next(h, Thread);
172 | CloseHandle(h);
173 | end;
174 | end;
175 |
176 | procedure RunThreads;
177 | var
178 | h, CurrTh, ThrHandle, CurrPr: DWORD;
179 | Thread: TTHREADENTRY32;
180 | begin
181 | CurrTh := GetCurrentThreadId;
182 | CurrPr := GetCurrentProcessId;
183 | h := CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
184 | if h <> INVALID_HANDLE_VALUE then
185 | begin
186 | Thread.dwSize := SizeOf(TTHREADENTRY32);
187 | if Thread32First(h, Thread) then
188 | repeat
189 | if (Thread.th32ThreadID <> CurrTh) and
190 | (Thread.th32OwnerProcessID = CurrPr) then
191 | begin
192 | ThrHandle := OpenThread(THREAD_SUSPEND_RESUME, false,
193 | Thread.th32ThreadID);
194 | if ThrHandle > 0 then
195 | begin
196 | ResumeThread(ThrHandle);
197 | CloseHandle(ThrHandle);
198 | end;
199 | end;
200 | until not Thread32Next(h, Thread);
201 | CloseHandle(h);
202 | end;
203 | end;
204 |
205 | function GetModuleAddress(ModuleName: String; ProcessId: DWORD; var BaseAddr: Pointer; var BaseSize: DWORD): Boolean;
206 | var
207 | hSnap: THandle;
208 | md: MODULEENTRY32;
209 | begin
210 | Result := False;
211 | hSnap := CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, ProcessId);
212 | if hSnap = INVALID_HANDLE_VALUE Then
213 | Exit;
214 | md.dwSize := SizeOf(MODULEENTRY32);
215 | if Module32First(hSnap, md) then
216 | begin
217 | if LowerCase(ExtractFileName(md.szExePath)) = LowerCase(ModuleName) then
218 | begin
219 | Result := True;
220 | BaseAddr := Pointer(md.modBaseAddr);
221 | BaseSize := md.modBaseSize;
222 | CloseHandle(hSnap);
223 | Exit;
224 | end;
225 | while Module32Next(hSnap, md) Do
226 | begin
227 | if LowerCase(ExtractFileName(md.szExePath)) = LowerCase(ModuleName) then
228 | begin
229 | Result := True;
230 | BaseAddr := Pointer(md.modBaseAddr);
231 | BaseSize := md.modBaseSize;
232 | Break;
233 | end;
234 | end;
235 | end;
236 | CloseHandle(hSnap);
237 | end;
238 |
239 | {procedure FindMem(Mem: Pointer; MemSz: DWORD; Buf: Pointer; BufSz: DWORD;
240 | From: DWORD; var A: IntArray);
241 | var
242 | I: Integer;
243 | begin
244 | SetLength(A, 0);
245 | I:=From;
246 | if From>0 then
247 | Inc(PByte(Mem), From);
248 | while I < MemSz - BufSz + 1 do
249 | begin
250 | if (not IsBadReadPtr(Mem, BufSz)) and (CompareMem(Mem, Buf, BufSz)) then
251 | begin
252 | SetLength(A, Length(A)+1);
253 | A[Length(A)-1] := I;
254 | end;
255 | Inc(I);
256 | Inc(PByte(Mem));
257 | end;
258 | end;}
259 |
260 | function GetModuleVersion(const ModuleName: String; var FileVersion: FILE_VERSION): Boolean;
261 | type
262 | VS_VERSIONINFO = record
263 | wLength, wValueLength, wType: Word;
264 | szKey: Array[1..16] of WideChar;
265 | Padding1: Word;
266 | Value: VS_FIXEDFILEINFO;
267 | Padding2, Children: Word;
268 | end;
269 | PVS_VERSIONINFO = ^VS_VERSIONINFO;
270 | const
271 | VFF_DEBUG = 1;
272 | VFF_PRERELEASE = 2;
273 | VFF_PRIVATE = 8;
274 | VFF_SPECIAL = 32;
275 | var
276 | hMod: HMODULE;
277 | hResourceInfo: HRSRC;
278 | VersionInfo: PVS_VERSIONINFO;
279 | begin
280 | Result := False;
281 |
282 | if ModuleName = '' then
283 | hMod := GetModuleHandle(nil)
284 | else
285 | hMod := GetModuleHandle(PWideChar(ModuleName));
286 | if hMod = 0 then
287 | Exit;
288 |
289 | hResourceInfo := FindResource(hMod, PWideChar(1), PWideChar($10));
290 | if hResourceInfo = 0 then
291 | Exit;
292 |
293 | VersionInfo := Pointer(LoadResource(hMod, hResourceInfo));
294 | if VersionInfo = nil then
295 | Exit;
296 |
297 | FileVersion.Version.dw := VersionInfo.Value.dwFileVersionMS;
298 | FileVersion.Release := Word(VersionInfo.Value.dwFileVersionLS shr 16);
299 | FileVersion.Build := Word(VersionInfo.Value.dwFileVersionLS);
300 | FileVersion.bDebug := (VersionInfo.Value.dwFileFlags and VFF_DEBUG) = VFF_DEBUG;
301 | FileVersion.bPrerelease := (VersionInfo.Value.dwFileFlags and VFF_PRERELEASE) = VFF_PRERELEASE;
302 | FileVersion.bPrivate := (VersionInfo.Value.dwFileFlags and VFF_PRIVATE) = VFF_PRIVATE;
303 | FileVersion.bSpecial := (VersionInfo.Value.dwFileFlags and VFF_SPECIAL) = VFF_SPECIAL;
304 |
305 | Result := True;
306 | end;
307 |
308 | function GetFileVersion(const FileName: String; var FileVersion: FILE_VERSION): Boolean;
309 | type
310 | VS_VERSIONINFO = record
311 | wLength, wValueLength, wType: Word;
312 | szKey: Array[1..16] of WideChar;
313 | Padding1: Word;
314 | Value: VS_FIXEDFILEINFO;
315 | Padding2, Children: Word;
316 | end;
317 | PVS_VERSIONINFO = ^VS_VERSIONINFO;
318 | const
319 | VFF_DEBUG = 1;
320 | VFF_PRERELEASE = 2;
321 | VFF_PRIVATE = 8;
322 | VFF_SPECIAL = 32;
323 | var
324 | hFile: HMODULE;
325 | hResourceInfo: HRSRC;
326 | VersionInfo: PVS_VERSIONINFO;
327 | begin
328 | Result := False;
329 |
330 | hFile := LoadLibraryEx(PWideChar(FileName), 0, LOAD_LIBRARY_AS_DATAFILE);
331 | if hFile = 0 then
332 | Exit;
333 |
334 | hResourceInfo := FindResource(hFile, PWideChar(1), PWideChar($10));
335 | if hResourceInfo = 0 then
336 | Exit;
337 |
338 | VersionInfo := Pointer(LoadResource(hFile, hResourceInfo));
339 | if VersionInfo = nil then
340 | Exit;
341 |
342 | FileVersion.Version.dw := VersionInfo.Value.dwFileVersionMS;
343 | FileVersion.Release := Word(VersionInfo.Value.dwFileVersionLS shr 16);
344 | FileVersion.Build := Word(VersionInfo.Value.dwFileVersionLS);
345 | FileVersion.bDebug := (VersionInfo.Value.dwFileFlags and VFF_DEBUG) = VFF_DEBUG;
346 | FileVersion.bPrerelease := (VersionInfo.Value.dwFileFlags and VFF_PRERELEASE) = VFF_PRERELEASE;
347 | FileVersion.bPrivate := (VersionInfo.Value.dwFileFlags and VFF_PRIVATE) = VFF_PRIVATE;
348 | FileVersion.bSpecial := (VersionInfo.Value.dwFileFlags and VFF_SPECIAL) = VFF_SPECIAL;
349 |
350 | Result := True;
351 | end;
352 |
353 | function OverrideSL(ValueName: String; var Value: DWORD): Boolean;
354 | begin
355 | Result := True;
356 | if INIValueExists(INI, 'SLPolicy', ValueName) then begin
357 | Value := INIReadDWord(INI, 'SLPolicy', ValueName, 0);
358 | Exit;
359 | end;
360 | Result := False;
361 | end;
362 |
363 | function New_SLGetWindowsInformationDWORD(pwszValueName: PWideChar;
364 | pdwValue: PDWORD): HRESULT; stdcall;
365 | var
366 | dw: DWORD;
367 | begin
368 | // wrapped SLGetWindowsInformationDWORD function
369 | // termsrv.dll will call this function instead of original SLC.dll
370 |
371 | // Override SL Policy
372 |
373 | WriteLog('Policy query: ' + pwszValueName);
374 | if OverrideSL(pwszValueName, dw) then begin
375 | pdwValue^ := dw;
376 | Result := S_OK;
377 | WriteLog('Policy rewrite: ' + IntToStr(pdwValue^));
378 | Exit;
379 | end;
380 |
381 | // If the requested value name is not defined above
382 |
383 | // revert to original SL Policy function
384 | WriteProcessMemory(GetCurrentProcess, @SLGetWindowsInformationDWORD,
385 | @Old_SLGetWindowsInformationDWORD, SizeOf(OldCode), bw);
386 |
387 | // get result
388 | Result := SLGetWindowsInformationDWORD(pwszValueName, pdwValue);
389 | if Result = S_OK then
390 | WriteLog('Policy result: ' + IntToStr(pdwValue^))
391 | else
392 | WriteLog('Policy request failed');
393 | // wrap it back
394 | WriteProcessMemory(GetCurrentProcess, @SLGetWindowsInformationDWORD,
395 | @Stub_SLGetWindowsInformationDWORD, SizeOf(far_jmp), bw);
396 | end;
397 |
398 | function New_Win8SL(pwszValueName: PWideChar; pdwValue: PDWORD): HRESULT; register;
399 | var
400 | dw: DWORD;
401 | begin
402 | // wrapped unexported function SLGetWindowsInformationDWORDWrapper in termsrv.dll
403 | // for Windows 8 support
404 |
405 | // Override SL Policy
406 |
407 | WriteLog('Policy query: ' + pwszValueName);
408 | if OverrideSL(pwszValueName, dw) then begin
409 | pdwValue^ := dw;
410 | Result := S_OK;
411 | WriteLog('Policy rewrite: ' + IntToStr(pdwValue^));
412 | Exit;
413 | end;
414 |
415 | // If the requested value name is not defined above
416 | // use function from SLC.dll
417 |
418 | Result := SLGetWindowsInformationDWORD(pwszValueName, pdwValue);
419 | if Result = S_OK then
420 | WriteLog('Policy result: ' + IntToStr(pdwValue^))
421 | else
422 | WriteLog('Policy request failed');
423 | end;
424 |
425 | function New_Win8SL_CP(eax: DWORD; pdwValue: PDWORD; ecx: DWORD; pwszValueName: PWideChar): HRESULT; register;
426 | begin
427 | // wrapped unexported function SLGetWindowsInformationDWORDWrapper in termsrv.dll
428 | // for Windows 8 Consumer Preview support
429 |
430 | Result := New_Win8SL(pwszValueName, pdwValue);
431 | end;
432 |
433 | function New_CSLQuery_Initialize: HRESULT; stdcall;
434 | var
435 | Sect: String;
436 | bServerSku,
437 | bRemoteConnAllowed,
438 | bFUSEnabled,
439 | bAppServerAllowed,
440 | bMultimonAllowed,
441 | lMaxUserSessions,
442 | ulMaxDebugSessions,
443 | bInitialized: PDWORD;
444 | begin
445 | bServerSku := nil;
446 | bRemoteConnAllowed := nil;
447 | bFUSEnabled := nil;
448 | bAppServerAllowed := nil;
449 | bMultimonAllowed := nil;
450 | lMaxUserSessions := nil;
451 | ulMaxDebugSessions := nil;
452 | bInitialized := nil;
453 | WriteLog('>>> CSLQuery::Initialize');
454 | Sect := IntToStr(FV.Version.w.Major)+'.'+IntToStr(FV.Version.w.Minor)+'.'+
455 | IntToStr(FV.Release)+'.'+IntToStr(FV.Build)+'-SLInit';
456 | if INISectionExists(INI, Sect) then begin
457 | bServerSku := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'bServerSku.x86', 0));
458 | bRemoteConnAllowed := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'bRemoteConnAllowed.x86', 0));
459 | bFUSEnabled := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'bFUSEnabled.x86', 0));
460 | bAppServerAllowed := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'bAppServerAllowed.x86', 0));
461 | bMultimonAllowed := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'bMultimonAllowed.x86', 0));
462 | lMaxUserSessions := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'lMaxUserSessions.x86', 0));
463 | ulMaxDebugSessions := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'ulMaxDebugSessions.x86', 0));
464 | bInitialized := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'bInitialized.x86', 0));
465 | end;
466 |
467 | if bServerSku <> nil then begin
468 | bServerSku^ := INIReadDWord(INI, 'SLInit', 'bServerSku', 1);
469 | WriteLog('SLInit [0x'+IntToHex(DWORD(bServerSku), 1)+'] bServerSku = ' + IntToStr(bServerSku^));
470 | end;
471 | if bRemoteConnAllowed <> nil then begin
472 | bRemoteConnAllowed^ := INIReadDWord(INI, 'SLInit', 'bRemoteConnAllowed', 1);
473 | WriteLog('SLInit [0x'+IntToHex(DWORD(bRemoteConnAllowed), 1)+'] bRemoteConnAllowed = ' + IntToStr(bRemoteConnAllowed^));
474 | end;
475 | if bFUSEnabled <> nil then begin
476 | bFUSEnabled^ := INIReadDWord(INI, 'SLInit', 'bFUSEnabled', 1);
477 | WriteLog('SLInit [0x'+IntToHex(DWORD(bFUSEnabled), 1)+'] bFUSEnabled = ' + IntToStr(bFUSEnabled^));
478 | end;
479 | if bAppServerAllowed <> nil then begin
480 | bAppServerAllowed^ := INIReadDWord(INI, 'SLInit', 'bAppServerAllowed', 1);
481 | WriteLog('SLInit [0x'+IntToHex(DWORD(bAppServerAllowed), 1)+'] bAppServerAllowed = ' + IntToStr(bAppServerAllowed^));
482 | end;
483 | if bMultimonAllowed <> nil then begin
484 | bMultimonAllowed^ := INIReadDWord(INI, 'SLInit', 'bMultimonAllowed', 1);
485 | WriteLog('SLInit [0x'+IntToHex(DWORD(bMultimonAllowed), 1)+'] bMultimonAllowed = ' + IntToStr(bMultimonAllowed^));
486 | end;
487 | if lMaxUserSessions <> nil then begin
488 | lMaxUserSessions^ := INIReadDWord(INI, 'SLInit', 'lMaxUserSessions', 0);
489 | WriteLog('SLInit [0x'+IntToHex(DWORD(lMaxUserSessions), 1)+'] lMaxUserSessions = ' + IntToStr(lMaxUserSessions^));
490 | end;
491 | if ulMaxDebugSessions <> nil then begin
492 | ulMaxDebugSessions^ := INIReadDWord(INI, 'SLInit', 'ulMaxDebugSessions', 0);
493 | WriteLog('SLInit [0x'+IntToHex(DWORD(ulMaxDebugSessions), 1)+'] ulMaxDebugSessions = ' + IntToStr(ulMaxDebugSessions^));
494 | end;
495 | if bInitialized <> nil then begin
496 | bInitialized^ := INIReadDWord(INI, 'SLInit', 'bInitialized', 1);
497 | WriteLog('SLInit [0x'+IntToHex(DWORD(bInitialized), 1)+'] bInitialized = ' + IntToStr(bInitialized^));
498 | end;
499 | Result := S_OK;
500 | WriteLog('<<< CSLQuery::Initialize');
501 | end;
502 |
503 | procedure HookFunctions;
504 | var
505 | ConfigFile, Sect, FuncName: String;
506 | V: DWORD;
507 | TS_Handle, SLC_Handle: THandle;
508 | TermSrvSize: DWORD;
509 | SignPtr: Pointer;
510 | I: Integer;
511 | PatchList: SList;
512 | Patch: Array of TBytes;
513 | Jump: far_jmp;
514 | MovJump: mov_far_jmp;
515 | begin
516 | { hook function ^^
517 | (called once) }
518 | IsHooked := True;
519 | TSMain := nil;
520 | TSGlobals := nil;
521 | SLGetWindowsInformationDWORD := nil;
522 |
523 | WriteLog('Loading configuration...');
524 | ConfigFile := ExtractFilePath(GetBinaryPath) + 'rdpwrap.ini';
525 | WriteLog('Configuration file: ' + ConfigFile);
526 | INILoad(INI, ConfigFile);
527 | if Length(INI) = 0 then begin
528 | WriteLog('Error: Failed to load configuration');
529 | Exit;
530 | end;
531 |
532 | LogFile := INIReadString(INI, 'Main', 'LogFile', ExtractFilePath(GetBinaryPath) + 'rdpwrap.txt');
533 | WriteLog('Initializing RDP Wrapper...');
534 |
535 | // load termsrv.dll and get functions
536 | TS_Handle := LoadLibrary('termsrv.dll');
537 | if TS_Handle = 0 then begin
538 | WriteLog('Error: Failed to load Terminal Services library');
539 | Exit;
540 | end;
541 | TSMain := GetProcAddress(TS_Handle, 'ServiceMain');
542 | TSGlobals := GetProcAddress(TS_Handle, 'SvchostPushServiceGlobals');
543 | WriteLog(
544 | 'Base addr: 0x' + IntToHex(TS_Handle, 8) + #13#10 +
545 | 'SvcMain: termsrv.dll+0x' + IntToHex(Cardinal(@TSMain) - TS_Handle, 1) + #13#10 +
546 | 'SvcGlobals: termsrv.dll+0x' + IntToHex(Cardinal(@TSGlobals) - TS_Handle, 1)
547 | );
548 |
549 | V := 0;
550 | // check termsrv version
551 | if GetModuleVersion('termsrv.dll', FV) then
552 | V := Byte(FV.Version.w.Minor) or (Byte(FV.Version.w.Major) shl 8)
553 | else begin
554 | // check NT version
555 | // V := GetVersion; // deprecated
556 | // V := ((V and $FF) shl 8) or ((V and $FF00) shr 8);
557 | end;
558 | if V = 0 then begin
559 | WriteLog('Error: Failed to detect Terminal Services version');
560 | Exit;
561 | end;
562 |
563 | WriteLog('Version: '+
564 | IntToStr(FV.Version.w.Major)+'.'+
565 | IntToStr(FV.Version.w.Minor)+'.'+
566 | IntToStr(FV.Release)+'.'+
567 | IntToStr(FV.Build));
568 |
569 | // temporarily freeze threads
570 | WriteLog('Freezing threads...');
571 | StopThreads();
572 |
573 | WriteLog('Caching patch codes...');
574 | PatchList := INIReadSection(INI, 'PatchCodes');
575 | SetLength(Patch, Length(PatchList));
576 | for I := 0 to Length(Patch) - 1 do begin
577 | Patch[I] := INIReadBytes(INI, 'PatchCodes', PatchList[I]);
578 | if Length(Patch[I]) > 16 then // for security reasons
579 | SetLength(Patch[I], 16); // not more than 16 bytes
580 | end;
581 |
582 | if (V = $0600) and (INIReadBool(INI, 'Main', 'SLPolicyHookNT60', True)) then begin
583 | // Windows Vista
584 | // uses SL Policy API (slc.dll)
585 |
586 | // load slc.dll and hook function
587 | SLC_Handle := LoadLibrary('slc.dll');
588 | SLGetWindowsInformationDWORD := GetProcAddress(SLC_Handle, 'SLGetWindowsInformationDWORD');
589 |
590 | if @SLGetWindowsInformationDWORD <> nil then
591 | begin
592 | // rewrite original function to call our function (make hook)
593 |
594 | WriteLog('Hook SLGetWindowsInformationDWORD');
595 | Stub_SLGetWindowsInformationDWORD.PushOp := $68;
596 | Stub_SLGetWindowsInformationDWORD.PushArg := @New_SLGetWindowsInformationDWORD;
597 | Stub_SLGetWindowsInformationDWORD.RetOp := $C3;
598 | ReadProcessMemory(GetCurrentProcess, @SLGetWindowsInformationDWORD,
599 | @Old_SLGetWindowsInformationDWORD, SizeOf(OldCode), bw);
600 | WriteProcessMemory(GetCurrentProcess, @SLGetWindowsInformationDWORD,
601 | @Stub_SLGetWindowsInformationDWORD, SizeOf(far_jmp), bw);
602 | end;
603 | end;
604 | if (V = $0601) and (INIReadBool(INI, 'Main', 'SLPolicyHookNT61', True)) then begin
605 | // Windows 7
606 | // uses SL Policy API (slc.dll)
607 |
608 | // load slc.dll and hook function
609 | SLC_Handle := LoadLibrary('slc.dll');
610 | SLGetWindowsInformationDWORD := GetProcAddress(SLC_Handle, 'SLGetWindowsInformationDWORD');
611 |
612 | if @SLGetWindowsInformationDWORD <> nil then
613 | begin
614 | // rewrite original function to call our function (make hook)
615 |
616 | WriteLog('Hook SLGetWindowsInformationDWORD');
617 | Stub_SLGetWindowsInformationDWORD.PushOp := $68;
618 | Stub_SLGetWindowsInformationDWORD.PushArg := @New_SLGetWindowsInformationDWORD;
619 | Stub_SLGetWindowsInformationDWORD.RetOp := $C3;
620 | ReadProcessMemory(GetCurrentProcess, @SLGetWindowsInformationDWORD,
621 | @Old_SLGetWindowsInformationDWORD, SizeOf(OldCode), bw);
622 | WriteProcessMemory(GetCurrentProcess, @SLGetWindowsInformationDWORD,
623 | @Stub_SLGetWindowsInformationDWORD, SizeOf(far_jmp), bw);
624 | end;
625 | end;
626 | if V = $0602 then begin
627 | // Windows 8
628 | // uses SL Policy internal unexported function
629 |
630 | // load slc.dll and get function
631 | // (will be used on intercepting undefined values)
632 | SLC_Handle := LoadLibrary('slc.dll');
633 | SLGetWindowsInformationDWORD := GetProcAddress(SLC_Handle, 'SLGetWindowsInformationDWORD');
634 | end;
635 | if V = $0603 then begin
636 | // Windows 8.1
637 | // uses SL Policy internal inline code
638 | end;
639 | if V = $0604 then begin
640 | // Windows 10
641 | // uses SL Policy internal inline code
642 | end;
643 |
644 | Sect := IntToStr(FV.Version.w.Major)+'.'+IntToStr(FV.Version.w.Minor)+'.'+
645 | IntToStr(FV.Release)+'.'+IntToStr(FV.Build);
646 |
647 | if INISectionExists(INI, Sect) then
648 | if GetModuleAddress('termsrv.dll', GetCurrentProcessId, TermSrvBase, TermSrvSize) then begin
649 | if INIReadBool(INI, Sect, 'LocalOnlyPatch.x86', False) then begin
650 | WriteLog('Patch CEnforcementCore::GetInstanceOfTSLicense');
651 | SignPtr := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'LocalOnlyOffset.x86', 0));
652 | I := SListFind(PatchList, INIReadString(INI, Sect, 'LocalOnlyCode.x86', ''));
653 | if I >= 0 then
654 | WriteProcessMemory(GetCurrentProcess, SignPtr, @Patch[I][0], Length(Patch[I]), bw);
655 | end;
656 | if INIReadBool(INI, Sect, 'SingleUserPatch.x86', False) then begin
657 | WriteLog('Patch CSessionArbitrationHelper::IsSingleSessionPerUserEnabled');
658 | SignPtr := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'SingleUserOffset.x86', 0));
659 | I := SListFind(PatchList, INIReadString(INI, Sect, 'SingleUserCode.x86', ''));
660 | if I >= 0 then
661 | WriteProcessMemory(GetCurrentProcess, SignPtr, @Patch[I][0], Length(Patch[I]), bw);
662 | end;
663 | if INIReadBool(INI, Sect, 'DefPolicyPatch.x86', False) then begin
664 | WriteLog('Patch CDefPolicy::Query');
665 | SignPtr := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'DefPolicyOffset.x86', 0));
666 | I := SListFind(PatchList, INIReadString(INI, Sect, 'DefPolicyCode.x86', ''));
667 | if I >= 0 then
668 | WriteProcessMemory(GetCurrentProcess, SignPtr, @Patch[I][0], Length(Patch[I]), bw);
669 | end;
670 | if INIReadBool(INI, Sect, 'SLPolicyInternal.x86', False) then begin
671 | WriteLog('Hook SLGetWindowsInformationDWORDWrapper');
672 | SignPtr := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'SLPolicyOffset.x86', 0));
673 | MovJump.MovOp := $89; // mov eax, ecx
674 | MovJump.MovArg := $C8; // __msfastcall compatibility
675 | MovJump.PushOp := $68;
676 | MovJump.PushArg := @New_Win8SL;
677 | MovJump.RetOp := $C3;
678 | FuncName := INIReadString(INI, Sect, 'SLPolicyFunc.x86', 'New_Win8SL');
679 | if FuncName = 'New_Win8SL' then
680 | MovJump.PushArg := @New_Win8SL;
681 | if FuncName = 'New_Win8SL_CP' then
682 | MovJump.PushArg := @New_Win8SL_CP;
683 | WriteProcessMemory(GetCurrentProcess, SignPtr,
684 | @MovJump, SizeOf(mov_far_jmp), bw);
685 | end;
686 | if INIReadBool(INI, Sect, 'SLInitHook.x86', False) then begin
687 | WriteLog('Hook CSLQuery::Initialize');
688 | SignPtr := Pointer(Cardinal(TermSrvBase) + INIReadDWordHex(INI, Sect, 'SLInitOffset.x86', 0));
689 | Jump.PushOp := $68;
690 | Jump.PushArg := @New_CSLQuery_Initialize;
691 | Jump.RetOp := $C3;
692 | FuncName := INIReadString(INI, Sect, 'SLInitFunc.x86', 'New_CSLQuery_Initialize');
693 | if FuncName = 'New_CSLQuery_Initialize' then
694 | Jump.PushArg := @New_CSLQuery_Initialize;
695 | WriteProcessMemory(GetCurrentProcess, SignPtr,
696 | @Jump, SizeOf(far_jmp), bw);
697 | end;
698 | end;
699 |
700 | // unfreeze threads
701 | WriteLog('Resumimg threads...');
702 | RunThreads();
703 | end;
704 |
705 | function TermServiceMain(dwArgc: DWORD; lpszArgv: PWideChar): DWORD; stdcall;
706 | begin
707 | // wrap ServiceMain function
708 | WriteLog('>>> ServiceMain');
709 | if not IsHooked then
710 | HookFunctions;
711 | Result := 0;
712 | if @TSMain <> nil then
713 | Result := TSMain(dwArgc, lpszArgv);
714 | WriteLog('<<< ServiceMain');
715 | end;
716 |
717 | function TermServiceGlobals(lpGlobalData: Pointer): DWORD; stdcall;
718 | begin
719 | // wrap SvchostPushServiceGlobals function
720 | WriteLog('>>> SvchostPushServiceGlobals');
721 | if not IsHooked then
722 | HookFunctions;
723 | Result := 0;
724 | if @TSGlobals <> nil then
725 | Result := TSGlobals(lpGlobalData);
726 | WriteLog('<<< SvchostPushServiceGlobals');
727 | end;
728 |
729 | // export section
730 |
731 | exports
732 | TermServiceMain index 1 name 'ServiceMain',
733 | TermServiceGlobals index 2 name 'SvchostPushServiceGlobals';
734 |
735 | begin
736 | // DllMain procedure is not used
737 | end.
--------------------------------------------------------------------------------
/src-x86-binarymaster/rdpwrap.dproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | {D6811241-D595-4809-B3B8-13BECEA56E11}
4 | rdpwrap.dpr
5 | Release
6 | DCC32
7 | 12.0
8 |
9 |
10 | true
11 |
12 |
13 | true
14 | Base
15 | true
16 |
17 |
18 | true
19 | Base
20 | true
21 |
22 |
23 | rdpwrap.dll
24 | WinTypes=Windows;WinProcs=Windows;$(DCC_UnitAlias)
25 | true
26 | 00400000
27 | x86
28 |
29 |
30 | false
31 | RELEASE;$(DCC_Define)
32 | 0
33 | false
34 |
35 |
36 | DEBUG;$(DCC_Define)
37 |
38 |
39 |
40 | MainSource
41 |
42 |
43 | Base
44 |
45 |
46 | Cfg_1
47 | Base
48 |
49 |
50 | Cfg_2
51 | Base
52 |
53 |
54 |
55 |
56 | Delphi.Personality.12
57 | VCLApplication
58 |
59 |
60 |
61 | rdpwrap.dpr
62 |
63 |
64 | False
65 | True
66 | False
67 |
68 |
69 | False
70 | False
71 | 1
72 | 0
73 | 0
74 | 0
75 | False
76 | False
77 | False
78 | False
79 | False
80 | 1049
81 | 1251
82 |
83 |
84 |
85 |
86 | 1.0.0.0
87 |
88 |
89 |
90 |
91 |
92 | 1.0.0.0
93 |
94 |
95 |
96 | Embarcadero C++Builder Office 2000 Servers Package
97 | Embarcadero C++Builder Office XP Servers Package
98 | Microsoft Office 2000 Sample Automation Server Wrapper Components
99 | Microsoft Office XP Sample Automation Server Wrapper Components
100 |
101 |
102 |
103 | 12
104 |
105 |
106 |
--------------------------------------------------------------------------------
/src-x86-binarymaster/rdpwrap.res:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/asmtron/rdpwrap/d973562ba338608de61fad22d41c82e0ef8f5494/src-x86-binarymaster/rdpwrap.res
--------------------------------------------------------------------------------
/src-x86-x64-Fusix/Export.def:
--------------------------------------------------------------------------------
1 | LIBRARY BTREE
2 | EXPORTS
3 | ServiceMain
4 | SvchostPushServiceGlobals
--------------------------------------------------------------------------------
/src-x86-x64-Fusix/IniFile.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2014 Stas'M Corp.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #include "stdafx.h"
18 | #include
19 | #include
20 | #include "IniFile.h"
21 |
22 | INI_FILE::INI_FILE(wchar_t *FilePath)
23 | {
24 | DWORD Status = 0;
25 | DWORD NumberOfBytesRead = 0;
26 |
27 | HANDLE hFile = CreateFile(FilePath, GENERIC_READ, FILE_SHARE_WRITE|FILE_SHARE_READ,
28 | NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
29 |
30 | if (hFile == INVALID_HANDLE_VALUE)
31 | {
32 | return;
33 | }
34 |
35 | FileSize = GetFileSize(hFile, NULL);
36 | if (FileSize == INVALID_FILE_SIZE)
37 | {
38 | return;
39 | }
40 |
41 | FileRaw = new char[FileSize];
42 | Status = ReadFile(hFile, FileRaw, FileSize, &NumberOfBytesRead, NULL);
43 | if (!Status)
44 | {
45 | return;
46 | }
47 |
48 | CreateStringsMap();
49 | Parse();
50 | }
51 |
52 |
53 | INI_FILE::~INI_FILE()
54 | {
55 | for (DWORD i = 0; i < IniData.SectionCount; i++)
56 | {
57 | delete[] IniData.Section[i].Variables;
58 | }
59 | delete[] IniData.Section;
60 | delete[] FileStringsMap;
61 | delete FileRaw;
62 | }
63 |
64 | bool INI_FILE::CreateStringsMap()
65 | {
66 | DWORD StringsCount = 1;
67 |
68 | for (DWORD i = 0; i < FileSize; i++)
69 | {
70 | if (FileRaw[i] == '\r' && FileRaw[i + 1] == '\n') StringsCount++;
71 | }
72 |
73 | FileStringsCount = StringsCount;
74 |
75 | FileStringsMap = new DWORD[StringsCount];
76 | FileStringsMap[0] = 0;
77 |
78 | StringsCount = 1;
79 |
80 | for (DWORD i = 0; i < FileSize; i++)
81 | {
82 | if (FileRaw[i] == '\r' && FileRaw[i + 1] == '\n')
83 | {
84 | FileStringsMap[StringsCount] = i + 2;
85 | StringsCount++;
86 | }
87 | }
88 |
89 | return true;
90 | }
91 |
92 | int INI_FILE::StrTrim(char* Str)
93 | {
94 | int i = 0, j;
95 | while ((Str[i] == ' ') || (Str[i] == '\t'))
96 | {
97 | i++;
98 | }
99 | if (i>0)
100 | {
101 | for (j = 0; j < strlen(Str); j++)
102 | {
103 | Str[j] = Str[j + i];
104 | }
105 | Str[j] = '\0';
106 | }
107 |
108 | i = strlen(Str) - 1;
109 | while ((Str[i] == ' ') || (Str[i] == '\t'))
110 | {
111 | i--;
112 | }
113 | if (i < (strlen(Str) - 1))
114 | {
115 | Str[i + 1] = '\0';
116 | }
117 | return 0;
118 | }
119 |
120 | DWORD INI_FILE::GetFileStringFromNum(DWORD StringNumber, char *RetString, DWORD Size)
121 | {
122 | DWORD CurrentStringNum = 0;
123 | DWORD EndStringPos = 0;
124 | DWORD StringSize = 0;
125 |
126 | if (StringNumber > FileStringsCount) return 0;
127 |
128 | for (DWORD i = FileStringsMap[StringNumber]; i < FileSize; i++)
129 | {
130 | if (i == (FileSize - 1))
131 | {
132 | EndStringPos = FileSize;
133 | break;
134 | }
135 | if (FileRaw[i] == '\r' && FileRaw[i + 1] == '\n')
136 | {
137 | EndStringPos = i;
138 | break;
139 | }
140 | }
141 |
142 | StringSize = EndStringPos - FileStringsMap[StringNumber];
143 |
144 | if (Size < StringSize) return 0;
145 |
146 | memset(RetString, 0x00, Size);
147 | memcpy(RetString, &(FileRaw[FileStringsMap[StringNumber]]), StringSize);
148 | return StringSize;
149 | }
150 |
151 | bool INI_FILE::IsVariable(char *Str, DWORD StrSize)
152 | {
153 | bool Quotes = false;
154 |
155 | for (DWORD i = 0; i < StrSize; i++)
156 | {
157 | if (Str[i] == '"' || Str[i] == '\'') Quotes = !Quotes;
158 | if (Str[i] == '=' && !Quotes) return true;
159 | }
160 | return false;
161 | }
162 |
163 | bool INI_FILE::FillVariable(INI_SECTION_VARIABLE *Variable, char *Str, DWORD StrSize)
164 | {
165 | bool Quotes = false;
166 |
167 | for (DWORD i = 0; i < StrSize; i++)
168 | {
169 | if (Str[i] == '"' || Str[i] == '\'') Quotes = !Quotes;
170 | if (Str[i] == '=' && !Quotes)
171 | {
172 | memset(Variable->VariableName, 0, MAX_STRING_LEN);
173 | memset(Variable->VariableValue, 0, MAX_STRING_LEN);
174 | memcpy(Variable->VariableName, Str, i);
175 | memcpy(Variable->VariableValue, &(Str[i + 1]), StrSize - (i - 1));
176 | StrTrim(Variable->VariableName);
177 | StrTrim(Variable->VariableValue);
178 | break;
179 | }
180 | }
181 | return true;
182 | }
183 |
184 | bool INI_FILE::Parse()
185 | {
186 | DWORD CurrentStringNum = 0;
187 | char CurrentString[512];
188 | DWORD CurrentStringSize = 0;
189 |
190 | DWORD SectionsCount = 0;
191 | DWORD VariablesCount = 0;
192 |
193 | DWORD CurrentSectionNum = -1;
194 | DWORD CurrentVariableNum = -1;
195 |
196 | // Calculate sections count
197 | for (DWORD CurrentStringNum = 0; CurrentStringNum < FileStringsCount; CurrentStringNum++)
198 | {
199 | CurrentStringSize = GetFileStringFromNum(CurrentStringNum, CurrentString, 512);
200 |
201 | if (CurrentString[0] == ';') continue; // It's a comment
202 |
203 | if (CurrentString[0] == '[' && CurrentString[CurrentStringSize - 1] == ']') // It's section declaration
204 | {
205 | SectionsCount++;
206 | continue;
207 | }
208 | }
209 |
210 | DWORD *SectionVariableCount = new DWORD[SectionsCount];
211 | memset(SectionVariableCount, 0x00, sizeof(DWORD)*SectionsCount);
212 |
213 | for (DWORD CurrentStringNum = 0; CurrentStringNum < FileStringsCount; CurrentStringNum++)
214 | {
215 | CurrentStringSize = GetFileStringFromNum(CurrentStringNum, CurrentString, 512);
216 |
217 | if (CurrentString[0] == ';') continue; // It's a comment
218 |
219 |
220 | if (CurrentString[0] == '[' && CurrentString[CurrentStringSize - 1] == ']') // It's section declaration
221 | {
222 | CurrentSectionNum++;
223 | continue;
224 | }
225 | if (IsVariable(CurrentString, CurrentStringSize))
226 | {
227 | VariablesCount++;
228 | SectionVariableCount[CurrentSectionNum]++;
229 | continue;
230 | }
231 | }
232 |
233 | IniData.SectionCount = SectionsCount;
234 | IniData.Section = new INI_SECTION[SectionsCount];
235 | memset(IniData.Section, 0x00, sizeof(PINI_SECTION)*SectionsCount);
236 |
237 | for (DWORD i = 0; i < SectionsCount; i++)
238 | {
239 | IniData.Section[i].VariablesCount = SectionVariableCount[i];
240 | IniData.Section[i].Variables = new INI_SECTION_VARIABLE[SectionVariableCount[i]];
241 | memset(IniData.Section[i].Variables, 0x00, sizeof(INI_SECTION_VARIABLE)*SectionVariableCount[i]);
242 | }
243 |
244 | delete[] SectionVariableCount;
245 |
246 | CurrentSectionNum = -1;
247 | CurrentVariableNum = -1;
248 |
249 | for (DWORD CurrentStringNum = 0; CurrentStringNum < FileStringsCount; CurrentStringNum++)
250 | {
251 | CurrentStringSize = GetFileStringFromNum(CurrentStringNum, CurrentString, 512);
252 |
253 | if (CurrentString[0] == ';') // It's a comment
254 | {
255 | continue;
256 | }
257 |
258 | if (CurrentString[0] == '[' && CurrentString[CurrentStringSize - 1] == ']')
259 | {
260 | CurrentSectionNum++;
261 | CurrentVariableNum = 0;
262 | memset(IniData.Section[CurrentSectionNum].SectionName, 0, MAX_STRING_LEN);
263 | memcpy(IniData.Section[CurrentSectionNum].SectionName, &(CurrentString[1]), (CurrentStringSize - 2));
264 | continue;
265 | }
266 |
267 | if (IsVariable(CurrentString, CurrentStringSize))
268 | {
269 | FillVariable(&(IniData.Section[CurrentSectionNum].Variables[CurrentVariableNum]), CurrentString, CurrentStringSize);
270 | CurrentVariableNum++;
271 | continue;
272 | }
273 | }
274 |
275 | return true;
276 | }
277 |
278 | PINI_SECTION INI_FILE::GetSection(char *SectionName)
279 | {
280 | for (DWORD i = 0; i < IniData.SectionCount; i++)
281 | {
282 | if (
283 | (strlen(IniData.Section[i].SectionName) == strlen(SectionName)) &&
284 | (memcmp(IniData.Section[i].SectionName, SectionName, strlen(SectionName)) == 0)
285 | )
286 | {
287 | return &IniData.Section[i];
288 | }
289 | }
290 | return NULL;
291 | }
292 |
293 | bool INI_FILE::SectionExists(char *SectionName)
294 | {
295 | if (GetSection(SectionName) == NULL) return false;
296 | return true;
297 | }
298 |
299 | bool INI_FILE::VariableExists(char *SectionName, char *VariableName)
300 | {
301 | INI_SECTION_VARIABLE Variable = { 0 };
302 | return GetVariableInSectionPrivate(SectionName, VariableName, &Variable);
303 | }
304 |
305 | bool INI_FILE::GetVariableInSectionPrivate(char *SectionName, char *VariableName, INI_SECTION_VARIABLE *RetVariable)
306 | {
307 | INI_SECTION *Section = NULL;
308 | INI_SECTION_VARIABLE *Variable = NULL;
309 |
310 | // Find section
311 | Section = GetSection(SectionName);
312 | if (Section == NULL)
313 | {
314 | SetLastError(318); // This region is not found
315 | return false;
316 | }
317 |
318 | // Find variable
319 | for (DWORD i = 0; i < Section->VariablesCount; i++)
320 | {
321 | if (
322 | (strlen(Section->Variables[i].VariableName) == strlen(VariableName)) &&
323 | (memcmp(Section->Variables[i].VariableName, VariableName, strlen(VariableName)) == 0)
324 | )
325 | {
326 | Variable = &(Section->Variables[i]);
327 | break;
328 | }
329 | }
330 | if (Variable == NULL)
331 | {
332 | SetLastError(1898); // Member of the group is not found
333 | return false;
334 | }
335 |
336 | memset(RetVariable, 0x00, sizeof(*RetVariable));
337 | memcpy(RetVariable, Variable, sizeof(*Variable));
338 |
339 | return true;
340 | }
341 |
342 | bool INI_FILE::GetVariableInSection(char *SectionName, char *VariableName, INI_VAR_STRING *RetVariable)
343 | {
344 | bool Status = false;
345 | INI_SECTION_VARIABLE Variable = {};
346 |
347 | Status = GetVariableInSectionPrivate(SectionName, VariableName, &Variable);
348 | if (!Status) return Status;
349 |
350 | memset(RetVariable, 0x00, sizeof(*RetVariable));
351 | memcpy(RetVariable->Name, Variable.VariableName, strlen(Variable.VariableName));
352 | memcpy(RetVariable->Value, Variable.VariableValue, strlen(Variable.VariableValue));
353 |
354 | return true;
355 | }
356 |
357 | bool INI_FILE::GetVariableInSection(char *SectionName, char *VariableName, INI_VAR_DWORD *RetVariable)
358 | {
359 | bool Status = false;
360 | INI_SECTION_VARIABLE Variable = {};
361 |
362 | Status = GetVariableInSectionPrivate(SectionName, VariableName, &Variable);
363 | if (!Status) return Status;
364 |
365 | memset(RetVariable, 0x00, sizeof(*RetVariable));
366 | memcpy(RetVariable->Name, Variable.VariableName, strlen(Variable.VariableName));
367 |
368 | #ifndef _WIN64
369 | RetVariable->ValueDec = strtol(Variable.VariableValue, NULL, 10);
370 | RetVariable->ValueHex = strtol(Variable.VariableValue, NULL, 16);
371 | #else
372 | RetVariable->ValueDec = _strtoi64(Variable.VariableValue, NULL, 10);
373 | RetVariable->ValueHex = _strtoi64(Variable.VariableValue, NULL, 16);
374 | #endif
375 | return true;
376 | }
377 |
378 | bool INI_FILE::GetVariableInSection(char *SectionName, char *VariableName, INI_VAR_BYTEARRAY *RetVariable)
379 | {
380 | bool Status = false;
381 | INI_SECTION_VARIABLE Variable = {};
382 |
383 | Status = GetVariableInSectionPrivate(SectionName, VariableName, &Variable);
384 | if (!Status) return Status;
385 |
386 | DWORD ValueLen = strlen(Variable.VariableValue);
387 | if ((ValueLen % 2) != 0) return false;
388 |
389 | // for security reasons not more than 16 bytes
390 | if (ValueLen > 32) ValueLen = 32; // 32 hex digits
391 |
392 | memset(RetVariable, 0x00, sizeof(*RetVariable));
393 | memcpy(RetVariable->Name, Variable.VariableName, strlen(Variable.VariableName));
394 |
395 | for (DWORD i = 0; i <= ValueLen; i++)
396 | {
397 | if ((i % 2) != 0) continue;
398 |
399 | switch (Variable.VariableValue[i])
400 | {
401 | case '0': break;
402 | case '1': RetVariable->Value[(i / 2)] += (1 << 4); break;
403 | case '2': RetVariable->Value[(i / 2)] += (2 << 4); break;
404 | case '3': RetVariable->Value[(i / 2)] += (3 << 4); break;
405 | case '4': RetVariable->Value[(i / 2)] += (4 << 4); break;
406 | case '5': RetVariable->Value[(i / 2)] += (5 << 4); break;
407 | case '6': RetVariable->Value[(i / 2)] += (6 << 4); break;
408 | case '7': RetVariable->Value[(i / 2)] += (7 << 4); break;
409 | case '8': RetVariable->Value[(i / 2)] += (8 << 4); break;
410 | case '9': RetVariable->Value[(i / 2)] += (9 << 4); break;
411 | case 'A': RetVariable->Value[(i / 2)] += (10 << 4); break;
412 | case 'B': RetVariable->Value[(i / 2)] += (11 << 4); break;
413 | case 'C': RetVariable->Value[(i / 2)] += (12 << 4); break;
414 | case 'D': RetVariable->Value[(i / 2)] += (13 << 4); break;
415 | case 'E': RetVariable->Value[(i / 2)] += (14 << 4); break;
416 | case 'F': RetVariable->Value[(i / 2)] += (15 << 4); break;
417 | }
418 |
419 | switch (Variable.VariableValue[i + 1])
420 | {
421 | case '0': break;
422 | case '1': RetVariable->Value[(i / 2)] += 1; break;
423 | case '2': RetVariable->Value[(i / 2)] += 2; break;
424 | case '3': RetVariable->Value[(i / 2)] += 3; break;
425 | case '4': RetVariable->Value[(i / 2)] += 4; break;
426 | case '5': RetVariable->Value[(i / 2)] += 5; break;
427 | case '6': RetVariable->Value[(i / 2)] += 6; break;
428 | case '7': RetVariable->Value[(i / 2)] += 7; break;
429 | case '8': RetVariable->Value[(i / 2)] += 8; break;
430 | case '9': RetVariable->Value[(i / 2)] += 9; break;
431 | case 'A': RetVariable->Value[(i / 2)] += 10; break;
432 | case 'B': RetVariable->Value[(i / 2)] += 11; break;
433 | case 'C': RetVariable->Value[(i / 2)] += 12; break;
434 | case 'D': RetVariable->Value[(i / 2)] += 13; break;
435 | case 'E': RetVariable->Value[(i / 2)] += 14; break;
436 | case 'F': RetVariable->Value[(i / 2)] += 15; break;
437 | }
438 | }
439 | RetVariable->ArraySize = ValueLen / 2;
440 | return true;
441 | }
442 |
443 | bool INI_FILE::GetVariableInSection(char *SectionName, char *VariableName, bool *RetVariable)
444 | {
445 | bool Status = false;
446 | INI_SECTION_VARIABLE Variable = {};
447 |
448 | Status = GetVariableInSectionPrivate(SectionName, VariableName, &Variable);
449 | if (!Status) return Status;
450 |
451 | *RetVariable = (bool)strtol(Variable.VariableValue, NULL, 10);
452 | return true;
453 | }
454 |
455 | bool INI_FILE::GetSectionVariablesList(char *SectionName, INI_SECTION_VARLIST *VariablesList)
456 | {
457 | INI_SECTION *Section = NULL;
458 |
459 | Section = GetSection(SectionName);
460 | if (Section == NULL)
461 | {
462 | SetLastError(318); // This region is not found
463 | return false;
464 | }
465 |
466 | VariablesList->EntriesCount = Section->VariablesCount;
467 |
468 | VariablesList->NamesEntries = new INI_SECTION_VARLIST_ENTRY[VariablesList->EntriesCount];
469 | memset(VariablesList->NamesEntries, 0x00, sizeof(INI_SECTION_VARLIST_ENTRY)*VariablesList->EntriesCount);
470 |
471 | VariablesList->ValuesEntries = new INI_SECTION_VARLIST_ENTRY[VariablesList->EntriesCount];
472 | memset(VariablesList->ValuesEntries, 0x00, sizeof(INI_SECTION_VARLIST_ENTRY)*VariablesList->EntriesCount);
473 |
474 | for (DWORD i = 0; i < Section->VariablesCount; i++)
475 | {
476 | memcpy(VariablesList->NamesEntries[i].String, Section->Variables[i].VariableName,
477 | strlen(Section->Variables[i].VariableName));
478 |
479 | memcpy(VariablesList->ValuesEntries[i].String, Section->Variables[i].VariableValue,
480 | strlen(Section->Variables[i].VariableValue));
481 | }
482 |
483 | return true;
484 | }
485 |
486 |
487 | // ---------------------------- WCHAR_T BLOCK ----------------------------------------------
488 |
489 | bool INI_FILE::SectionExists(wchar_t *SectionName)
490 | {
491 | char cSectionName[MAX_STRING_LEN] = { 0x00 };
492 |
493 | wcstombs(cSectionName, SectionName, MAX_STRING_LEN);
494 |
495 | return GetSection(cSectionName);
496 | }
497 |
498 | bool INI_FILE::VariableExists(wchar_t *SectionName, wchar_t *VariableName)
499 | {
500 | INI_SECTION_VARIABLE Variable = { 0 };
501 |
502 | char cSectionName[MAX_STRING_LEN] = { 0x00 };
503 | char cVariableName[MAX_STRING_LEN] = { 0x00 };
504 |
505 | wcstombs(cSectionName, SectionName, MAX_STRING_LEN);
506 | wcstombs(cVariableName, VariableName, MAX_STRING_LEN);
507 |
508 | return GetVariableInSectionPrivate(cSectionName, cVariableName, &Variable);
509 | }
510 |
511 | bool INI_FILE::GetVariableInSection(wchar_t *SectionName, wchar_t *VariableName, INI_VAR_STRING *RetVariable)
512 | {
513 | char cSectionName[MAX_STRING_LEN] = { 0x00 };
514 | char cVariableName[MAX_STRING_LEN] = { 0x00 };
515 |
516 | wcstombs(cSectionName, SectionName, MAX_STRING_LEN);
517 | wcstombs(cVariableName, VariableName, MAX_STRING_LEN);
518 |
519 | return GetVariableInSection(cSectionName, cVariableName, RetVariable);
520 | }
521 |
522 | bool INI_FILE::GetVariableInSection(wchar_t *SectionName, wchar_t *VariableName, INI_VAR_DWORD *RetVariable)
523 | {
524 | char cSectionName[MAX_STRING_LEN] = { 0x00 };
525 | char cVariableName[MAX_STRING_LEN] = { 0x00 };
526 |
527 | wcstombs(cSectionName, SectionName, MAX_STRING_LEN);
528 | wcstombs(cVariableName, VariableName, MAX_STRING_LEN);
529 |
530 | return GetVariableInSection(cSectionName, cVariableName, RetVariable);
531 | }
532 |
533 | bool INI_FILE::GetVariableInSection(wchar_t *SectionName, wchar_t *VariableName, INI_VAR_BYTEARRAY *RetVariable)
534 | {
535 | char cSectionName[MAX_STRING_LEN] = { 0x00 };
536 | char cVariableName[MAX_STRING_LEN] = { 0x00 };
537 |
538 | wcstombs(cSectionName, SectionName, MAX_STRING_LEN);
539 | wcstombs(cVariableName, VariableName, MAX_STRING_LEN);
540 |
541 | return GetVariableInSection(cSectionName, cVariableName, RetVariable);
542 | }
543 |
544 | bool INI_FILE::GetVariableInSection(wchar_t *SectionName, wchar_t *VariableName, bool *RetVariable)
545 | {
546 | char cSectionName[MAX_STRING_LEN] = { 0x00 };
547 | char cVariableName[MAX_STRING_LEN] = { 0x00 };
548 |
549 | wcstombs(cSectionName, SectionName, MAX_STRING_LEN);
550 | wcstombs(cVariableName, VariableName, MAX_STRING_LEN);
551 |
552 | return GetVariableInSection(cSectionName, cVariableName, RetVariable);
553 | }
554 |
555 | bool INI_FILE::GetSectionVariablesList(wchar_t *SectionName, INI_SECTION_VARLIST *VariablesList)
556 | {
557 | char cSectionName[MAX_STRING_LEN] = { 0x00 };
558 |
559 | wcstombs(cSectionName, SectionName, MAX_STRING_LEN);
560 |
561 | return GetSectionVariablesList(cSectionName, VariablesList);
562 | }
--------------------------------------------------------------------------------
/src-x86-x64-Fusix/IniFile.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2014 Stas'M Corp.
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 | */
16 |
17 | #include "stdafx.h"
18 | #include
19 |
20 | #define MAX_STRING_LEN 255
21 |
22 | // Out values struсts
23 | typedef struct _INI_VAR_STRING
24 | {
25 | char Name[MAX_STRING_LEN];
26 | char Value[MAX_STRING_LEN];
27 | } INI_VAR_STRING, *PINI_VAR_STRING;
28 |
29 | typedef struct _INI_VAR_DWORD
30 | {
31 | char Name[MAX_STRING_LEN];
32 | #ifndef _WIN64
33 | DWORD ValueDec;
34 | DWORD ValueHex;
35 | #else
36 | DWORD64 ValueDec;
37 | DWORD64 ValueHex;
38 | #endif
39 |
40 | } INI_VAR_DWORD, *PINI_VAR_DWORD;
41 |
42 | typedef struct _INI_VAR_BYTEARRAY
43 | {
44 | char Name[MAX_STRING_LEN];
45 | BYTE ArraySize;
46 | char Value[MAX_STRING_LEN];
47 | } INI_VAR_BYTEARRAY, *PINI_VAR_BYTEARRAY;
48 |
49 | typedef struct _INI_SECTION_VARLIST_ENTRY
50 | {
51 | char String[MAX_STRING_LEN];
52 | } INI_SECTION_VARLIST_ENTRY, *PINI_SECTION_VARLIST_ENTRY;
53 |
54 | typedef struct _INI_SECTION_VARLIST
55 | {
56 | DWORD EntriesCount;
57 | [length_is(EntriesCount)] INI_SECTION_VARLIST_ENTRY *NamesEntries;
58 | [length_is(EntriesCount)] INI_SECTION_VARLIST_ENTRY *ValuesEntries;
59 | } INI_SECTION_VARLIST, *PINI_SECTION_VARLIST;
60 |
61 | // end
62 |
63 | typedef struct _INI_SECTION_VARIABLE
64 | {
65 | char VariableName[MAX_STRING_LEN];
66 | char VariableValue[MAX_STRING_LEN];
67 | } INI_SECTION_VARIABLE, *PINI_SECTION_VARIABLE;
68 |
69 |
70 | typedef struct _INI_SECTION
71 | {
72 | char SectionName[MAX_STRING_LEN];
73 | DWORD VariablesCount;
74 | [length_is(SectionCount)] INI_SECTION_VARIABLE *Variables;
75 |
76 | } INI_SECTION, *PINI_SECTION;
77 |
78 | typedef struct _INI_DATA
79 | {
80 | DWORD SectionCount;
81 | [length_is(SectionCount)] INI_SECTION *Section;
82 | } INI_DATA, *PINI_DATA;
83 |
84 | class INI_FILE
85 | {
86 | public:
87 | INI_FILE(wchar_t*);
88 | ~INI_FILE();
89 |
90 | // char block
91 | bool SectionExists(char *SectionName);
92 | bool VariableExists(char *SectionName, char *VariableName);
93 | bool GetVariableInSection(char *SectionName, char *VariableName, INI_VAR_STRING *Variable);
94 | bool GetVariableInSection(char *SectionName, char *VariableName, INI_VAR_DWORD *Variable);
95 | bool GetVariableInSection(char *SectionName, char *VariableName, bool *Variable);
96 | bool GetVariableInSection(char *SectionName, char *VariableName, INI_VAR_BYTEARRAY *Variable);
97 | bool GetSectionVariablesList(char *SectionName, INI_SECTION_VARLIST *VariablesList);
98 |
99 | // wchar_t tramps
100 | bool SectionExists(wchar_t *SectionName);
101 | bool VariableExists(wchar_t *SectionName, wchar_t *VariableName);
102 | bool GetVariableInSection(wchar_t *SectionName, wchar_t *VariableName, INI_VAR_STRING *Variable);
103 | bool GetVariableInSection(wchar_t *SectionName, wchar_t *VariableName, INI_VAR_DWORD *Variable);
104 | bool GetVariableInSection(wchar_t *SectionName, wchar_t *VariableName, bool *Variable);
105 | bool GetVariableInSection(wchar_t *SectionName, wchar_t *VariableName, INI_VAR_BYTEARRAY *Variable);
106 | bool GetSectionVariablesList(wchar_t *SectionName, INI_SECTION_VARLIST *VariablesList);
107 |
108 | private:
109 | DWORD FileSize; // Ini file size
110 | char *FileRaw; // Ini file raw dump
111 | DWORD FileStringsCount; // String-map length
112 | DWORD *FileStringsMap; // String-map
113 | INI_DATA IniData; // Parsed data
114 |
115 | // Common service functions
116 | int StrTrim(char* Str);
117 |
118 | // Class service functions
119 | bool CreateStringsMap(); // Create file string-map
120 | bool Parse(); // Parse file to class structures
121 | DWORD GetFileStringFromNum(DWORD StringNumber, char *RetString, DWORD Size); // Get string from string-map
122 | bool IsVariable(char *Str, DWORD StrSize);
123 | bool FillVariable(INI_SECTION_VARIABLE *Variable, char *Str, DWORD StrSize); // Fill INI_SECTION_VARIABLE struct (for Parse)
124 | PINI_SECTION GetSection(char *SectionName);
125 | bool GetVariableInSectionPrivate(char *SectionName, char *VariableName, INI_SECTION_VARIABLE *RetVariable);
126 | };
127 |
--------------------------------------------------------------------------------
/src-x86-x64-Fusix/RDPWrap.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2012
4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RDPWrap", "RDPWrap.vcxproj", "{29E4E73B-EBA6-495B-A76C-FBB462196C64}"
5 | EndProject
6 | Global
7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
8 | Debug|Win32 = Debug|Win32
9 | Debug|x64 = Debug|x64
10 | Release|Win32 = Release|Win32
11 | Release|x64 = Release|x64
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {29E4E73B-EBA6-495B-A76C-FBB462196C64}.Debug|Win32.ActiveCfg = Debug|Win32
15 | {29E4E73B-EBA6-495B-A76C-FBB462196C64}.Debug|Win32.Build.0 = Debug|Win32
16 | {29E4E73B-EBA6-495B-A76C-FBB462196C64}.Debug|Win32.Deploy.0 = Debug|Win32
17 | {29E4E73B-EBA6-495B-A76C-FBB462196C64}.Debug|x64.ActiveCfg = Debug|x64
18 | {29E4E73B-EBA6-495B-A76C-FBB462196C64}.Debug|x64.Build.0 = Debug|x64
19 | {29E4E73B-EBA6-495B-A76C-FBB462196C64}.Debug|x64.Deploy.0 = Debug|x64
20 | {29E4E73B-EBA6-495B-A76C-FBB462196C64}.Release|Win32.ActiveCfg = Release|Win32
21 | {29E4E73B-EBA6-495B-A76C-FBB462196C64}.Release|Win32.Build.0 = Release|Win32
22 | {29E4E73B-EBA6-495B-A76C-FBB462196C64}.Release|Win32.Deploy.0 = Release|Win32
23 | {29E4E73B-EBA6-495B-A76C-FBB462196C64}.Release|x64.ActiveCfg = Release|x64
24 | {29E4E73B-EBA6-495B-A76C-FBB462196C64}.Release|x64.Build.0 = Release|x64
25 | {29E4E73B-EBA6-495B-A76C-FBB462196C64}.Release|x64.Deploy.0 = Release|x64
26 | EndGlobalSection
27 | GlobalSection(SolutionProperties) = preSolution
28 | HideSolutionNode = FALSE
29 | EndGlobalSection
30 | EndGlobal
31 |
--------------------------------------------------------------------------------
/src-x86-x64-Fusix/RDPWrap.v11.suo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/asmtron/rdpwrap/d973562ba338608de61fad22d41c82e0ef8f5494/src-x86-x64-Fusix/RDPWrap.v11.suo
--------------------------------------------------------------------------------
/src-x86-x64-Fusix/RDPWrap.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Debug
10 | x64
11 |
12 |
13 | Release
14 | Win32
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | {29E4E73B-EBA6-495B-A76C-FBB462196C64}
23 | Win32Proj
24 | RDPWrap
25 |
26 |
27 |
28 | DynamicLibrary
29 | true
30 | v120
31 | Unicode
32 |
33 |
34 | DynamicLibrary
35 | true
36 | v120
37 | Unicode
38 |
39 |
40 | DynamicLibrary
41 | false
42 | v120
43 | true
44 | Unicode
45 |
46 |
47 | DynamicLibrary
48 | false
49 | v120
50 | true
51 | Unicode
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | true
71 |
72 |
73 | true
74 |
75 |
76 | false
77 |
78 |
79 | false
80 |
81 |
82 |
83 | Use
84 | Level3
85 | Disabled
86 | WIN32;_DEBUG;_WINDOWS;_USRDLL;RDPWRAP_EXPORTS;%(PreprocessorDefinitions)
87 | true
88 |
89 |
90 | Windows
91 | true
92 | Export.def
93 |
94 |
95 |
96 |
97 | Use
98 | Level3
99 | Disabled
100 | WIN32;_DEBUG;_WINDOWS;_USRDLL;RDPWRAP_EXPORTS;%(PreprocessorDefinitions)
101 | true
102 |
103 |
104 | Windows
105 | true
106 | Export.def
107 |
108 |
109 |
110 |
111 | Use
112 | MaxSpeed
113 | true
114 | true
115 | WIN32;NDEBUG;_WINDOWS;_USRDLL;RDPWRAP_EXPORTS;%(PreprocessorDefinitions)
116 | true
117 | true
118 | Level3
119 | 1Byte
120 | MultiThreaded
121 |
122 |
123 | Windows
124 | false
125 | true
126 | true
127 | Export.def
128 |
129 |
130 | false
131 | true
132 |
133 |
134 |
135 |
136 | Use
137 | MaxSpeed
138 | true
139 | true
140 | WIN32;NDEBUG;_WINDOWS;_USRDLL;RDPWRAP_EXPORTS;%(PreprocessorDefinitions)
141 | true
142 | true
143 | Level3
144 | 1Byte
145 | MultiThreaded
146 |
147 |
148 | Windows
149 | false
150 | true
151 | true
152 | Export.def
153 |
154 |
155 | false
156 | true
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 | false
170 | false
171 |
172 |
173 |
174 |
175 | false
176 | false
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 | Create
186 | Create
187 | Create
188 | Create
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
--------------------------------------------------------------------------------
/src-x86-x64-Fusix/RDPWrap.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | Заголовочные файлы
23 |
24 |
25 | Заголовочные файлы
26 |
27 |
28 | Заголовочные файлы
29 |
30 |
31 |
32 |
33 | Файлы исходного кода
34 |
35 |
36 | Файлы исходного кода
37 |
38 |
39 | Файлы исходного кода
40 |
41 |
42 | Файлы исходного кода
43 |
44 |
45 |
46 |
47 | Файлы исходного кода
48 |
49 |
50 |
--------------------------------------------------------------------------------
/src-x86-x64-Fusix/ReadMe.txt:
--------------------------------------------------------------------------------
1 | ========================================================================
2 | БИБЛИОТЕКА ДИНАМИЧЕСКОЙ КОМПОНОВКИ. Обзор проекта RDPWrap
3 | ========================================================================
4 |
5 | Эта библиотека DLL RDPWrap создана автоматически с помощью мастера приложений.
6 |
7 | В этом файле представлена сводка содержимого всех файлов, входящих в состав приложения RDPWrap.
8 |
9 |
10 | RDPWrap.vcxproj
11 | Это основной файл проекта VC++, создаваемый с помощью мастера приложений. Он содержит данные о версии языка Visual C++, использованной для создания файла, а также сведения о платформах, конфигурациях и функциях проекта, выбранных с помощью мастера приложений.
12 |
13 | RDPWrap.vcxproj.filters
14 | Это файл фильтров для проектов VC++, созданный с помощью мастера приложений. Он содержит сведения о сопоставлениях между файлами в вашем проекте и фильтрами. Эти сопоставления используются в среде IDE для группировки файлов с одинаковыми расширениями в одном узле (например CPP-файлы сопоставляются с фильтром "Исходные файлы").
15 |
16 | RDPWrap.cpp
17 | Основной исходный файл библиотеки DLL.
18 |
19 | При создании этой библиотеки DLL не выполняется экспорт символов. Поэтому при ее построении не создается LIB-файл. Если в этом проекте требуется определить зависимость от другого проекта, необходимо добавить код для экспорта символов из библиотеки DLL, чтобы обеспечить создание библиотеки экспорта, или задать значение «Да» для свойства «Пропустить входную библиотеку» на странице общих свойств папки «Компоновщик» в диалоговом окне «Страницы свойств» проекта.
20 |
21 | /////////////////////////////////////////////////////////////////////////////
22 | Другие стандартные файлы:
23 |
24 | StdAfx.h, StdAfx.cpp
25 | Эти файлы используются для построения файла предкомпилированного заголовка (PCH) с именем RDPWrap.pch и файла предкомпилированных типов с именем StdAfx.obj.
26 |
27 | /////////////////////////////////////////////////////////////////////////////
28 | Прочие примечания.
29 |
30 | С помощью комментариев «TODO:» в мастере приложений обозначаются фрагменты исходного кода, которые необходимо дополнить или изменить.
31 |
32 | /////////////////////////////////////////////////////////////////////////////
33 |
--------------------------------------------------------------------------------
/src-x86-x64-Fusix/dllmain.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/asmtron/rdpwrap/d973562ba338608de61fad22d41c82e0ef8f5494/src-x86-x64-Fusix/dllmain.cpp
--------------------------------------------------------------------------------
/src-x86-x64-Fusix/stdafx.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/asmtron/rdpwrap/d973562ba338608de61fad22d41c82e0ef8f5494/src-x86-x64-Fusix/stdafx.cpp
--------------------------------------------------------------------------------
/src-x86-x64-Fusix/stdafx.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/asmtron/rdpwrap/d973562ba338608de61fad22d41c82e0ef8f5494/src-x86-x64-Fusix/stdafx.h
--------------------------------------------------------------------------------
/src-x86-x64-Fusix/targetver.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/asmtron/rdpwrap/d973562ba338608de61fad22d41c82e0ef8f5494/src-x86-x64-Fusix/targetver.h
--------------------------------------------------------------------------------