├── .gitattributes
├── .gitignore
├── ClientDemo
├── ClientDemo.cpp
├── ClientDemo.vcxproj
├── ClientDemo.vcxproj.filters
├── ReadMe.txt
├── stdafx.cpp
├── stdafx.h
└── targetver.h
├── CodeLib.vcxproj
├── CodeLib.vcxproj.filters
├── NTFS.cpp
├── NTFS.h
├── ReadMe.txt
├── Sample
└── Services
│ ├── SampleService.cpp
│ └── SampleService.h
├── Test.cpp
├── include
├── Common.h
├── IFileMap.h
├── IIPCInterface.h
├── IIni.h
├── ILPC.h
├── IMiniDump.h
├── IProcess.h
├── IThread.h
├── IVolumeParse.h
└── ntdll.h
├── src
├── CdfsVolumeParse.cpp
├── CdfsVolumeParse.h
├── Common.cpp
├── CommonFunc.cpp
├── CommonFunc.h
├── ConsoleDebug.h
├── Fat16VolumeParse.cpp
├── Fat16VolumeParse.h
├── Fat32VolumeParse.cpp
├── Fat32VolumeParse.h
├── FileMapImpl.cpp
├── FileMapImpl.h
├── FileScan.cpp
├── FileScan.h
├── ICallBack.h
├── IPCMessage.h
├── IniFileImpl.cpp
├── IniFileImpl.h
├── IoCompletePort.h
├── Keyboard.cpp
├── Keyboard.h
├── LPCClientImpl.cpp
├── LPCClientImpl.h
├── LPCServerImpl.cpp
├── LPCServerImpl.h
├── MiniDumpImpl.cpp
├── MiniDumpImpl.h
├── NTFSDefine.h
├── NamedPipeClientImpl.cpp
├── NamedPipeClientImpl.h
├── NamedPipeServerImpl.cpp
├── NamedPipeServerImpl.h
├── NamedPipeWrapper.h
├── NtfsVolumeParse.cpp
├── NtfsVolumeParse.h
├── ProcessImpl.cpp
├── ProcessImpl.h
├── Services
│ ├── ServiceBase.cpp
│ ├── ServiceBase.h
│ ├── ServiceInstaller.cpp
│ ├── ServiceInstaller.h
│ └── ThreadPool.h
├── SparseFiles.cpp
├── SparseFiles.h
├── ThreadImpl.cpp
├── ThreadImpl.h
├── ThreadWithFunc.cpp
└── ThreadWithFunc.h
├── stdafx.cpp
├── stdafx.h
└── targetver.h
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 | *.sln merge=union
7 | *.csproj merge=union
8 | *.vbproj merge=union
9 | *.fsproj merge=union
10 | *.dbproj merge=union
11 |
12 | # Standard to msysgit
13 | *.doc diff=astextplain
14 | *.DOC diff=astextplain
15 | *.docx diff=astextplain
16 | *.DOCX diff=astextplain
17 | *.dot diff=astextplain
18 | *.DOT diff=astextplain
19 | *.pdf diff=astextplain
20 | *.PDF diff=astextplain
21 | *.rtf diff=astextplain
22 | *.RTF diff=astextplain
23 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | #################
2 | ## Eclipse
3 | #################
4 |
5 | *.pydevproject
6 | .project
7 | .metadata
8 | bin/
9 | tmp/
10 | *.tmp
11 | *.bak
12 | *.swp
13 | *~.nib
14 | local.properties
15 | .classpath
16 | .settings/
17 | .loadpath
18 |
19 | # External tool builders
20 | .externalToolBuilders/
21 |
22 | # Locally stored "Eclipse launch configurations"
23 | *.launch
24 |
25 | # CDT-specific
26 | .cproject
27 |
28 | # PDT-specific
29 | .buildpath
30 |
31 |
32 | #################
33 | ## Visual Studio
34 | #################
35 |
36 | ## Ignore Visual Studio temporary files, build results, and
37 | ## files generated by popular Visual Studio add-ons.
38 |
39 | # User-specific files
40 | *.suo
41 | *.user
42 | *.sln.docstates
43 |
44 | # Build results
45 |
46 | [Dd]ebug/
47 | [Rr]elease/
48 | x64/
49 | build/
50 | [Bb]in/
51 | [Oo]bj/
52 |
53 | # MSTest test Results
54 | [Tt]est[Rr]esult*/
55 | [Bb]uild[Ll]og.*
56 |
57 | *_i.c
58 | *_p.c
59 | *.ilk
60 | *.meta
61 | *.obj
62 | *.pch
63 | *.pdb
64 | *.pgc
65 | *.pgd
66 | *.rsp
67 | *.sbr
68 | *.tlb
69 | *.tli
70 | *.tlh
71 | *.tmp
72 | *.tmp_proj
73 | *.log
74 | *.vspscc
75 | *.vssscc
76 | .builds
77 | *.pidb
78 | *.log
79 | *.scc
80 |
81 | # Visual C++ cache files
82 | ipch/
83 | *.aps
84 | *.ncb
85 | *.opensdf
86 | *.sdf
87 | *.cachefile
88 |
89 | # Visual Studio profiler
90 | *.psess
91 | *.vsp
92 | *.vspx
93 |
94 | # Guidance Automation Toolkit
95 | *.gpState
96 |
97 | # ReSharper is a .NET coding add-in
98 | _ReSharper*/
99 | *.[Rr]e[Ss]harper
100 |
101 | # TeamCity is a build add-in
102 | _TeamCity*
103 |
104 | # DotCover is a Code Coverage Tool
105 | *.dotCover
106 |
107 | # NCrunch
108 | *.ncrunch*
109 | .*crunch*.local.xml
110 |
111 | # Installshield output folder
112 | [Ee]xpress/
113 |
114 | # DocProject is a documentation generator add-in
115 | DocProject/buildhelp/
116 | DocProject/Help/*.HxT
117 | DocProject/Help/*.HxC
118 | DocProject/Help/*.hhc
119 | DocProject/Help/*.hhk
120 | DocProject/Help/*.hhp
121 | DocProject/Help/Html2
122 | DocProject/Help/html
123 |
124 | # Click-Once directory
125 | publish/
126 |
127 | # Publish Web Output
128 | *.Publish.xml
129 | *.pubxml
130 |
131 | # NuGet Packages Directory
132 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line
133 | #packages/
134 |
135 | # Windows Azure Build Output
136 | csx
137 | *.build.csdef
138 |
139 | # Windows Store app package directory
140 | AppPackages/
141 |
142 | # Others
143 | sql/
144 | *.Cache
145 | ClientBin/
146 | [Ss]tyle[Cc]op.*
147 | ~$*
148 | *~
149 | *.dbmdl
150 | *.[Pp]ublish.xml
151 | *.pfx
152 | *.publishsettings
153 |
154 | # RIA/Silverlight projects
155 | Generated_Code/
156 |
157 | # Backup & report files from converting an old project file to a newer
158 | # Visual Studio version. Backup files are not needed, because we have git ;-)
159 | _UpgradeReport_Files/
160 | Backup*/
161 | UpgradeLog*.XML
162 | UpgradeLog*.htm
163 |
164 | # SQL Server files
165 | App_Data/*.mdf
166 | App_Data/*.ldf
167 |
168 | #############
169 | ## Windows detritus
170 | #############
171 |
172 | # Windows image file caches
173 | Thumbs.db
174 | ehthumbs.db
175 |
176 | # Folder config file
177 | Desktop.ini
178 |
179 | # Recycle Bin used on file shares
180 | $RECYCLE.BIN/
181 |
182 | # Mac crap
183 | .DS_Store
184 |
185 |
186 | #############
187 | ## Python
188 | #############
189 |
190 | *.py[co]
191 |
192 | # Packages
193 | *.egg
194 | *.egg-info
195 | dist/
196 | build/
197 | eggs/
198 | parts/
199 | var/
200 | sdist/
201 | develop-eggs/
202 | .installed.cfg
203 |
204 | # Installer logs
205 | pip-log.txt
206 |
207 | # Unit test / coverage reports
208 | .coverage
209 | .tox
210 |
211 | #Translations
212 | *.mo
213 |
214 | #Mr Developer
215 | .mr.developer.cfg
216 | *.sln
217 |
--------------------------------------------------------------------------------
/ClientDemo/ClientDemo.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wyrover/CodeLib/cee0615b2cba6d1281b93177aea7a64c4a39e1de/ClientDemo/ClientDemo.cpp
--------------------------------------------------------------------------------
/ClientDemo/ClientDemo.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 |
14 | {C497F76F-9CC0-4E5E-879F-D0CAE69EA384}
15 | Win32Proj
16 | ClientDemo
17 |
18 |
19 |
20 | Application
21 | true
22 | v110
23 | Unicode
24 |
25 |
26 | Application
27 | false
28 | v110
29 | true
30 | Unicode
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | true
44 |
45 |
46 | false
47 |
48 |
49 |
50 | Use
51 | Level3
52 | Disabled
53 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
54 | true
55 | J:\GitHub\CodeLib\include
56 |
57 |
58 | Console
59 | true
60 |
61 |
62 |
63 |
64 | Level3
65 | Use
66 | MaxSpeed
67 | true
68 | true
69 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
70 | true
71 |
72 |
73 | Console
74 | true
75 | true
76 | true
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 | Create
92 | Create
93 |
94 |
95 |
96 |
97 |
98 |
--------------------------------------------------------------------------------
/ClientDemo/ClientDemo.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 |
--------------------------------------------------------------------------------
/ClientDemo/ReadMe.txt:
--------------------------------------------------------------------------------
1 | ========================================================================
2 | 控制台应用程序:ClientDemo 项目概述
3 | ========================================================================
4 |
5 | 应用程序向导已为您创建了此 ClientDemo 应用程序。
6 |
7 | 本文件概要介绍组成 ClientDemo 应用程序的每个文件的内容。
8 |
9 |
10 | ClientDemo.vcxproj
11 | 这是使用应用程序向导生成的 VC++ 项目的主项目文件,其中包含生成该文件的 Visual C++ 的版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。
12 |
13 | ClientDemo.vcxproj.filters
14 | 这是使用“应用程序向导”生成的 VC++ 项目筛选器文件。它包含有关项目文件与筛选器之间的关联信息。在 IDE 中,通过这种关联,在特定节点下以分组形式显示具有相似扩展名的文件。例如,“.cpp”文件与“源文件”筛选器关联。
15 |
16 | ClientDemo.cpp
17 | 这是主应用程序源文件。
18 |
19 | /////////////////////////////////////////////////////////////////////////////
20 | 其他标准文件:
21 |
22 | StdAfx.h, StdAfx.cpp
23 | 这些文件用于生成名为 ClientDemo.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。
24 |
25 | /////////////////////////////////////////////////////////////////////////////
26 | 其他注释:
27 |
28 | 应用程序向导使用“TODO:”注释来指示应添加或自定义的源代码部分。
29 |
30 | /////////////////////////////////////////////////////////////////////////////
31 |
--------------------------------------------------------------------------------
/ClientDemo/stdafx.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wyrover/CodeLib/cee0615b2cba6d1281b93177aea7a64c4a39e1de/ClientDemo/stdafx.cpp
--------------------------------------------------------------------------------
/ClientDemo/stdafx.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wyrover/CodeLib/cee0615b2cba6d1281b93177aea7a64c4a39e1de/ClientDemo/stdafx.h
--------------------------------------------------------------------------------
/ClientDemo/targetver.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wyrover/CodeLib/cee0615b2cba6d1281b93177aea7a64c4a39e1de/ClientDemo/targetver.h
--------------------------------------------------------------------------------
/CodeLib.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 | {11287A04-25AA-4426-9CAD-EBA5A19C634A}
23 | Win32Proj
24 | CodeLib
25 |
26 |
27 |
28 | Application
29 | true
30 | v110
31 | Unicode
32 |
33 |
34 | Application
35 | true
36 | v110
37 | Unicode
38 |
39 |
40 | Application
41 | false
42 | v110
43 | true
44 | Unicode
45 |
46 |
47 | Application
48 | false
49 | v110
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;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)
87 | true
88 | include\
89 |
90 |
91 | Console
92 | true
93 |
94 |
95 |
96 |
97 | Use
98 | Level3
99 | Disabled
100 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
101 | true
102 | include\
103 | true
104 |
105 |
106 | Console
107 | true
108 |
109 |
110 |
111 |
112 | Level3
113 | Use
114 | MaxSpeed
115 | true
116 | true
117 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
118 | true
119 | include\
120 |
121 |
122 | Console
123 | true
124 | true
125 | true
126 |
127 |
128 |
129 |
130 | Level3
131 | Use
132 | MaxSpeed
133 | true
134 | true
135 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
136 | true
137 | include\
138 |
139 |
140 | Console
141 | true
142 | true
143 | true
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 | Create
215 | Create
216 | Create
217 | Create
218 |
219 |
220 |
221 |
222 |
223 |
--------------------------------------------------------------------------------
/CodeLib.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 | {b7602908-fe00-4852-90f0-7a0698a595ba}
18 |
19 |
20 | {3436fbcc-472f-49c4-83e5-69ce8212991f}
21 |
22 |
23 | {ee3148df-776b-4261-9518-247e0d1f7460}
24 |
25 |
26 | {a9cec680-2206-476f-a43e-f2566f5da070}
27 |
28 |
29 | {2233e64a-cce9-4fb2-ac78-86a74793a93c}
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | 头文件
38 |
39 |
40 | 头文件
41 |
42 |
43 | include
44 |
45 |
46 | include
47 |
48 |
49 | src
50 |
51 |
52 | include
53 |
54 |
55 | src
56 |
57 |
58 | include
59 |
60 |
61 | src
62 |
63 |
64 | include
65 |
66 |
67 | src
68 |
69 |
70 | include
71 |
72 |
73 | src
74 |
75 |
76 | include
77 |
78 |
79 | src
80 |
81 |
82 | src
83 |
84 |
85 | src
86 |
87 |
88 | src
89 |
90 |
91 | include
92 |
93 |
94 | src
95 |
96 |
97 | src
98 |
99 |
100 | src
101 |
102 |
103 | src
104 |
105 |
106 | 头文件
107 |
108 |
109 | src
110 |
111 |
112 | src
113 |
114 |
115 | src
116 |
117 |
118 | src
119 |
120 |
121 | src
122 |
123 |
124 | src\Services
125 |
126 |
127 | src\Services
128 |
129 |
130 | src\Services
131 |
132 |
133 | Sample\Services
134 |
135 |
136 | src
137 |
138 |
139 | src
140 |
141 |
142 | src
143 |
144 |
145 | src
146 |
147 |
148 | src
149 |
150 |
151 |
152 |
153 | 源文件
154 |
155 |
156 | 源文件
157 |
158 |
159 | src
160 |
161 |
162 | src
163 |
164 |
165 | src
166 |
167 |
168 | src
169 |
170 |
171 | src
172 |
173 |
174 | src
175 |
176 |
177 | src
178 |
179 |
180 | src
181 |
182 |
183 | src
184 |
185 |
186 | src
187 |
188 |
189 | src
190 |
191 |
192 | src
193 |
194 |
195 | src
196 |
197 |
198 | src
199 |
200 |
201 | src
202 |
203 |
204 | src\Services
205 |
206 |
207 | src\Services
208 |
209 |
210 | Sample\Services
211 |
212 |
213 | src
214 |
215 |
216 | src
217 |
218 |
219 | src
220 |
221 |
222 | src
223 |
224 |
225 |
--------------------------------------------------------------------------------
/NTFS.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wyrover/CodeLib/cee0615b2cba6d1281b93177aea7a64c4a39e1de/NTFS.cpp
--------------------------------------------------------------------------------
/NTFS.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wyrover/CodeLib/cee0615b2cba6d1281b93177aea7a64c4a39e1de/NTFS.h
--------------------------------------------------------------------------------
/ReadMe.txt:
--------------------------------------------------------------------------------
1 | ========================================================================
2 | 控制台应用程序:CodeLib 项目概述
3 | ========================================================================
4 |
5 | 应用程序向导已为您创建了此 CodeLib 应用程序。
6 |
7 | 本文件概要介绍组成 CodeLib 应用程序的每个文件的内容。
8 |
9 |
10 | CodeLib.vcxproj
11 | 这是使用应用程序向导生成的 VC++ 项目的主项目文件,其中包含生成该文件的 Visual C++ 的版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。
12 |
13 | CodeLib.vcxproj.filters
14 | 这是使用“应用程序向导”生成的 VC++ 项目筛选器文件。它包含有关项目文件与筛选器之间的关联信息。在 IDE 中,通过这种关联,在特定节点下以分组形式显示具有相似扩展名的文件。例如,“.cpp”文件与“源文件”筛选器关联。
15 |
16 | CodeLib.cpp
17 | 这是主应用程序源文件。
18 |
19 | /////////////////////////////////////////////////////////////////////////////
20 | 其他标准文件:
21 |
22 | StdAfx.h, StdAfx.cpp
23 | 这些文件用于生成名为 CodeLib.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。
24 |
25 | /////////////////////////////////////////////////////////////////////////////
26 | 其他注释:
27 |
28 | 应用程序向导使用“TODO:”注释来指示应添加或自定义的源代码部分。
29 |
30 | /////////////////////////////////////////////////////////////////////////////
31 |
--------------------------------------------------------------------------------
/Sample/Services/SampleService.cpp:
--------------------------------------------------------------------------------
1 | /****************************** Module Header ******************************\
2 | * Module Name: SampleService.cpp
3 | * Project: CppWindowsService
4 | * Copyright (c) Microsoft Corporation.
5 | *
6 | * Provides a sample service class that derives from the service base class -
7 | * CServiceBase. The sample service logs the service start and stop
8 | * information to the Application event log, and shows how to run the main
9 | * function of the service in a thread pool worker thread.
10 | *
11 | * This source is subject to the Microsoft Public License.
12 | * See http://www.microsoft.com/en-us/openness/resources/licenses.aspx#MPL.
13 | * All other rights reserved.
14 | *
15 | * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
16 | * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
17 | * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
18 | \***************************************************************************/
19 |
20 | #pragma region Includes
21 | #include "stdafx.h"
22 | #include "SampleService.h"
23 | #include "..\src\Services\ThreadPool.h"
24 | #pragma endregion
25 |
26 |
27 | CSampleService::CSampleService(PWSTR pszServiceName,
28 | BOOL fCanStop,
29 | BOOL fCanShutdown,
30 | BOOL fCanPauseContinue)
31 | : CServiceBase(pszServiceName, fCanStop, fCanShutdown, fCanPauseContinue)
32 | {
33 | m_fStopping = FALSE;
34 |
35 | // Create a manual-reset event that is not signaled at first to indicate
36 | // the stopped signal of the service.
37 | m_hStoppedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
38 | if (m_hStoppedEvent == NULL)
39 | {
40 | throw GetLastError();
41 | }
42 | }
43 |
44 |
45 | CSampleService::~CSampleService(void)
46 | {
47 | if (m_hStoppedEvent)
48 | {
49 | CloseHandle(m_hStoppedEvent);
50 | m_hStoppedEvent = NULL;
51 | }
52 | }
53 |
54 |
55 | //
56 | // FUNCTION: CSampleService::OnStart(DWORD, LPWSTR *)
57 | //
58 | // PURPOSE: The function is executed when a Start command is sent to the
59 | // service by the SCM or when the operating system starts (for a service
60 | // that starts automatically). It specifies actions to take when the
61 | // service starts. In this code sample, OnStart logs a service-start
62 | // message to the Application log, and queues the main service function for
63 | // execution in a thread pool worker thread.
64 | //
65 | // PARAMETERS:
66 | // * dwArgc - number of command line arguments
67 | // * lpszArgv - array of command line arguments
68 | //
69 | // NOTE: A service application is designed to be long running. Therefore,
70 | // it usually polls or monitors something in the system. The monitoring is
71 | // set up in the OnStart method. However, OnStart does not actually do the
72 | // monitoring. The OnStart method must return to the operating system after
73 | // the service's operation has begun. It must not loop forever or block. To
74 | // set up a simple monitoring mechanism, one general solution is to create
75 | // a timer in OnStart. The timer would then raise events in your code
76 | // periodically, at which time your service could do its monitoring. The
77 | // other solution is to spawn a new thread to perform the main service
78 | // functions, which is demonstrated in this code sample.
79 | //
80 | void CSampleService::OnStart(DWORD dwArgc, LPWSTR *lpszArgv)
81 | {
82 | // Log a service start message to the Application log.
83 | WriteEventLogEntry(L"CppWindowsService in OnStart",
84 | EVENTLOG_INFORMATION_TYPE);
85 |
86 | // Queue the main service function for execution in a worker thread.
87 | CThreadPool::QueueUserWorkItem(&CSampleService::ServiceWorkerThread, this);
88 | }
89 |
90 |
91 | //
92 | // FUNCTION: CSampleService::ServiceWorkerThread(void)
93 | //
94 | // PURPOSE: The method performs the main function of the service. It runs
95 | // on a thread pool worker thread.
96 | //
97 | void CSampleService::ServiceWorkerThread(void)
98 | {
99 | // Periodically check if the service is stopping.
100 | while (!m_fStopping)
101 | {
102 | // Perform main service function here...
103 |
104 | ::Sleep(2000); // Simulate some lengthy operations.
105 | }
106 |
107 | // Signal the stopped event.
108 | SetEvent(m_hStoppedEvent);
109 | }
110 |
111 |
112 | //
113 | // FUNCTION: CSampleService::OnStop(void)
114 | //
115 | // PURPOSE: The function is executed when a Stop command is sent to the
116 | // service by SCM. It specifies actions to take when a service stops
117 | // running. In this code sample, OnStop logs a service-stop message to the
118 | // Application log, and waits for the finish of the main service function.
119 | //
120 | // COMMENTS:
121 | // Be sure to periodically call ReportServiceStatus() with
122 | // SERVICE_STOP_PENDING if the procedure is going to take long time.
123 | //
124 | void CSampleService::OnStop()
125 | {
126 | // Log a service stop message to the Application log.
127 | WriteEventLogEntry(L"CppWindowsService in OnStop",
128 | EVENTLOG_INFORMATION_TYPE);
129 |
130 | // Indicate that the service is stopping and wait for the finish of the
131 | // main service function (ServiceWorkerThread).
132 | m_fStopping = TRUE;
133 | if (WaitForSingleObject(m_hStoppedEvent, INFINITE) != WAIT_OBJECT_0)
134 | {
135 | throw GetLastError();
136 | }
137 | }
--------------------------------------------------------------------------------
/Sample/Services/SampleService.h:
--------------------------------------------------------------------------------
1 | /****************************** Module Header ******************************\
2 | * Module Name: SampleService.h
3 | * Project: CppWindowsService
4 | * Copyright (c) Microsoft Corporation.
5 | *
6 | * Provides a sample service class that derives from the service base class -
7 | * CServiceBase. The sample service logs the service start and stop
8 | * information to the Application event log, and shows how to run the main
9 | * function of the service in a thread pool worker thread.
10 | *
11 | * This source is subject to the Microsoft Public License.
12 | * See http://www.microsoft.com/en-us/openness/resources/licenses.aspx#MPL.
13 | * All other rights reserved.
14 | *
15 | * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
16 | * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
17 | * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
18 | \***************************************************************************/
19 |
20 | #pragma once
21 | #include "..\src\Services\ServiceBase.h"
22 |
23 | class CSampleService : public CServiceBase
24 | {
25 | public:
26 |
27 | CSampleService(PWSTR pszServiceName,
28 | BOOL fCanStop = TRUE,
29 | BOOL fCanShutdown = TRUE,
30 | BOOL fCanPauseContinue = FALSE);
31 | virtual ~CSampleService(void);
32 |
33 | protected:
34 |
35 | virtual void OnStart(DWORD dwArgc, PWSTR *pszArgv);
36 | virtual void OnStop();
37 |
38 | void ServiceWorkerThread(void);
39 |
40 | private:
41 |
42 | BOOL m_fStopping;
43 | HANDLE m_hStoppedEvent;
44 | };
--------------------------------------------------------------------------------
/Test.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wyrover/CodeLib/cee0615b2cba6d1281b93177aea7a64c4a39e1de/Test.cpp
--------------------------------------------------------------------------------
/include/Common.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 | #include "IProcess.h"
5 | #include "IIni.h"
6 | #include "IFileMap.h"
7 | #include "IMiniDump.h"
8 | #include "IThread.h"
9 | #include "ILPC.h"
10 |
11 | namespace CODELIB
12 | {
13 | enum INTERFACE_NAME
14 | {
15 | CODELIB_PROCESS,
16 | CODELIB_INIFILE,
17 | CODELIB_FILEMAP,
18 | CODELIB_MINIDUMP,
19 | CODELIB_THREAD,
20 | CODELIB_LPCSERVER,
21 | CODELIB_LPCCLIENT,
22 | CODELIB_NAMEDPIPESERVER,
23 | CODELIB_NAMEDPIPECLIENT
24 | };
25 |
26 | LPVOID CreateInstance(INTERFACE_NAME interfaceName,LPVOID lpCreateParam=NULL);
27 | }
28 |
--------------------------------------------------------------------------------
/include/IFileMap.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "Common.h"
3 |
4 | namespace CODELIB
5 | {
6 | class IFileMap
7 | {
8 | public:
9 | virtual ~IFileMap() = 0 {};
10 | virtual BOOL Create(LPCTSTR lpszFileName, DWORD dwProtect = PAGE_READONLY) = 0;
11 | virtual void Close() = 0;
12 | virtual LPVOID GetBuffer() = 0;
13 | virtual DWORD GetFileSize() = 0;
14 | };
15 | }
--------------------------------------------------------------------------------
/include/IIPCInterface.h:
--------------------------------------------------------------------------------
1 | /********************************************************************
2 | created: 2014/04/26
3 | file base: IIPCInterface
4 | author: redcode
5 | purpose: the interface for the IPC
6 | *********************************************************************/
7 |
8 | #pragma once
9 | #include
10 | #include
11 |
12 | #define pure_virtual __declspec(novtable)
13 |
14 | struct pure_virtual IIPCMessage
15 | {
16 | virtual ~IIPCMessage() = 0 {};
17 | virtual DWORD GetID() = 0;
18 | virtual BOOL GetBuffer(LPVOID lpBuf, LPDWORD dwBufferSize) = 0;
19 | };
20 |
21 | struct pure_virtual IIPCConnector
22 | {
23 | virtual ~IIPCConnector() = 0 {};
24 | virtual DWORD GetSID() = 0;
25 | virtual LPCTSTR GetName() = 0;
26 | virtual BOOL PostMessage(LPCVOID lpBuf, DWORD dwBufSize) = 0;
27 | virtual BOOL RequestAndReply(LPVOID lpSendBuf, DWORD dwSendBufSize, LPVOID lpReplyBuf, DWORD dwReplyBufSize, DWORD dwTimeout = 3000) = 0;
28 | };
29 |
30 | struct pure_virtual IIPCConnectorIterator
31 | {
32 | virtual ~IIPCConnectorIterator() = 0 {};
33 | virtual void Begin() = 0;
34 | virtual BOOL End() = 0;
35 | virtual void Next() = 0;
36 | virtual IIPCConnector* GetCurrent() = 0;
37 | };
38 |
39 | typedef std::vector ConnectorMap;
40 |
41 | struct pure_virtual IIPCObject
42 | {
43 | virtual ~IIPCObject() = 0 {};
44 | virtual BOOL Create(LPCTSTR lpPipeName) = 0;
45 | virtual void Close() = 0;
46 | virtual IIPCConnectorIterator* GetClients() = 0;
47 | };
48 |
49 | struct pure_virtual IIPCEvent
50 | {
51 | virtual ~IIPCEvent() = 0 {};
52 | virtual void OnRequest(IIPCObject* pServer, IIPCConnector* pClient, LPCVOID lpBuf, DWORD dwBufSize) = 0;
53 | };
--------------------------------------------------------------------------------
/include/IIni.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "Common.h"
3 |
4 | namespace CODELIB
5 | {
6 | class IIniFile
7 | {
8 | public:
9 | virtual ~IIniFile() = 0 {};
10 | virtual BOOL Open(LPCTSTR lpszFileName) = 0;
11 | virtual void Close() = 0;
12 | virtual DWORD ReadDword(LPCTSTR Section, LPCTSTR key) = 0;
13 | virtual DOUBLE ReadDouble(LPCTSTR Section, LPCTSTR key) = 0;
14 | virtual DWORD ReadString(LPCTSTR Section, LPCTSTR key, TCHAR* Buf) = 0;
15 | virtual BOOL WriteDword(LPCTSTR Section, LPCTSTR key, DWORD Value) = 0;
16 | virtual BOOL WriteDouble(LPCTSTR Section, LPCTSTR key, double Value) = 0;
17 | virtual BOOL WriteString(LPCTSTR Section, LPCTSTR key, LPCTSTR Value) = 0;
18 | };
19 | }
--------------------------------------------------------------------------------
/include/ILPC.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "ntdll.h"
3 |
4 | namespace CODELIB
5 | {
6 | enum MESSAGE_TYPE
7 | {
8 | LPC_MESSAGE_REQUEST,
9 | LPC_MESSAGE_REPLY
10 | };
11 |
12 | class IMessage
13 | {
14 | public:
15 | virtual ~IMessage() = 0 {};
16 | virtual PPORT_MESSAGE GetHeader() = 0;
17 | virtual MESSAGE_TYPE GetMessageType() = 0;
18 | virtual LPVOID GetBuffer(DWORD& dwBufferSize) = 0;
19 | virtual void SetMessageType(MESSAGE_TYPE msgType) = 0;
20 | virtual void SetBuffer(LPVOID lpBuf, DWORD dwBufSize) = 0;
21 | };
22 |
23 | class ISender
24 | {
25 | public:
26 | virtual ~ISender() = 0 {};
27 | virtual DWORD GetSID() = 0;
28 | virtual BOOL SendMessage(IMessage* pMessage) = 0;
29 | virtual BOOL PostMessage(IMessage* pMessage) = 0;
30 | };
31 |
32 | class ILPC
33 | {
34 | public:
35 | virtual ~ILPC() = 0 {};
36 | virtual BOOL Create(LPCTSTR lpPortName) = 0;
37 | virtual void Close() = 0;
38 | };
39 |
40 | class ILPCEvent
41 | {
42 | public:
43 | virtual ~ILPCEvent() = 0 {};
44 | virtual void OnCreate(ILPC* pLPC) = 0;
45 | virtual void OnClose(ILPC* pLPC) = 0;
46 | virtual BOOL OnConnect(ILPC* pLPC, ISender* pSender) = 0;
47 | virtual void OnDisConnect(ILPC* pLPC, ISender* pSender) = 0;
48 | virtual void OnRecv(ILPC* pLPC, ISender* pSender, IMessage* pMessage) = 0;
49 | virtual void OnRecvAndReply(ILPC* pLPC, ISender* pSender, IMessage* pReceiveMsg, IMessage* pReplyMsg) = 0;
50 | };
51 | }
--------------------------------------------------------------------------------
/include/IMiniDump.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "Common.h"
3 |
4 | namespace CODELIB
5 | {
6 | class IMiniDump
7 | {
8 | public:
9 | virtual ~IMiniDump()=0{};
10 | virtual void Active(BOOL bEnable=TRUE)=0;
11 | };
12 | }
--------------------------------------------------------------------------------
/include/IProcess.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "Common.h"
3 |
4 | namespace CODELIB
5 | {
6 | enum INTEGRITYLEVEL
7 | {
8 | INTEGRITY_UNKNOWN,
9 | LOW_INTEGRITY,
10 | MEDIUM_INTEGRITY,
11 | HIGH_INTEGRITY,
12 | };
13 |
14 | class IProcess
15 | {
16 | public:
17 | virtual ~IProcess() = 0 {};
18 | virtual BOOL IsOpened()=0;
19 | virtual BOOL Open(DWORD dwPID) = 0;
20 | virtual void Close() = 0;
21 | virtual BOOL Terminate() = 0;
22 | virtual BOOL ReadMemory(LPCVOID lpBase, LPVOID lpBuf, DWORD dwWantRead) = 0;
23 | virtual BOOL WriteMemory(LPVOID lpBase, LPCVOID lpBuf, DWORD dwWantWrite) = 0;
24 | virtual DWORD GetPID() = 0;
25 | virtual LPCTSTR GetFullPathName() = 0;
26 | virtual BOOL GetIntegrityLevel(INTEGRITYLEVEL* pLevel) = 0;
27 | virtual HANDLE GetHandle() = 0;
28 | virtual SIZE_T VirtualQueryEx(LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength) = 0;
29 | };
30 | }
--------------------------------------------------------------------------------
/include/IThread.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "Common.h"
3 | namespace CODELIB
4 | {
5 | class IThread
6 | {
7 | public:
8 | virtual ~IThread() = 0 {};
9 | virtual BOOL Start() = 0;
10 | virtual BOOL Stop() = 0;
11 | virtual BOOL Run() = 0;
12 | };
13 | }
--------------------------------------------------------------------------------
/include/IVolumeParse.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 |
4 | class IVolumeParse
5 | {
6 | public:
7 | virtual ~IVolumeParse()=0{};
8 |
9 | virtual BOOL ScanFile(LPCTSTR lpszVolumeName)=0;
10 |
11 | virtual BOOL ScanFileChange(LPCTSTR lpszVolume)=0;
12 | };
--------------------------------------------------------------------------------
/include/ntdll.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wyrover/CodeLib/cee0615b2cba6d1281b93177aea7a64c4a39e1de/include/ntdll.h
--------------------------------------------------------------------------------
/src/CdfsVolumeParse.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 | #include "CdfsVolumeParse.h"
3 |
4 |
5 | CCdfsVolumeParse::CCdfsVolumeParse(void)
6 | {
7 | }
8 |
9 |
10 | CCdfsVolumeParse::~CCdfsVolumeParse(void)
11 | {
12 | }
13 |
14 | BOOL CCdfsVolumeParse::ScanFile( LPCTSTR lpszVolumeName )
15 | {
16 | return FALSE;
17 | }
18 |
19 | BOOL CCdfsVolumeParse::ScanFileChange( LPCTSTR lpszVolume )
20 | {
21 | return FALSE;
22 | }
23 |
--------------------------------------------------------------------------------
/src/CdfsVolumeParse.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "IVolumeParse.h"
3 | class CCdfsVolumeParse : public IVolumeParse
4 | {
5 | public:
6 | CCdfsVolumeParse(void);
7 | virtual ~CCdfsVolumeParse(void);
8 |
9 | virtual BOOL ScanFile( LPCTSTR lpszVolumeName );
10 |
11 | virtual BOOL ScanFileChange( LPCTSTR lpszVolume );
12 |
13 | };
14 |
15 |
--------------------------------------------------------------------------------
/src/Common.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 | #include "ProcessImpl.h"
3 | #include "IniFileImpl.h"
4 | #include "FileMapImpl.h"
5 | #include "MiniDumpImpl.h"
6 | #include "ThreadImpl.h"
7 | #include "LPCServerImpl.h"
8 | #include "LPCClientImpl.h"
9 | #include "NamedPipeServerImpl.h"
10 | #include "NamedPipeClientImpl.h"
11 |
12 | namespace CODELIB
13 | {
14 | LPVOID CreateInstance(INTERFACE_NAME interfaceName, LPVOID lpCreateParam)
15 | {
16 | LPVOID pInterface = NULL;
17 |
18 | switch(interfaceName)
19 | {
20 | case CODELIB_PROCESS:
21 | {
22 | pInterface = new CODELIB::CProcessImpl;
23 | break;
24 | }
25 |
26 | case CODELIB_INIFILE:
27 | {
28 | pInterface = new CODELIB::CIniFileImpl;
29 | break;
30 | }
31 |
32 | case CODELIB_FILEMAP:
33 | {
34 | pInterface = new CODELIB::CFileMapImpl;
35 | break;
36 | }
37 |
38 | case CODELIB_MINIDUMP:
39 | {
40 | pInterface = new CODELIB::CMiniDumpImpl;
41 | break;
42 | }
43 |
44 | case CODELIB_THREAD:
45 | {
46 | pInterface = new CODELIB::CThreadImpl;
47 | break;
48 | }
49 |
50 | case CODELIB_LPCSERVER:
51 | {
52 | pInterface = new CODELIB::CLPCServerImpl((ILPCEvent*)lpCreateParam);
53 | break;
54 | }
55 |
56 | case CODELIB_LPCCLIENT:
57 | {
58 | pInterface = new CODELIB::CLPCClientImpl((ILPCEvent*)lpCreateParam);
59 | break;
60 | }
61 |
62 | case CODELIB_NAMEDPIPESERVER:
63 | {
64 | pInterface = new CNamedPipeServerImpl((IIPCEvent*)lpCreateParam);
65 | break;
66 | }
67 |
68 | case CODELIB_NAMEDPIPECLIENT:
69 | {
70 | pInterface = new CNamedPipeClientImpl((IIPCEvent*)lpCreateParam);
71 | break;
72 | }
73 |
74 | default:
75 | break;
76 | }
77 |
78 | return pInterface;
79 | }
80 | }
81 |
82 |
--------------------------------------------------------------------------------
/src/CommonFunc.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 | #include "CommonFunc.h"
3 | #include
4 |
5 | DWORD GetMainThreadID( DWORD dwPID )
6 | {
7 | DWORD dwThreadID = dwPID;
8 | THREADENTRY32 te32 = {sizeof(te32)};
9 | HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, dwPID);
10 |
11 | if(Thread32First(hThreadSnap, &te32))
12 | {
13 | do
14 | {
15 | if(dwPID == te32.th32OwnerProcessID)
16 | {
17 | dwThreadID = te32.th32ThreadID;
18 | break;
19 | }
20 | }
21 | while(Thread32Next(hThreadSnap, &te32));
22 | }
23 |
24 | return dwThreadID;
25 | }
26 |
27 | HMODULE WINAPI ModuleFromAddress(PVOID pv)
28 | {
29 | MEMORY_BASIC_INFORMATION mbi;
30 | if (::VirtualQuery(pv, &mbi, sizeof(mbi)) != 0)
31 | {
32 | return (HMODULE)mbi.AllocationBase;
33 | }
34 | else
35 | {
36 | return NULL;
37 | }
38 | }
39 |
40 |
--------------------------------------------------------------------------------
/src/CommonFunc.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wyrover/CodeLib/cee0615b2cba6d1281b93177aea7a64c4a39e1de/src/CommonFunc.h
--------------------------------------------------------------------------------
/src/ConsoleDebug.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 | #include
5 |
6 | class CConsoleDebug
7 | {
8 | public:
9 | CConsoleDebug(): m_pFile(NULL)
10 | {
11 | #ifdef _DEBUG
12 | AllocConsole();
13 | freopen_s(&m_pFile, "CONOUT$", "w", stdout);
14 | HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE);
15 | // SetConsoleTextAttribute(hCon, FOREGROUND_INTENSITY);
16 | COORD size;
17 | size.X=80;
18 | size.Y=3000;
19 | ::SetConsoleScreenBufferSize(hCon, size);
20 | std::ios_base::sync_with_stdio();
21 | #endif
22 | }
23 |
24 | virtual ~CConsoleDebug()
25 | {
26 | #ifdef _DEBUG
27 | fclose(m_pFile);
28 | m_pFile = NULL;
29 | FreeConsole();
30 | #endif
31 | }
32 | private:
33 | FILE* m_pFile;
34 | };
--------------------------------------------------------------------------------
/src/Fat16VolumeParse.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 | #include "Fat16VolumeParse.h"
3 |
4 |
5 | CFat16VolumeParse::CFat16VolumeParse(void)
6 | {
7 | }
8 |
9 |
10 | CFat16VolumeParse::~CFat16VolumeParse(void)
11 | {
12 | }
13 |
14 | BOOL CFat16VolumeParse::ScanFile( LPCTSTR lpszVolumeName )
15 | {
16 | return FALSE;
17 | }
18 |
19 | BOOL CFat16VolumeParse::ScanFileChange( LPCTSTR lpszVolume )
20 | {
21 | return FALSE;
22 | }
23 |
--------------------------------------------------------------------------------
/src/Fat16VolumeParse.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "IVolumeParse.h"
3 | class CFat16VolumeParse : public IVolumeParse
4 | {
5 | public:
6 | CFat16VolumeParse(void);
7 | virtual ~CFat16VolumeParse(void);
8 |
9 | virtual BOOL ScanFile( LPCTSTR lpszVolumeName );
10 |
11 | virtual BOOL ScanFileChange( LPCTSTR lpszVolume );
12 |
13 | };
14 |
15 |
--------------------------------------------------------------------------------
/src/Fat32VolumeParse.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 | #include "Fat32VolumeParse.h"
3 |
4 |
5 | CFat32VolumeParse::CFat32VolumeParse(void)
6 | {
7 | }
8 |
9 |
10 | CFat32VolumeParse::~CFat32VolumeParse(void)
11 | {
12 | }
13 |
14 | BOOL CFat32VolumeParse::ScanFile( LPCTSTR lpszVolumeName )
15 | {
16 | return FALSE;
17 | }
18 |
19 | BOOL CFat32VolumeParse::ScanFileChange( LPCTSTR lpszVolume )
20 | {
21 | return FALSE;
22 | }
23 |
--------------------------------------------------------------------------------
/src/Fat32VolumeParse.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "IVolumeParse.h"
3 |
4 | class CFat32VolumeParse : public IVolumeParse
5 | {
6 | public:
7 | CFat32VolumeParse(void);
8 | virtual ~CFat32VolumeParse(void);
9 |
10 | virtual BOOL ScanFile( LPCTSTR lpszVolumeName );
11 |
12 | virtual BOOL ScanFileChange( LPCTSTR lpszVolume );
13 |
14 | };
15 |
16 |
--------------------------------------------------------------------------------
/src/FileMapImpl.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 | #include "FileMapImpl.h"
3 | #include
4 |
5 | namespace CODELIB
6 | {
7 | CFileMapImpl::CFileMapImpl(): m_hFileMap(NULL)
8 | , m_dwFileMapSize(0)
9 | , m_lpMapBuf(NULL)
10 | {
11 |
12 | }
13 |
14 | CFileMapImpl::~CFileMapImpl()
15 | {
16 |
17 | }
18 |
19 | BOOL CFileMapImpl::Create(LPCTSTR lpszFileName, DWORD dwProtect)
20 | {
21 | if(!PathFileExists(lpszFileName))
22 | {
23 | return FALSE;
24 | }
25 |
26 | if(NULL != m_hFileMap)
27 | {
28 | return TRUE;
29 | }
30 |
31 | HANDLE hFile =::CreateFile(lpszFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
32 | OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
33 |
34 | if(INVALID_HANDLE_VALUE == hFile)
35 | {
36 | return FALSE;
37 | }
38 |
39 | m_dwFileMapSize =::GetFileSize(hFile, 0);
40 |
41 | m_hFileMap =::CreateFileMapping(hFile, NULL, dwProtect, 0, 0, NULL);
42 |
43 | if(NULL == m_hFileMap)
44 | {
45 | CloseHandle(hFile);
46 | return FALSE;
47 | }
48 |
49 | m_lpMapBuf =::MapViewOfFile(m_hFileMap, FILE_MAP_READ, 0, 0, 0);
50 |
51 | if(NULL == m_lpMapBuf)
52 | {
53 | Close();
54 | CloseHandle(hFile);
55 | return FALSE;
56 | }
57 |
58 | CloseHandle(hFile);
59 |
60 | return TRUE;
61 | }
62 |
63 | void CFileMapImpl::Close()
64 | {
65 | if(NULL != m_lpMapBuf)
66 | {
67 | UnmapViewOfFile(m_lpMapBuf);
68 | m_lpMapBuf = NULL;
69 | }
70 |
71 | if(NULL != m_hFileMap)
72 | {
73 | CloseHandle(m_hFileMap);
74 | m_hFileMap = NULL;
75 | }
76 |
77 | m_dwFileMapSize = 0;
78 | }
79 |
80 | LPVOID CFileMapImpl::GetBuffer()
81 | {
82 | return m_lpMapBuf;
83 | }
84 |
85 | DWORD CFileMapImpl::GetFileSize()
86 | {
87 | return m_dwFileMapSize;
88 | }
89 |
90 | }
--------------------------------------------------------------------------------
/src/FileMapImpl.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "Common.h"
3 | #include "IFileMap.h"
4 |
5 | namespace CODELIB
6 | {
7 | class CFileMapImpl : public IFileMap
8 | {
9 | public:
10 | CFileMapImpl();
11 | virtual ~CFileMapImpl();
12 |
13 | BOOL Create(LPCTSTR lpszFileName, DWORD dwProtect = PAGE_READONLY);
14 | void Close();
15 | LPVOID GetBuffer();
16 | DWORD GetFileSize();
17 | private:
18 | HANDLE m_hFileMap;
19 | LPVOID m_lpMapBuf;
20 | DWORD m_dwFileMapSize;
21 | };
22 | }
--------------------------------------------------------------------------------
/src/FileScan.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wyrover/CodeLib/cee0615b2cba6d1281b93177aea7a64c4a39e1de/src/FileScan.cpp
--------------------------------------------------------------------------------
/src/FileScan.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wyrover/CodeLib/cee0615b2cba6d1281b93177aea7a64c4a39e1de/src/FileScan.h
--------------------------------------------------------------------------------
/src/ICallBack.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 |
4 | typedef enum REQUEST_TYPE
5 | {
6 | REQUEST_KEYBOARDHOOK,
7 | REQUEST_MEMSCAN
8 | };
9 |
10 | class IRequest
11 | {
12 | public:
13 | virtual ~IRequest() = 0 {};
14 | virtual REQUEST_TYPE GetType() = 0;
15 | };
16 |
17 | class CRequestBase : public IRequest
18 | {
19 | public:
20 | CRequestBase(REQUEST_TYPE requestType): m_requestType(requestType) {}
21 |
22 | virtual ~CRequestBase() {}
23 |
24 | virtual REQUEST_TYPE GetType()
25 | {
26 | return m_requestType;
27 | }
28 |
29 | private:
30 | REQUEST_TYPE m_requestType;
31 | };
32 | class IRequestHandler
33 | {
34 | public:
35 | virtual ~IRequestHandler() = 0 {};
36 | virtual BOOL HandleRequest(IRequest* pRequest) = 0;
37 | };
--------------------------------------------------------------------------------
/src/IPCMessage.h:
--------------------------------------------------------------------------------
1 | /********************************************************************
2 | created: 2014/04/26
3 | file base: IPCMessage
4 | author: redcode
5 | purpose: the implement for the NamedPipe Message struct
6 | *********************************************************************/
7 |
8 | #pragma once
9 | #include "IIPCInterface.h"
10 |
11 | enum IPC_OVERLAPPED_TYPE
12 | {
13 | IPC_OVERLAPPED_UKNOWN,
14 | IPC_OVERLAPPED_CONNECT,
15 | IPC_OVERLAPPED_READ,
16 | IPC_OVERLAPPED_WRITE,
17 | };
18 |
19 | const int FIXED_MAXIMUM_MESSAGE = 4096;
20 |
21 | typedef struct _IPC_OVERLAPPED_HEADER : OVERLAPPED
22 | {
23 | IPC_OVERLAPPED_TYPE ovType;
24 | } IPC_OVERLAPPED_HEADER, *LPIPC_OVERALPPED_HEADER;
25 |
26 | typedef struct _IPC_DATA_PACKAGE
27 | {
28 | DWORD dwPackageID; // package id
29 | DWORD dwUserDataSize; // custom data size
30 | BYTE lpUserData[FIXED_MAXIMUM_MESSAGE]; // custom buf
31 | DWORD dwTotalSize; // the total size of the package
32 | FILETIME ftOccurance; // the time of the package been used
33 |
34 | } IPC_DATA_PACKAGE, *LPIPC_DATA_PACKAGE;
35 |
36 | struct CNamedPipeMessage
37 | {
38 | friend class CNamedPipeConnector;
39 | friend class CNamedPipeClientImpl;
40 | private:
41 | IPC_OVERLAPPED_HEADER m_ovHeader; // overlapped header
42 | IPC_DATA_PACKAGE m_package; // the communication package
43 | public:
44 | CNamedPipeMessage(LPCVOID lpData, DWORD dwDataSize , IPC_OVERLAPPED_TYPE ovType = IPC_OVERLAPPED_UKNOWN, DWORD dwPackageID = 0)
45 | {
46 | // init overlapped header
47 | ZeroMemory(this, sizeof(CNamedPipeMessage));
48 | m_ovHeader.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
49 | m_ovHeader.ovType = ovType;
50 |
51 | // init package
52 | m_package.dwPackageID = dwPackageID;
53 |
54 | if(NULL != lpData && dwDataSize <= FIXED_MAXIMUM_MESSAGE)
55 | {
56 | memcpy_s(m_package.lpUserData, FIXED_MAXIMUM_MESSAGE, lpData, dwDataSize);
57 | m_package.dwUserDataSize = dwDataSize;
58 | }
59 |
60 | m_package.dwTotalSize = sizeof(IPC_DATA_PACKAGE) - FIXED_MAXIMUM_MESSAGE + dwDataSize;
61 | GetSystemTimeAsFileTime(&m_package.ftOccurance);
62 | }
63 |
64 | ~CNamedPipeMessage()
65 | {
66 | if(NULL != m_ovHeader.hEvent)
67 | {
68 | CloseHandle(m_ovHeader.hEvent);
69 | m_ovHeader.hEvent = NULL;
70 | }
71 |
72 | ZeroMemory(this, sizeof(CNamedPipeMessage));
73 | }
74 |
75 | LPOVERLAPPED GetOvHeader()
76 | {
77 | return &m_ovHeader;
78 | }
79 |
80 | IPC_OVERLAPPED_TYPE GetOvType()
81 | {
82 | return m_ovHeader.ovType;
83 | }
84 |
85 | DWORD GetID()
86 | {
87 | return m_package.dwPackageID;
88 | }
89 |
90 | BOOL GetCustomBuffer(LPVOID* lpBuf, LPDWORD dwBufferSize)
91 | {
92 | assert(NULL != lpBuf && NULL == *lpBuf);
93 |
94 | if(m_package.dwUserDataSize > 0)
95 | {
96 | *lpBuf = m_package.lpUserData;
97 |
98 | if(NULL != dwBufferSize)
99 | *dwBufferSize = m_package.dwUserDataSize;
100 |
101 | return TRUE;
102 | }
103 |
104 | return FALSE;
105 | }
106 | };
107 |
--------------------------------------------------------------------------------
/src/IniFileImpl.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 | #include "IniFileImpl.h"
3 | #include
4 | #pragma comment(lib,"shlwapi.lib")
5 |
6 | namespace CODELIB
7 | {
8 | CIniFileImpl::CIniFileImpl()
9 | {
10 | ZeroMemory(m_sIniFileName, MAX_PATH);
11 | }
12 |
13 | CIniFileImpl::~CIniFileImpl()
14 | {
15 |
16 | }
17 |
18 | BOOL CIniFileImpl::Open(LPCTSTR lpszFileName)
19 | {
20 | if(!PathFileExists(lpszFileName))
21 | return FALSE;
22 |
23 | if(NULL == lpszFileName)
24 | return FALSE;
25 |
26 | memcpy_s(m_sIniFileName, MAX_PATH, lpszFileName, _tcslen(lpszFileName)*sizeof(TCHAR));
27 | return TRUE;
28 | }
29 |
30 | void CIniFileImpl::Close()
31 | {
32 |
33 | }
34 |
35 | DWORD CIniFileImpl::ReadDword(LPCTSTR Section, LPCTSTR key)
36 | {
37 | return GetPrivateProfileInt(Section, key, 0, m_sIniFileName);
38 | }
39 |
40 | DOUBLE CIniFileImpl::ReadDouble(LPCTSTR Section, LPCTSTR key)
41 | {
42 | TCHAR sValue[MAX_PATH] = {0};
43 | ReadString(Section, key, sValue);
44 | return _tstof(sValue);
45 | }
46 |
47 | DWORD CIniFileImpl::ReadString(LPCTSTR Section, LPCTSTR key, TCHAR* Buf)
48 | {
49 | DWORD dwReaded = GetPrivateProfileString(Section, key, 0, Buf, MAX_PATH, m_sIniFileName);
50 | return dwReaded + 1;
51 | }
52 |
53 | BOOL CIniFileImpl::WriteDword(LPCTSTR Section, LPCTSTR key, DWORD Value)
54 | {
55 | TCHAR sValue[MAX_PATH] = {0};
56 | _stprintf_s(sValue, MAX_PATH, _T("%u"), Value);
57 | return WritePrivateProfileString(Section, key, sValue, m_sIniFileName);
58 | }
59 |
60 | BOOL CIniFileImpl::WriteDouble(LPCTSTR Section, LPCTSTR key, double Value)
61 | {
62 | TCHAR sValue[MAX_PATH] = {0};
63 | _stprintf_s(sValue, MAX_PATH, _T("%f"), Value);
64 | return WritePrivateProfileString(Section, key, sValue, m_sIniFileName);
65 | }
66 |
67 | BOOL CIniFileImpl::WriteString(LPCTSTR Section, LPCTSTR key, LPCTSTR Value)
68 | {
69 | return WritePrivateProfileString(Section, key, Value, m_sIniFileName);
70 | }
71 |
72 |
73 |
74 | }
--------------------------------------------------------------------------------
/src/IniFileImpl.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "IIni.h"
3 |
4 | namespace CODELIB
5 | {
6 | class CIniFileImpl : public IIniFile
7 | {
8 | public:
9 | CIniFileImpl();
10 | virtual ~CIniFileImpl();
11 |
12 | virtual BOOL Open(LPCTSTR lpszFileName);
13 |
14 | virtual void Close();
15 |
16 | virtual DWORD ReadDword(LPCTSTR Section, LPCTSTR key);
17 |
18 | virtual DOUBLE ReadDouble(LPCTSTR Section, LPCTSTR key);
19 |
20 | virtual DWORD ReadString(LPCTSTR Section, LPCTSTR key, TCHAR* Buf);
21 |
22 | virtual BOOL WriteDword(LPCTSTR Section, LPCTSTR key, DWORD Value);
23 |
24 | virtual BOOL WriteDouble(LPCTSTR Section, LPCTSTR key, double Value);
25 |
26 | virtual BOOL WriteString(LPCTSTR Section, LPCTSTR key, LPCTSTR Value);
27 | private:
28 | TCHAR m_sIniFileName[MAX_PATH];
29 |
30 | };
31 | }
--------------------------------------------------------------------------------
/src/IoCompletePort.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | class CIOCompletionPort
5 | {
6 | private:
7 | HANDLE m_hIOCP;
8 |
9 | public:
10 |
11 | CIOCompletionPort() : m_hIOCP(NULL)
12 | {
13 | }
14 |
15 | ~CIOCompletionPort()
16 | {
17 | Close();
18 | }
19 |
20 | BOOL Create(DWORD dwNumberOfConcurrentThreads = 0)
21 | {
22 | m_hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, dwNumberOfConcurrentThreads);
23 | return (m_hIOCP != NULL);
24 | }
25 |
26 | BOOL Close()
27 | {
28 | // Ensure that the handle of the I/O completion port is closed
29 | if(m_hIOCP != NULL && CloseHandle(m_hIOCP))
30 | {
31 | m_hIOCP = NULL;
32 | return TRUE;
33 | }
34 |
35 | return FALSE;
36 | }
37 |
38 | BOOL AssociateDevice(HANDLE hDevice, ULONG_PTR CompKey)
39 | {
40 | HANDLE h = CreateIoCompletionPort(hDevice, m_hIOCP, CompKey, 0);
41 | return h == m_hIOCP;
42 | }
43 |
44 | BOOL QueuePacket(ULONG_PTR CompKey, DWORD dwNumBytes = 0,
45 | OVERLAPPED* po = NULL)
46 | {
47 | return PostQueuedCompletionStatus(m_hIOCP, dwNumBytes, CompKey, po);
48 | }
49 |
50 | BOOL DequeuePacket(ULONG_PTR* pCompKey, PDWORD pdwNumBytes,
51 | OVERLAPPED** ppo, DWORD dwMilliseconds = INFINITE)
52 | {
53 | return GetQueuedCompletionStatus(m_hIOCP, pdwNumBytes, pCompKey, ppo,
54 | dwMilliseconds);
55 | }
56 | };
--------------------------------------------------------------------------------
/src/Keyboard.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 | #include "Keyboard.h"
3 | #include "CommonFunc.h"
4 |
5 | HHOOK CKeyboardHook::m_hHook = NULL;
6 | CKeyboardHook::CKeyboardHook(IRequestHandler* pCallback): m_pCallback(pCallback), m_pRequest(NULL)
7 | {
8 | m_pRequest = new CKeyboardHookRequest;
9 | }
10 |
11 | CKeyboardHook::~CKeyboardHook()
12 | {
13 | if(NULL != m_pRequest)
14 | delete m_pRequest;
15 |
16 | m_pRequest = NULL;
17 | }
18 |
19 | BOOL CKeyboardHook::Install(DWORD dwPID)
20 | {
21 | if(NULL == m_hHook)
22 | {
23 | if(-1 != dwPID)
24 | {
25 | m_hHook =::SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)_HookProc, ModuleFromAddress(_HookProc), GetMainThreadID(dwPID));
26 | }
27 | else
28 | m_hHook =::SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)_HookProc, ModuleFromAddress(_HookProc), 0);
29 | }
30 |
31 | PrintDebugInfo(_T("Keyboard Install\r\n"));
32 |
33 | return (NULL != m_hHook);
34 | }
35 |
36 | BOOL CKeyboardHook::UnInstall()
37 | {
38 | BOOL bRet = FALSE;
39 |
40 | if(NULL != m_hHook)
41 | {
42 | bRet =::UnhookWindowsHookEx(m_hHook);
43 | m_hHook = NULL;
44 | }
45 |
46 | PrintDebugInfo(_T("Keyboard UnInstall\r\n"));
47 | return bRet;
48 | }
49 |
50 | LRESULT CALLBACK CKeyboardHook::_HookProc(int nCode, WPARAM wParam, LPARAM lParam)
51 | {
52 | if(nCode < 0 || nCode == HC_NOREMOVE)
53 | return ::CallNextHookEx(m_hHook, nCode, wParam, lParam);
54 |
55 | if(lParam & 0x40000000) // Check the previous key state
56 | {
57 | return ::CallNextHookEx(m_hHook, nCode, wParam, lParam);
58 | }
59 |
60 | return ::CallNextHookEx(m_hHook, nCode, wParam, lParam);
61 | }
62 |
63 | void CKeyboardHook::PrintDebugInfo(LPCTSTR lpszInfo)
64 | {
65 | m_pRequest->SetDebugInfo(lpszInfo);
66 |
67 | if(NULL != m_pCallback)
68 | m_pCallback->HandleRequest(m_pRequest);
69 | }
70 |
71 | CKeyboardHookRequest::CKeyboardHookRequest()
72 | {
73 | ZeroMemory(m_szDebugInfo, sizeof(m_szDebugInfo));
74 | }
75 |
76 | CKeyboardHookRequest::~CKeyboardHookRequest()
77 | {
78 |
79 | }
80 |
81 | REQUEST_TYPE CKeyboardHookRequest::GetType()
82 | {
83 | return REQUEST_KEYBOARDHOOK;
84 | }
85 |
86 | void CKeyboardHookRequest::SetDebugInfo(LPCTSTR lpszInfo)
87 | {
88 | _tcscpy_s(m_szDebugInfo, sizeof(m_szDebugInfo) / sizeof(TCHAR), lpszInfo);
89 | }
90 |
91 | LPCTSTR CKeyboardHookRequest::GetDebugInfo()
92 | {
93 | return m_szDebugInfo;
94 | }
95 |
--------------------------------------------------------------------------------
/src/Keyboard.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wyrover/CodeLib/cee0615b2cba6d1281b93177aea7a64c4a39e1de/src/Keyboard.h
--------------------------------------------------------------------------------
/src/LPCClientImpl.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 | #include "LPCClientImpl.h"
3 | #include "LPCServerImpl.h"
4 |
5 | namespace CODELIB
6 | {
7 |
8 |
9 | CLPCClientImpl::CLPCClientImpl(ILPCEvent* pEvent): m_pEvent(pEvent), m_hPort(NULL)
10 | {
11 | InitializeCriticalSection(&m_mapCS);
12 | }
13 |
14 | CLPCClientImpl::~CLPCClientImpl()
15 | {
16 | DeleteCriticalSection(&m_mapCS);
17 | }
18 |
19 | BOOL CLPCClientImpl::PostData(MESSAGE_TYPE type, LPVOID lpData, DWORD dwDataSize)
20 | {
21 | CLPCMessage sendMsg;
22 | sendMsg.SetBuffer(lpData, dwDataSize);
23 | NTSTATUS ntStatus = NtRequestPort(m_hPort, sendMsg.GetHeader());
24 | return NT_SUCCESS(ntStatus);
25 | }
26 |
27 | BOOL CLPCClientImpl::Create(LPCTSTR lpPortName)
28 | {
29 | HANDLE m_hConnect = NULL;
30 | UNICODE_STRING sPortName;
31 | RtlInitUnicodeString(&sPortName, lpPortName);
32 | ULONG uMsgSize = 0;
33 | ULONG uMaxInfoLength = 0;
34 | NTSTATUS ntStatus = NtConnectPort(&m_hConnect, &sPortName, /*&SecurityQos*/NULL,
35 | /*&ClientView*/NULL, /*&ServerView*/NULL, &uMaxInfoLength, NULL, NULL);
36 |
37 | if(!NT_SUCCESS(ntStatus))
38 | return FALSE;
39 |
40 | ISender* pSender = new CLPCSender(m_hConnect, 0, m_pEvent);
41 |
42 | if(NULL == pSender)
43 | return FALSE;
44 |
45 | AddSender(m_hConnect, pSender);
46 |
47 | OnConnect(this, pSender);
48 |
49 | return TRUE;
50 | }
51 |
52 | void CLPCClientImpl::Close()
53 | {
54 | if(NULL != m_hPort)
55 | {
56 | NtClose(m_hPort);
57 | m_hPort = NULL;
58 | }
59 |
60 | OnClose(this);
61 | }
62 |
63 | void CLPCClientImpl::OnCreate(ILPC* pLPC)
64 | {
65 | if(NULL != m_pEvent)
66 | {
67 | m_pEvent->OnCreate(pLPC);
68 | }
69 | }
70 |
71 | void CLPCClientImpl::OnClose(ILPC* pLPC)
72 | {
73 | if(NULL != m_pEvent)
74 | m_pEvent->OnClose(pLPC);
75 | }
76 |
77 | BOOL CLPCClientImpl::OnConnect(ILPC* pLPC, ISender* pSender)
78 | {
79 | if(NULL != m_pEvent)
80 | return m_pEvent->OnConnect(pLPC, pSender);
81 |
82 | return FALSE;
83 | }
84 |
85 | void CLPCClientImpl::OnDisConnect(ILPC* pLPC, ISender* pSender)
86 | {
87 | if(NULL != m_pEvent)
88 | m_pEvent->OnDisConnect(pLPC, pSender);
89 | }
90 |
91 | void CLPCClientImpl::OnRecv(ILPC* pLPC, ISender* pSender, IMessage* pMessage)
92 | {
93 | if(NULL != m_pEvent)
94 | m_pEvent->OnRecv(pLPC, pSender, pMessage);
95 | }
96 |
97 | void CLPCClientImpl::OnRecvAndReply(ILPC* pLPC, ISender* pSender, IMessage* pReceiveMsg, IMessage* pReplyMsg)
98 | {
99 | if(NULL != m_pEvent)
100 | m_pEvent->OnRecvAndReply(pLPC, pSender, pReceiveMsg, pReplyMsg);
101 | }
102 |
103 | void CLPCClientImpl::AddSender(HANDLE hPort, ISender* pSender)
104 | {
105 | EnterCriticalSection(&m_mapCS);
106 |
107 | if(NULL != hPort || NULL != pSender)
108 | m_sendersMap.insert(std::make_pair(hPort, pSender));
109 |
110 | LeaveCriticalSection(&m_mapCS);
111 | }
112 |
113 | void CLPCClientImpl::RemoveSender(HANDLE hPort)
114 | {
115 | EnterCriticalSection(&m_mapCS);
116 | m_sendersMap.erase(hPort);
117 | LeaveCriticalSection(&m_mapCS);
118 | }
119 |
120 | ISender* CLPCClientImpl::FindSenderByHandle(HANDLE hPort)
121 | {
122 | ISender* pSender = NULL;
123 | EnterCriticalSection(&m_mapCS);
124 |
125 | SenderMap::const_iterator cit = m_sendersMap.find(hPort);
126 |
127 | if(cit != m_sendersMap.end())
128 | pSender = cit->second;
129 |
130 | LeaveCriticalSection(&m_mapCS);
131 |
132 | return pSender;
133 | }
134 |
135 | }
--------------------------------------------------------------------------------
/src/LPCClientImpl.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wyrover/CodeLib/cee0615b2cba6d1281b93177aea7a64c4a39e1de/src/LPCClientImpl.h
--------------------------------------------------------------------------------
/src/LPCServerImpl.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wyrover/CodeLib/cee0615b2cba6d1281b93177aea7a64c4a39e1de/src/LPCServerImpl.cpp
--------------------------------------------------------------------------------
/src/LPCServerImpl.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wyrover/CodeLib/cee0615b2cba6d1281b93177aea7a64c4a39e1de/src/LPCServerImpl.h
--------------------------------------------------------------------------------
/src/MiniDumpImpl.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 | #include "MiniDumpImpl.h"
3 | #include
4 | #pragma comment(lib,"DbgHelp.lib")
5 |
6 | namespace CODELIB
7 | {
8 | CMiniDumpImpl::CMiniDumpImpl()
9 | {
10 |
11 | }
12 |
13 | CMiniDumpImpl::~CMiniDumpImpl()
14 | {
15 |
16 | }
17 |
18 | void CMiniDumpImpl::Active(BOOL bEnable/*=TRUE */)
19 | {
20 | if(bEnable)
21 | SetUnhandledExceptionFilter(&CMiniDumpImpl::MyUnhandledExceptionFilter);
22 | }
23 |
24 | LONG WINAPI CMiniDumpImpl::MyUnhandledExceptionFilter(EXCEPTION_POINTERS* ExceptionInfo)
25 | {
26 | TCHAR sModuleName[MAX_PATH] = {0};
27 | GetModuleFileName(NULL, sModuleName, MAX_PATH);
28 | TCHAR* pChar = _tcsrchr(sModuleName, _T('\\'));
29 |
30 | if(NULL != pChar)
31 | {
32 | int iPos = int(pChar - sModuleName);
33 | sModuleName[iPos + 1] = _T('\0');
34 | }
35 |
36 | TCHAR sFileName[MAX_PATH] = {0};
37 | SYSTEMTIME systime = {0};
38 | GetLocalTime(&systime);
39 | _stprintf_s(sFileName, _T("%04d%02d%02d-%02d%02d%02d.dmp"),
40 | systime.wYear, systime.wMonth, systime.wDay, systime.wHour, systime.wMinute, systime.wSecond);
41 |
42 | _tcscat_s(sModuleName, sFileName);
43 | HANDLE lhDumpFile = CreateFile(sModuleName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL , NULL);
44 | MINIDUMP_EXCEPTION_INFORMATION loExceptionInfo;
45 | loExceptionInfo.ExceptionPointers = ExceptionInfo;
46 | loExceptionInfo.ThreadId = GetCurrentThreadId();
47 | loExceptionInfo.ClientPointers = FALSE;
48 | MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), lhDumpFile, MiniDumpNormal, &loExceptionInfo, NULL, NULL);
49 | CloseHandle(lhDumpFile);
50 |
51 | return EXCEPTION_EXECUTE_HANDLER;
52 | }
53 |
54 | }
--------------------------------------------------------------------------------
/src/MiniDumpImpl.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "IMiniDump.h"
3 |
4 | namespace CODELIB
5 | {
6 | class CMiniDumpImpl: public IMiniDump
7 | {
8 | public:
9 | CMiniDumpImpl();
10 | virtual ~CMiniDumpImpl();
11 |
12 | virtual void Active( BOOL bEnable=TRUE );
13 | private:
14 | static LONG WINAPI MyUnhandledExceptionFilter( EXCEPTION_POINTERS* ExceptionInfo );
15 | };
16 | }
--------------------------------------------------------------------------------
/src/NTFSDefine.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | #define MAXIMUM_VOLUME_LABEL_LENGTH (32 * sizeof(WCHAR))
6 |
7 | typedef struct _BIOS_PARAMETERS_BLOCK
8 | {
9 | USHORT BytesPerSector; // 0x0B
10 | UCHAR SectorsPerCluster; // 0x0D
11 | UCHAR Unused0[7]; // 0x0E, checked when volume is mounted
12 | UCHAR MediaId; // 0x15
13 | UCHAR Unused1[2]; // 0x16
14 | USHORT SectorsPerTrack; // 0x18
15 | USHORT Heads; // 0x1A
16 | UCHAR Unused2[4]; // 0x1C
17 | UCHAR Unused3[4]; // 0x20, checked when volume is mounted
18 | } BIOS_PARAMETERS_BLOCK, *PBIOS_PARAMETERS_BLOCK;
19 |
20 | typedef struct _EXTENDED_BIOS_PARAMETERS_BLOCK
21 | {
22 | USHORT Unknown[2]; // 0x24, always 80 00 80 00
23 | ULONGLONG SectorCount; // 0x28
24 | ULONGLONG MftLocation; // 0x30
25 | ULONGLONG MftMirrLocation; // 0x38
26 | CHAR ClustersPerMftRecord; // 0x40
27 | UCHAR Unused4[3]; // 0x41
28 | CHAR ClustersPerIndexRecord; // 0x44
29 | UCHAR Unused5[3]; // 0x45
30 | ULONGLONG SerialNumber; // 0x48
31 | UCHAR Checksum[4]; // 0x50
32 | } EXTENDED_BIOS_PARAMETERS_BLOCK, *PEXTENDED_BIOS_PARAMETERS_BLOCK;
33 |
34 | typedef struct _BOOT_SECTOR
35 | {
36 | UCHAR Jump[3]; // 0x00
37 | UCHAR OEMID[8]; // 0x03
38 | BIOS_PARAMETERS_BLOCK BPB;
39 | EXTENDED_BIOS_PARAMETERS_BLOCK EBPB;
40 | UCHAR BootStrap[426]; // 0x54
41 | USHORT EndSector; // 0x1FE
42 | } BOOT_SECTOR, *PBOOT_SECTOR;
43 |
44 | typedef struct _NTFS_INFO
45 | {
46 | ULONG BytesPerSector;
47 | ULONG SectorsPerCluster;
48 | ULONG BytesPerCluster;
49 | ULONGLONG SectorCount;
50 | ULARGE_INTEGER MftStart;
51 | ULARGE_INTEGER MftMirrStart;
52 | ULONG BytesPerFileRecord;
53 |
54 | ULONGLONG SerialNumber;
55 | USHORT VolumeLabelLength;
56 | WCHAR VolumeLabel[MAXIMUM_VOLUME_LABEL_LENGTH];
57 | UCHAR MajorVersion;
58 | UCHAR MinorVersion;
59 | USHORT Flags;
60 |
61 | } NTFS_INFO, *PNTFS_INFO;
62 |
63 | #define NTFS_TYPE_CCB '20SF'
64 | #define NTFS_TYPE_FCB '30SF'
65 | #define NTFS_TYPE_VCB '50SF'
66 | #define NTFS_TYPE_IRP_CONTEST '60SF'
67 | #define NTFS_TYPE_GLOBAL_DATA '70SF'
68 |
69 | typedef struct
70 | {
71 | ULONG Type;
72 | ULONG Size;
73 | } NTFSIDENTIFIER, *PNTFSIDENTIFIER;
74 |
75 | typedef enum
76 | {
77 | AttributeStandardInformation = 0x10,
78 | AttributeAttributeList = 0x20,
79 | AttributeFileName = 0x30,
80 | AttributeObjectId = 0x40,
81 | AttributeSecurityDescriptor = 0x50,
82 | AttributeVolumeName = 0x60,
83 | AttributeVolumeInformation = 0x70,
84 | AttributeData = 0x80,
85 | AttributeIndexRoot = 0x90,
86 | AttributeIndexAllocation = 0xA0,
87 | AttributeBitmap = 0xB0,
88 | AttributeReparsePoint = 0xC0,
89 | AttributeEAInformation = 0xD0,
90 | AttributeEA = 0xE0,
91 | AttributePropertySet = 0xF0,
92 | AttributeLoggedUtilityStream = 0x100
93 | } ATTRIBUTE_TYPE, *PATTRIBUTE_TYPE;
94 |
95 |
96 | typedef struct
97 | {
98 | ULONG Type; /* Magic number 'FILE' */
99 | USHORT UsaOffset; /* Offset to the update sequence */
100 | USHORT UsaCount; /* Size in words of Update Sequence Number & Array (S) */
101 | ULONGLONG Lsn; /* $LogFile Sequence Number (LSN) */
102 | } NTFS_RECORD_HEADER, *PNTFS_RECORD_HEADER;
103 |
104 | /* NTFS_RECORD_HEADER.Type */
105 | #define NRH_FILE_TYPE 0x454C4946 /* 'FILE' */
106 |
107 |
108 | typedef struct
109 | {
110 | NTFS_RECORD_HEADER Ntfs;
111 | USHORT SequenceNumber; /* Sequence number */
112 | USHORT LinkCount; /* Hard link count */
113 | USHORT AttributeOffset; /* Offset to the first Attribute */
114 | USHORT Flags; /* Flags */
115 | ULONG BytesInUse; /* Real size of the FILE record */
116 | ULONG BytesAllocated; /* Allocated size of the FILE record */
117 | ULONGLONG BaseFileRecord; /* File reference to the base FILE record */
118 | USHORT NextAttributeNumber; /* Next Attribute Id */
119 | USHORT Pading; /* Align to 4 UCHAR boundary (XP) */
120 | ULONG MFTRecordNumber; /* Number of this MFT Record (XP) */
121 | } FILE_RECORD_HEADER, *PFILE_RECORD_HEADER;
122 |
123 | /* Flags in FILE_RECORD_HEADER */
124 |
125 | #define FRH_IN_USE 0x0001 /* Record is in use */
126 | #define FRH_DIRECTORY 0x0002 /* Record is a directory */
127 | #define FRH_UNKNOWN1 0x0004 /* Don't know */
128 | #define FRH_UNKNOWN2 0x0008 /* Don't know */
129 |
130 | typedef struct
131 | {
132 | ATTRIBUTE_TYPE AttributeType;
133 | ULONG Length;
134 | BOOLEAN Nonresident;
135 | UCHAR NameLength;
136 | USHORT NameOffset;
137 | USHORT Flags;
138 | USHORT AttributeNumber;
139 | } ATTRIBUTE, *PATTRIBUTE;
140 |
141 | typedef struct
142 | {
143 | ATTRIBUTE Attribute;
144 | ULONG ValueLength;
145 | USHORT ValueOffset;
146 | UCHAR Flags;
147 | // UCHAR Padding0;
148 | } RESIDENT_ATTRIBUTE, *PRESIDENT_ATTRIBUTE;
149 |
150 | typedef struct
151 | {
152 | ATTRIBUTE Attribute;
153 | ULONGLONG StartVcn; // LowVcn
154 | ULONGLONG LastVcn; // HighVcn
155 | USHORT RunArrayOffset;
156 | USHORT CompressionUnit;
157 | ULONG Padding0;
158 | UCHAR IndexedFlag;
159 | ULONGLONG AllocatedSize;
160 | ULONGLONG DataSize;
161 | ULONGLONG InitializedSize;
162 | ULONGLONG CompressedSize;
163 | } NONRESIDENT_ATTRIBUTE, *PNONRESIDENT_ATTRIBUTE;
164 |
165 |
166 | typedef struct
167 | {
168 | ULONGLONG CreationTime;
169 | ULONGLONG ChangeTime;
170 | ULONGLONG LastWriteTime;
171 | ULONGLONG LastAccessTime;
172 | ULONG FileAttribute;
173 | ULONG AlignmentOrReserved[3];
174 | #if 0
175 | ULONG QuotaId;
176 | ULONG SecurityId;
177 | ULONGLONG QuotaCharge;
178 | USN Usn;
179 | #endif
180 | } STANDARD_INFORMATION, *PSTANDARD_INFORMATION;
181 |
182 |
183 | typedef struct
184 | {
185 | ATTRIBUTE_TYPE AttributeType;
186 | USHORT Length;
187 | UCHAR NameLength;
188 | UCHAR NameOffset;
189 | ULONGLONG StartVcn; // LowVcn
190 | ULONGLONG FileReferenceNumber;
191 | USHORT AttributeNumber;
192 | USHORT AlignmentOrReserved[3];
193 | } ATTRIBUTE_LIST, *PATTRIBUTE_LIST;
194 |
195 |
196 | typedef struct
197 | {
198 | ULONGLONG DirectoryFileReferenceNumber;
199 | ULONGLONG CreationTime;
200 | ULONGLONG ChangeTime;
201 | ULONGLONG LastWriteTime;
202 | ULONGLONG LastAccessTime;
203 | ULONGLONG AllocatedSize;
204 | ULONGLONG DataSize;
205 | ULONG FileAttributes;
206 | ULONG AlignmentOrReserved;
207 | UCHAR NameLength;
208 | UCHAR NameType;
209 | WCHAR Name[1];
210 | } FILENAME_ATTRIBUTE, *PFILENAME_ATTRIBUTE;
211 |
212 | typedef struct
213 | {
214 | ULONGLONG Unknown1;
215 | UCHAR MajorVersion;
216 | UCHAR MinorVersion;
217 | USHORT Flags;
218 | ULONG Unknown2;
219 | } VOLINFO_ATTRIBUTE, *PVOLINFO_ATTRIBUTE;
220 |
221 |
--------------------------------------------------------------------------------
/src/NamedPipeClientImpl.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 | #include "NamedPipeClientImpl.h"
3 |
4 | CNamedPipeClientImpl::CNamedPipeClientImpl(IIPCEvent* pEvent): m_pEvent(pEvent)
5 | , m_hThreadIOCP(NULL)
6 | , m_dwProcessID(0)
7 | , m_dwIOCPThreadNum(0)
8 | {
9 | SYSTEM_INFO sysInfo = { 0 };
10 | GetNativeSystemInfo(&sysInfo);
11 | m_dwIOCPThreadNum = sysInfo.dwNumberOfProcessors * 2;
12 | }
13 |
14 |
15 | CNamedPipeClientImpl::~CNamedPipeClientImpl(void)
16 | {
17 | Close();
18 | }
19 |
20 | BOOL CNamedPipeClientImpl::Create(LPCTSTR lpPipeName)
21 | {
22 | TCHAR sPipeName[MAX_PATH] = {0};
23 | _tcscpy_s(sPipeName, MAX_PATH, _T("\\\\.\\pipe\\"));
24 | _tcscat_s(sPipeName, lpPipeName);
25 |
26 | while(TRUE)
27 | {
28 | if(m_pipe.CreateFile(sPipeName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL))
29 | break;
30 |
31 | DWORD dwError = GetLastError();
32 |
33 | if(ERROR_PIPE_BUSY != dwError)
34 | return FALSE;
35 |
36 | if(!m_pipe.WaitNamedPipe(sPipeName, 5000))
37 | return FALSE;
38 | }
39 |
40 | if(!m_iocp.Create(m_dwIOCPThreadNum))
41 | return FALSE;
42 |
43 | m_hThreadIOCP = new HANDLE[m_dwIOCPThreadNum];
44 |
45 | for(DWORD i = 0; i < m_dwIOCPThreadNum; ++i)
46 | m_hThreadIOCP[i] = CreateThread(0, 0, IOCompletionThread, this, 0, NULL);
47 |
48 | DWORD dwMode = PIPE_READMODE_MESSAGE ;
49 |
50 | if(!m_pipe.SetNamedPipeHandleState(&dwMode, NULL, NULL))
51 | return FALSE;
52 |
53 | if(!m_iocp.AssociateDevice(m_pipe.GetHandle(), (ULONG_PTR)this))
54 | return FALSE;
55 |
56 | return TRUE;
57 | }
58 |
59 | void CNamedPipeClientImpl::Close()
60 | {
61 | m_pipe.Close();
62 | m_iocp.Close();
63 |
64 | if(NULL != m_hThreadIOCP)
65 | WaitForMultipleObjects(m_dwIOCPThreadNum, m_hThreadIOCP, TRUE, INFINITE);
66 |
67 | for(DWORD i = 0; i < m_dwIOCPThreadNum; i++)
68 | {
69 | if(NULL != m_hThreadIOCP && NULL != m_hThreadIOCP[i])
70 | {
71 | CloseHandle(m_hThreadIOCP[i]);
72 | m_hThreadIOCP[i] = NULL;
73 | }
74 | }
75 |
76 | delete m_hThreadIOCP;
77 | m_hThreadIOCP = NULL;
78 | }
79 |
80 | HANDLE CNamedPipeClientImpl::GetHandle()
81 | {
82 | return m_pipe.GetHandle();
83 | }
84 |
85 | BOOL CNamedPipeClientImpl::PostMessage(LPCVOID lpBuf, DWORD dwBufSize)
86 | {
87 | if(NULL == lpBuf || dwBufSize <= 0)
88 | return FALSE;
89 |
90 | CNamedPipeMessage* postPackage = new CNamedPipeMessage(lpBuf, dwBufSize, IPC_OVERLAPPED_WRITE);
91 |
92 | DWORD dwWrited = 0;
93 | BOOL bSucess = m_pipe.WriteFile(&postPackage->m_package, postPackage->m_package.dwTotalSize, &dwWrited, postPackage->GetOvHeader());
94 | return (bSucess || GetLastError() == ERROR_IO_PENDING);
95 | }
96 |
97 | IIPCConnectorIterator* CNamedPipeClientImpl::GetClients()
98 | {
99 | return this;
100 | }
101 |
102 | void CNamedPipeClientImpl::Begin()
103 | {
104 | m_iIterator = 0;
105 | }
106 |
107 | BOOL CNamedPipeClientImpl::End()
108 | {
109 | return (1 == m_iIterator);
110 | }
111 |
112 | void CNamedPipeClientImpl::Next()
113 | {
114 | m_iIterator++;
115 | }
116 |
117 | IIPCConnector* CNamedPipeClientImpl::GetCurrent()
118 | {
119 | return this;
120 | }
121 |
122 | BOOL CNamedPipeClientImpl::RequestAndReply(LPVOID lpSendBuf, DWORD dwSendBufSize, LPVOID lpReplyBuf, DWORD dwReplyBufSize, DWORD dwTimeout)
123 | {
124 | if(NULL == lpSendBuf || dwSendBufSize <= 0)
125 | return FALSE;
126 |
127 | if(NULL == lpReplyBuf || dwReplyBufSize <= 0)
128 | return FALSE;
129 |
130 | CNamedPipeMessage* sendPackage = new CNamedPipeMessage(lpSendBuf, dwSendBufSize);
131 |
132 | DWORD dwWrited = 0;
133 | BOOL bSucess = m_pipe.WriteFile(&sendPackage->m_package, sendPackage->m_package.dwTotalSize, &dwWrited, sendPackage->GetOvHeader());
134 |
135 | if(!bSucess && GetLastError() == ERROR_IO_PENDING)
136 | {
137 | // if(GetOverlappedResult(m_pipe.GetHandle(), sendPackage->GetOvHeader(), &dwWrited, TRUE))
138 | if(WAIT_OBJECT_0 == WaitForSingleObject(sendPackage->GetOvHeader()->hEvent, dwTimeout))
139 | bSucess = TRUE;
140 | }
141 |
142 | CNamedPipeMessage* recePackage = new CNamedPipeMessage(NULL, 0);
143 |
144 | DWORD dwReaded = 0;
145 | bSucess = m_pipe.ReadFile(&recePackage->m_package, sizeof(recePackage->m_package), &dwReaded, recePackage->GetOvHeader());
146 |
147 | if(!bSucess && GetLastError() == ERROR_IO_PENDING)
148 | {
149 | // if(GetOverlappedResult(m_pipe.GetHandle(), recePackage->GetOvHeader(), &dwReaded, TRUE))
150 | if(WAIT_OBJECT_0 == WaitForSingleObject(recePackage->GetOvHeader()->hEvent, dwTimeout))
151 | bSucess = TRUE;
152 | }
153 |
154 | if(bSucess)
155 | {
156 | VOID* lpBuf = NULL;
157 | DWORD dwBufSize = 0;
158 |
159 | if(recePackage->GetCustomBuffer(&lpBuf, &dwBufSize))
160 | memcpy_s(lpReplyBuf, dwReplyBufSize, lpBuf, dwBufSize);
161 | }
162 |
163 | return bSucess;
164 | }
165 |
166 |
167 | DWORD CNamedPipeClientImpl::GetSID()
168 | {
169 | return m_dwProcessID;
170 | }
171 |
172 | LPCTSTR CNamedPipeClientImpl::GetName()
173 | {
174 | return m_sName;
175 | }
176 |
177 | DWORD CNamedPipeClientImpl::IOCompletionThread(LPVOID lpParam)
178 | {
179 | CNamedPipeClientImpl* pThis = (CNamedPipeClientImpl*)lpParam;
180 |
181 | if(NULL == lpParam)
182 | return -1;
183 |
184 | CIOCompletionPort* iocp = &pThis->m_iocp;
185 | CNamedPipeClientImpl* pClient = NULL;
186 | DWORD dwBytesTransferred = 0;
187 | CNamedPipeMessage* message = NULL;
188 | BOOL bSucess = FALSE;
189 |
190 | while(TRUE)
191 | {
192 | bSucess = iocp->DequeuePacket((ULONG_PTR*)&pClient, &dwBytesTransferred, (OVERLAPPED **)&message, INFINITE);
193 |
194 | if(!bSucess && NULL == message)
195 | {
196 | break;
197 | }
198 | else if(!bSucess && GetLastError() == ERROR_BROKEN_PIPE)
199 | {
200 | CNamedPipeClientImpl::FreeOverlapped(&message);
201 | continue;
202 | }
203 |
204 | IPC_OVERLAPPED_TYPE type = IPC_OVERLAPPED_UKNOWN;
205 |
206 | if(NULL != message)
207 | type = message->GetOvType();
208 |
209 | switch(type)
210 | {
211 | case IPC_OVERLAPPED_READ:
212 | {
213 | VOID* lpBuf = NULL;
214 | DWORD dwBufSize = 0;
215 |
216 | if(message->GetCustomBuffer(&lpBuf, &dwBufSize))
217 | pThis->m_pEvent->OnRequest(pThis, pClient, lpBuf, dwBufSize);
218 |
219 | CNamedPipeClientImpl::FreeOverlapped(&message);
220 | break;
221 | }
222 |
223 | case IPC_OVERLAPPED_WRITE:
224 | pClient->DoRead();
225 | CNamedPipeClientImpl::FreeOverlapped(&message);
226 | break;
227 |
228 | default:
229 | CNamedPipeClientImpl::FreeOverlapped(&message);
230 | break;
231 | }
232 | }
233 |
234 | _tprintf(_T("DequeuePacket failed w/err 0x%08lx\n"), GetLastError());
235 |
236 | return 0;
237 | }
238 |
239 | BOOL CNamedPipeClientImpl::CloseConnection(CNamedPipeClientImpl* pConnector)
240 | {
241 | m_pipe.FlushFileBuffers();
242 | m_pipe.DisconnectNamedPipe();
243 | m_pipe.Close();
244 | return TRUE;
245 | }
246 |
247 | BOOL CNamedPipeClientImpl::DoRead()
248 | {
249 | CNamedPipeMessage* package = new CNamedPipeMessage(NULL, 0, IPC_OVERLAPPED_READ);
250 | BOOL bSucess = m_pipe.ReadFile(&package->m_package, sizeof(package->m_package), NULL, package->GetOvHeader());
251 | return (bSucess || ERROR_IO_PENDING == GetLastError());
252 | }
253 |
254 | void CNamedPipeClientImpl::FreeOverlapped(CNamedPipeMessage** dataOverlapped)
255 | {
256 | if(NULL != *dataOverlapped)
257 | delete *dataOverlapped;
258 |
259 | *dataOverlapped = NULL;
260 | }
261 |
--------------------------------------------------------------------------------
/src/NamedPipeClientImpl.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "IIPCInterface.h"
3 | #include "IoCompletePort.h"
4 | #include "NamedPipeWrapper.h"
5 | #include "IPCMessage.h"
6 |
7 | class CNamedPipeClientImpl : public IIPCObject , public IIPCConnector, public IIPCConnectorIterator
8 | {
9 | public:
10 |
11 | CNamedPipeClientImpl(IIPCEvent* pEvent);
12 |
13 | virtual ~CNamedPipeClientImpl(void);
14 |
15 | virtual BOOL Create(LPCTSTR lpPipeName);
16 |
17 | virtual void Close();
18 |
19 | virtual IIPCConnectorIterator* GetClients();
20 |
21 | virtual HANDLE GetHandle();
22 |
23 | virtual DWORD GetSID();
24 |
25 | virtual LPCTSTR GetName();
26 |
27 | virtual BOOL PostMessage(LPCVOID lpBuf, DWORD dwBufSize);
28 |
29 | virtual BOOL RequestAndReply(LPVOID lpSendBuf, DWORD dwSendBufSize, LPVOID lpReplyBuf, DWORD dwReplyBufSize, DWORD dwTimeout = 3000);
30 |
31 | virtual void Begin();
32 |
33 | virtual BOOL End();
34 |
35 | virtual void Next();
36 |
37 | virtual IIPCConnector* GetCurrent();
38 |
39 | protected:
40 |
41 | static void FreeOverlapped(CNamedPipeMessage** dataOverlapped);
42 |
43 | static DWORD WINAPI IOCompletionThread(LPVOID lpParam);
44 |
45 | BOOL CloseConnection(CNamedPipeClientImpl* pConnector);
46 |
47 | BOOL DoRead();
48 |
49 | private:
50 |
51 | IIPCEvent* m_pEvent;
52 |
53 | int m_iIterator;
54 |
55 | TCHAR m_sName[MAX_PATH];
56 |
57 | DWORD m_dwProcessID;
58 |
59 | CIOCompletionPort m_iocp;
60 |
61 | CNamedPipeWrapper m_pipe;
62 |
63 | HANDLE* m_hThreadIOCP;
64 |
65 | DWORD m_dwIOCPThreadNum;
66 |
67 | };
68 |
69 |
--------------------------------------------------------------------------------
/src/NamedPipeServerImpl.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 | #include "NamedPipeServerImpl.h"
3 |
4 | CNamedPipeServerImpl::CNamedPipeServerImpl(IIPCEvent* pEvent): m_pEvent(pEvent)
5 | , m_hThreadIOCP(NULL)
6 | , m_dwIOCPThreadNum(0)
7 | {
8 | InitializeCriticalSection(&m_csClientMap);
9 | SYSTEM_INFO sysInfo = { 0 };
10 | GetNativeSystemInfo(&sysInfo);
11 | m_dwIOCPThreadNum = sysInfo.dwNumberOfProcessors * 2;
12 | }
13 |
14 | CNamedPipeServerImpl::~CNamedPipeServerImpl()
15 | {
16 | Close();
17 | DeleteCriticalSection(&m_csClientMap);
18 | }
19 |
20 | BOOL CNamedPipeServerImpl::Create(LPCTSTR lpPipeName)
21 | {
22 | if(NULL == lpPipeName)
23 | return FALSE;
24 |
25 | _tcscpy_s(m_sPipeName, MAX_PATH, _T("\\\\.\\pipe\\"));
26 | _tcscat_s(m_sPipeName, lpPipeName);
27 |
28 | if(!m_iocp.Create(m_dwIOCPThreadNum))
29 | return FALSE;
30 |
31 | m_hThreadIOCP = new HANDLE[m_dwIOCPThreadNum];
32 |
33 | if(NULL == m_hThreadIOCP)
34 | return FALSE;
35 |
36 | for(DWORD i = 0; i < m_dwIOCPThreadNum; ++i)
37 | m_hThreadIOCP[i] = CreateThread(0, 0, IOCompletionThread, this, 0, NULL);
38 |
39 | WaitClientConnect();
40 | return TRUE;
41 | }
42 |
43 | void CNamedPipeServerImpl::Close()
44 | {
45 | m_iocp.Close();
46 |
47 | if(NULL != m_hThreadIOCP)
48 | WaitForMultipleObjects(m_dwIOCPThreadNum, m_hThreadIOCP, TRUE, INFINITE);
49 |
50 | for(DWORD i = 0; i < m_dwIOCPThreadNum; i++)
51 | {
52 | if(NULL != m_hThreadIOCP && NULL != m_hThreadIOCP[i])
53 | {
54 | CloseHandle(m_hThreadIOCP[i]);
55 | m_hThreadIOCP[i] = NULL;
56 | }
57 | }
58 |
59 | delete m_hThreadIOCP;
60 | m_hThreadIOCP = NULL;
61 |
62 | for(ConnectorMap::const_iterator cit = m_connectorMap.begin(); cit != m_connectorMap.end(); cit++)
63 | {
64 | CNamedPipeConnector* pClient = dynamic_cast(*cit);
65 |
66 | if(NULL != pClient)
67 | {
68 | pClient->Close();
69 | delete pClient;
70 | pClient = NULL;
71 | }
72 | }
73 |
74 | m_connectorMap.clear();
75 | }
76 |
77 | IIPCConnectorIterator* CNamedPipeServerImpl::GetClients()
78 | {
79 | return this;
80 | }
81 |
82 | ConnectorMap::const_iterator CNamedPipeServerImpl::FindClient(HANDLE hPipe)
83 | {
84 | EnterCriticalSection(&m_csClientMap);
85 | ConnectorMap::const_iterator citFinded = m_connectorMap.end();
86 |
87 | for(ConnectorMap::const_iterator cit = m_connectorMap.begin(); cit != m_connectorMap.end(); cit++)
88 | {
89 | CNamedPipeConnector* pConnector = dynamic_cast(*cit);
90 |
91 | if(NULL != pConnector && pConnector->GetHandle() == hPipe)
92 | {
93 | citFinded = cit;
94 | break;
95 | }
96 | }
97 |
98 | LeaveCriticalSection(&m_csClientMap);
99 | return citFinded;
100 | }
101 |
102 | void CNamedPipeServerImpl::Begin()
103 | {
104 | EnterCriticalSection(&m_csClientMap);
105 | m_citCurrent = m_connectorMap.begin();
106 | LeaveCriticalSection(&m_csClientMap);
107 | }
108 |
109 | BOOL CNamedPipeServerImpl::End()
110 | {
111 | BOOL bEnd = FALSE;
112 | EnterCriticalSection(&m_csClientMap);
113 | bEnd = m_citCurrent == m_connectorMap.end();
114 | LeaveCriticalSection(&m_csClientMap);
115 | return bEnd;
116 | }
117 |
118 | void CNamedPipeServerImpl::Next()
119 | {
120 | EnterCriticalSection(&m_csClientMap);
121 | m_citCurrent++;
122 | LeaveCriticalSection(&m_csClientMap);
123 | }
124 |
125 | IIPCConnector* CNamedPipeServerImpl::GetCurrent()
126 | {
127 | IIPCConnector* pConnector = NULL;
128 | EnterCriticalSection(&m_csClientMap);
129 | pConnector = *m_citCurrent;
130 | LeaveCriticalSection(&m_csClientMap);
131 | return pConnector;
132 | }
133 |
134 | void CNamedPipeServerImpl::FreeOverlapped(CNamedPipeMessage* dataOverlapped)
135 | {
136 | if(NULL != dataOverlapped)
137 | delete dataOverlapped;
138 |
139 | dataOverlapped = NULL;
140 | }
141 |
142 | DWORD WINAPI CNamedPipeServerImpl::IOCompletionThread(LPVOID lpParam)
143 | {
144 | CNamedPipeServerImpl* pThis = (CNamedPipeServerImpl*)lpParam;
145 |
146 | if(NULL == lpParam)
147 | return -1;
148 |
149 | CIOCompletionPort* iocp = &pThis->m_iocp;
150 | CNamedPipeConnector* pClient = NULL;
151 | DWORD dwBytesTransferred = 0;
152 | CNamedPipeMessage* message = NULL;
153 | BOOL bSucess = FALSE;
154 |
155 | while(TRUE)
156 | {
157 | bSucess = iocp->DequeuePacket((ULONG_PTR*)&pClient, &dwBytesTransferred, (OVERLAPPED **)&message, INFINITE);
158 |
159 | if(!bSucess && NULL == message)
160 | {
161 | break;
162 | }
163 | else if(!bSucess && GetLastError() == ERROR_BROKEN_PIPE)
164 | {
165 | EnterCriticalSection(&pThis->m_csClientMap);
166 | pThis->RemoveAndCloseClient(pClient);
167 | CNamedPipeServerImpl::FreeOverlapped(message);
168 | pClient = NULL;
169 | LeaveCriticalSection(&pThis->m_csClientMap);
170 | continue;
171 | }
172 |
173 | IPC_OVERLAPPED_TYPE type = IPC_OVERLAPPED_UKNOWN;
174 |
175 | if(NULL != message)
176 | type = message->GetOvType();
177 |
178 | switch(type)
179 | {
180 | case IPC_OVERLAPPED_CONNECT:
181 | pClient->DoRead();
182 | pThis->WaitClientConnect();
183 | // the overlapped struct of the connection header doesn't need to free in here.
184 | // it be freed in the destruction of the class
185 | break;
186 |
187 | case IPC_OVERLAPPED_READ:
188 | {
189 | VOID* lpBuf = NULL;
190 | DWORD dwBufSize = 0;
191 |
192 | EnterCriticalSection(&pThis->m_csClientMap);
193 |
194 | if(message->GetCustomBuffer(&lpBuf, &dwBufSize))
195 | pThis->m_pEvent->OnRequest(pThis, pClient, lpBuf, dwBufSize);
196 |
197 | LeaveCriticalSection(&pThis->m_csClientMap);
198 |
199 | CNamedPipeServerImpl::FreeOverlapped(message);
200 | break;
201 | }
202 |
203 | case IPC_OVERLAPPED_WRITE:
204 | pClient->DoRead();
205 | CNamedPipeServerImpl::FreeOverlapped(message);
206 | break;
207 |
208 | default:
209 | CNamedPipeServerImpl::FreeOverlapped(message);
210 | break;
211 | }
212 | }
213 |
214 | return 0;
215 | }
216 |
217 | BOOL CNamedPipeServerImpl::WaitClientConnect()
218 | {
219 | CNamedPipeConnector* pClient = new CNamedPipeConnector();
220 |
221 | if(NULL == pClient)
222 | return FALSE;
223 |
224 | if(!pClient->Create(m_sPipeName))
225 | {
226 | delete pClient;
227 | pClient = NULL;
228 | return FALSE;
229 | }
230 |
231 | m_connectorMap.push_back(pClient);
232 |
233 | if(!m_iocp.AssociateDevice(pClient->GetHandle(), (ULONG_PTR)pClient))
234 | return FALSE;
235 |
236 | if(!pClient->WaitConnect())
237 | return FALSE;
238 |
239 | return TRUE;
240 | }
241 |
242 | void CNamedPipeServerImpl::RemoveAndCloseClient(CNamedPipeConnector* pClient)
243 | {
244 | EnterCriticalSection(&m_csClientMap);
245 | ConnectorMap::const_iterator cit = FindClient(pClient->GetHandle());
246 | pClient->Close();
247 | delete pClient;
248 | pClient = NULL;
249 |
250 | if(cit != m_connectorMap.end())
251 | m_connectorMap.erase(cit);
252 |
253 | LeaveCriticalSection(&m_csClientMap);
254 | }
255 |
256 | CNamedPipeConnector::CNamedPipeConnector(): m_pConnPackage(NULL)
257 | {
258 | m_pConnPackage = new CNamedPipeMessage(NULL, 0, IPC_OVERLAPPED_CONNECT);
259 | }
260 |
261 | CNamedPipeConnector::~CNamedPipeConnector()
262 | {
263 | if(NULL != m_pConnPackage)
264 | delete m_pConnPackage;
265 |
266 | m_pConnPackage = NULL;
267 | }
268 |
269 | DWORD CNamedPipeConnector::GetSID()
270 | {
271 | return m_pipe.GetNamedPipeClientProcessId();
272 | }
273 |
274 | LPCTSTR CNamedPipeConnector::GetName()
275 | {
276 | return NULL;
277 | }
278 |
279 | BOOL CNamedPipeConnector::PostMessage(LPCVOID lpBuf, DWORD dwBufSize)
280 | {
281 | if(NULL == lpBuf || dwBufSize <= 0)
282 | return FALSE;
283 |
284 | CNamedPipeMessage* postPackage = new CNamedPipeMessage(lpBuf, dwBufSize, IPC_OVERLAPPED_WRITE);
285 |
286 | DWORD dwWrited = 0;
287 | BOOL bSucess = m_pipe.WriteFile(&postPackage->m_package, postPackage->m_package.dwTotalSize, &dwWrited, postPackage->GetOvHeader());
288 | return (bSucess || GetLastError() == ERROR_IO_PENDING);
289 | }
290 |
291 | BOOL CNamedPipeConnector::RequestAndReply(LPVOID lpSendBuf, DWORD dwSendBufSize, LPVOID lpReplyBuf, DWORD dwReplyBufSize, DWORD dwTimeout)
292 | {
293 | throw _T("the server sshoudn't implemention this method");
294 | return FALSE;
295 | }
296 |
297 | BOOL CNamedPipeConnector::Create(LPCTSTR lpPipeName)
298 | {
299 | if(NULL == lpPipeName) return FALSE;
300 |
301 | return m_pipe.CreateNamedPipe(lpPipeName, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
302 | PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
303 | PIPE_UNLIMITED_INSTANCES, 0, 0, NMPWAIT_USE_DEFAULT_WAIT, NULL);
304 | }
305 |
306 | void CNamedPipeConnector::Close()
307 | {
308 | m_pipe.FlushFileBuffers();
309 | m_pipe.DisconnectNamedPipe();
310 | m_pipe.Close();
311 | }
312 |
313 | HANDLE CNamedPipeConnector::GetHandle()
314 | {
315 | return m_pipe.GetHandle();
316 | }
317 |
318 | BOOL CNamedPipeConnector::DoRead()
319 | {
320 | CNamedPipeMessage* package = new CNamedPipeMessage(NULL, 0, IPC_OVERLAPPED_READ);
321 | BOOL bSucess = m_pipe.ReadFile(&package->m_package, sizeof(package->m_package), NULL, package->GetOvHeader());
322 | return (bSucess || ERROR_IO_PENDING == GetLastError());
323 | }
324 |
325 | BOOL CNamedPipeConnector::WaitConnect()
326 | {
327 | BOOL bSucess = m_pipe.ConnectNamedPipe(m_pConnPackage->GetOvHeader());
328 | return (bSucess || GetLastError() == ERROR_IO_PENDING);
329 | }
330 |
--------------------------------------------------------------------------------
/src/NamedPipeServerImpl.h:
--------------------------------------------------------------------------------
1 | /********************************************************************
2 | created: 2014/04/26
3 | file base: NamedPipeServerImpl
4 | author: redcode
5 | purpose: the implement for the NamedPipe Server
6 | *********************************************************************/
7 |
8 | #pragma once
9 | #include "IIPCInterface.h"
10 | #include "IoCompletePort.h"
11 | #include "NamedPipeWrapper.h"
12 | #include "IPCMessage.h"
13 |
14 | class CNamedPipeServerImpl: public IIPCObject, public IIPCConnectorIterator
15 | {
16 | public:
17 | CNamedPipeServerImpl(IIPCEvent* pEvent);
18 |
19 | virtual ~CNamedPipeServerImpl();
20 |
21 | virtual BOOL Create(LPCTSTR lpPipeName);
22 |
23 | virtual void Close();
24 |
25 | virtual IIPCConnectorIterator* GetClients();
26 |
27 | virtual void Begin();
28 |
29 | virtual BOOL End();
30 |
31 | virtual void Next();
32 |
33 | virtual IIPCConnector* GetCurrent();
34 |
35 | static void FreeOverlapped(CNamedPipeMessage* dataOverlapped);
36 |
37 | protected:
38 |
39 | static DWORD WINAPI IOCompletionThread(LPVOID lpParam);
40 |
41 | BOOL WaitClientConnect();
42 |
43 | ConnectorMap::const_iterator FindClient(HANDLE hPipe);
44 |
45 | void RemoveAndCloseClient(CNamedPipeConnector* pClient);
46 |
47 | private:
48 |
49 | CRITICAL_SECTION m_csClientMap;
50 |
51 | CIOCompletionPort m_iocp;
52 |
53 | ConnectorMap m_connectorMap;
54 |
55 | ConnectorMap::const_iterator m_citCurrent;
56 |
57 | TCHAR m_sPipeName[MAX_PATH];
58 |
59 | HANDLE* m_hThreadIOCP;
60 |
61 | IIPCEvent* m_pEvent;
62 |
63 | DWORD m_dwIOCPThreadNum;
64 | };
65 |
66 | class CNamedPipeConnector : public IIPCConnector
67 | {
68 | public:
69 | CNamedPipeConnector();
70 |
71 | virtual ~CNamedPipeConnector();
72 |
73 | BOOL Create(LPCTSTR lpPipeName);
74 |
75 | BOOL WaitConnect();
76 |
77 | void Close();
78 |
79 | BOOL DoRead();
80 |
81 | HANDLE GetHandle();
82 |
83 | virtual DWORD GetSID();
84 |
85 | virtual LPCTSTR GetName();
86 |
87 | virtual BOOL PostMessage(LPCVOID lpBuf, DWORD dwBufSize);
88 |
89 | virtual BOOL RequestAndReply(LPVOID lpSendBuf, DWORD dwSendBufSize, LPVOID lpReplyBuf, DWORD dwReplySize, DWORD dwTimeout = 3000);
90 |
91 | friend class CNamedPipeServerImpl;
92 |
93 | private:
94 | CNamedPipeWrapper m_pipe;
95 |
96 | DWORD m_dwProcessID;
97 |
98 | CNamedPipeMessage* m_pConnPackage;
99 | };
--------------------------------------------------------------------------------
/src/NamedPipeWrapper.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 |
5 | class CNamedPipeWrapper
6 | {
7 | public:
8 | CNamedPipeWrapper(void): m_hPipe(INVALID_HANDLE_VALUE)
9 | {
10 |
11 | }
12 | virtual ~CNamedPipeWrapper(void)
13 | {
14 |
15 | }
16 |
17 | void Close()
18 | {
19 | if(INVALID_HANDLE_VALUE != m_hPipe)
20 | CloseHandle(m_hPipe);
21 |
22 | m_hPipe = INVALID_HANDLE_VALUE;
23 | }
24 |
25 | HANDLE GetHandle()
26 | {
27 | return m_hPipe;
28 | }
29 |
30 | BOOL CreateNamedPipe(
31 | __in LPCTSTR lpName,
32 | __in DWORD dwOpenMode,
33 | __in DWORD dwPipeMode,
34 | __in DWORD nMaxInstances,
35 | __in DWORD nOutBufferSize,
36 | __in DWORD nInBufferSize,
37 | __in DWORD nDefaultTimeOut,
38 | __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes
39 | )
40 | {
41 | assert(INVALID_HANDLE_VALUE == m_hPipe);
42 | m_hPipe =::CreateNamedPipe(lpName, dwOpenMode, dwPipeMode, nMaxInstances, nOutBufferSize, nInBufferSize, nDefaultTimeOut, lpSecurityAttributes);
43 | return (INVALID_HANDLE_VALUE != m_hPipe);
44 | }
45 |
46 | BOOL ConnectNamedPipe(
47 | LPOVERLAPPED lpOverlapped
48 | )
49 | {
50 | return ::ConnectNamedPipe(m_hPipe, lpOverlapped);
51 | }
52 |
53 | BOOL CreateFile(
54 | LPCTSTR lpFileName,
55 | DWORD dwDesiredAccess,
56 | DWORD dwShareMode,
57 | LPSECURITY_ATTRIBUTES lpSecurityAttributes,
58 | DWORD dwCreationDisposition,
59 | DWORD dwFlagsAndAttributes,
60 | HANDLE hTemplateFile
61 | )
62 | {
63 | assert(INVALID_HANDLE_VALUE == m_hPipe);
64 | m_hPipe = ::CreateFile(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
65 | return (INVALID_HANDLE_VALUE != m_hPipe);
66 | }
67 |
68 |
69 | BOOL ReadFile(
70 | LPVOID lpBuffer,
71 | DWORD nNumberOfBytesToRead,
72 | LPDWORD lpNumberOfBytesRead,
73 | LPOVERLAPPED lpOverlapped
74 | )
75 | {
76 | return ::ReadFile(m_hPipe, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
77 | }
78 |
79 | BOOL WriteFile(
80 | LPCVOID lpBuffer,
81 | DWORD nNumberOfBytesToWrite,
82 | LPDWORD lpNumberOfBytesWritten,
83 | LPOVERLAPPED lpOverlapped
84 | )
85 | {
86 | return ::WriteFile(m_hPipe, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped);
87 | }
88 |
89 | BOOL FlushFileBuffers(
90 | )
91 | {
92 | return ::FlushFileBuffers(m_hPipe);
93 | }
94 |
95 | BOOL DisconnectNamedPipe(
96 | )
97 | {
98 | return ::DisconnectNamedPipe(m_hPipe);
99 | }
100 |
101 | BOOL WINAPI SetNamedPipeHandleState(
102 | __in_opt LPDWORD lpMode,
103 | __in_opt LPDWORD lpMaxCollectionCount,
104 | __in_opt LPDWORD lpCollectDataTimeout
105 | )
106 | {
107 | return ::SetNamedPipeHandleState(m_hPipe, lpMode, lpMaxCollectionCount, lpCollectDataTimeout);
108 | }
109 |
110 | BOOL TransactNamedPipe(
111 | __in LPVOID lpInBuffer,
112 | __in DWORD nInBufferSize,
113 | __out LPVOID lpOutBuffer,
114 | __in DWORD nOutBufferSize,
115 | __out LPDWORD lpBytesRead,
116 | __inout_opt LPOVERLAPPED lpOverlapped
117 | )
118 | {
119 | return ::TransactNamedPipe(m_hPipe, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize, lpBytesRead, lpOverlapped);
120 | }
121 |
122 | BOOL WaitNamedPipe(
123 | __in LPCTSTR lpNamedPipeName,
124 | __in DWORD nTimeOut
125 | )
126 | {
127 | return ::WaitNamedPipe(lpNamedPipeName, nTimeOut);
128 | }
129 |
130 | DWORD GetNamedPipeClientProcessId()
131 | {
132 | DWORD dwPID = -1;
133 |
134 | if(::GetNamedPipeClientProcessId(m_hPipe, &dwPID))
135 | return dwPID;
136 |
137 | return dwPID;
138 | }
139 |
140 | DWORD GetNamedPipeClientSessionId()
141 | {
142 | DWORD SID = 0;
143 |
144 | if(::GetNamedPipeClientSessionId(m_hPipe, &SID))
145 | return SID;
146 |
147 | return SID;
148 | }
149 |
150 | private:
151 | HANDLE m_hPipe;
152 | };
153 |
154 |
--------------------------------------------------------------------------------
/src/NtfsVolumeParse.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wyrover/CodeLib/cee0615b2cba6d1281b93177aea7a64c4a39e1de/src/NtfsVolumeParse.cpp
--------------------------------------------------------------------------------
/src/NtfsVolumeParse.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include "IVolumeParse.h"
4 |
5 | class CNtfsVolumeParse : public IVolumeParse
6 | {
7 | public:
8 | CNtfsVolumeParse();
9 | virtual ~CNtfsVolumeParse(void);
10 |
11 | virtual BOOL ScanFile( LPCTSTR lpszVolumeName );
12 |
13 | virtual BOOL ScanFileChange(LPCTSTR lpszVolume);
14 |
15 | protected:
16 |
17 | LONGLONG GetRecordTotalSize(LPCTSTR lpszVolume);
18 | };
19 |
20 |
--------------------------------------------------------------------------------
/src/ProcessImpl.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 | #include "ProcessImpl.h"
3 | #include
4 | #include
5 | #include
6 | #pragma comment(lib,"Psapi.lib")
7 | namespace CODELIB
8 | {
9 | CProcessImpl::CProcessImpl(void): m_dwPID(-1), m_hProcess(NULL)
10 | {
11 | }
12 |
13 |
14 | CProcessImpl::~CProcessImpl(void)
15 | {
16 | Close();
17 | }
18 |
19 | BOOL CProcessImpl::Open(DWORD dwPID)
20 | {
21 | assert(NULL == m_hProcess);
22 | m_hProcess =::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID);
23 |
24 | if(NULL != m_hProcess)
25 | m_dwPID = dwPID;
26 |
27 | return (NULL != m_hProcess);
28 | }
29 |
30 | void CProcessImpl::Close()
31 | {
32 | if(NULL != m_hProcess)
33 | {
34 | ::CloseHandle(m_hProcess);
35 | m_hProcess = NULL;
36 | }
37 | }
38 |
39 | BOOL CProcessImpl::Terminate()
40 | {
41 | BOOL bRet = FALSE;
42 |
43 | if(NULL != m_hProcess)
44 | bRet =::TerminateProcess(m_hProcess, 0);
45 |
46 | return bRet;
47 | }
48 |
49 | BOOL CProcessImpl::ReadMemory(LPCVOID lpBase, LPVOID lpBuf, DWORD dwWantRead)
50 | {
51 | BOOL bRet = FALSE;
52 | DWORD dwReaded = 0;
53 |
54 | if(NULL != m_hProcess)
55 | bRet =::ReadProcessMemory(m_hProcess, lpBase, lpBuf, dwWantRead, (SIZE_T*)&dwReaded);
56 |
57 | return ((TRUE == bRet) && (dwWantRead == dwReaded));
58 | }
59 |
60 | BOOL CProcessImpl::WriteMemory(LPVOID lpBase, LPCVOID lpBuf, DWORD dwWantWrite)
61 | {
62 | BOOL bRet = FALSE;
63 | DWORD dwWrited = 0;
64 |
65 | if(NULL != m_hProcess)
66 | bRet =::WriteProcessMemory(m_hProcess, lpBase, lpBuf, dwWantWrite, (SIZE_T*)&dwWrited);
67 |
68 | return ((TRUE == bRet) && (dwWrited == dwWantWrite));
69 | }
70 |
71 | DWORD CProcessImpl::GetPID()
72 | {
73 | return m_dwPID;
74 | }
75 |
76 | LPCTSTR CProcessImpl::GetFullPathName()
77 | {
78 | ZeroMemory(m_sFullPathName, MAX_PATH);
79 |
80 | if(0 != GetModuleFileNameEx(m_hProcess, NULL, m_sFullPathName, MAX_PATH))
81 | return m_sFullPathName;
82 |
83 | return NULL;
84 | }
85 |
86 | BOOL CProcessImpl::GetIntegrityLevel(INTEGRITYLEVEL* pLevel)
87 | {
88 | if(!pLevel)
89 | return FALSE;
90 |
91 | HANDLE process_token;
92 |
93 | if(!OpenProcessToken(m_hProcess, TOKEN_QUERY | TOKEN_QUERY_SOURCE,
94 | &process_token))
95 | return FALSE;
96 |
97 | DWORD token_info_length = 0;
98 |
99 | if(GetTokenInformation(process_token, TokenIntegrityLevel, NULL, 0,
100 | &token_info_length) ||
101 | GetLastError() != ERROR_INSUFFICIENT_BUFFER)
102 | return FALSE;
103 |
104 | char* tokenInfo = new char[token_info_length];
105 |
106 | TOKEN_MANDATORY_LABEL* token_label =
107 | reinterpret_cast(tokenInfo);
108 |
109 | if(!token_label)
110 | return FALSE;
111 |
112 | if(!GetTokenInformation(process_token, TokenIntegrityLevel, token_label,
113 | token_info_length, &token_info_length))
114 | return FALSE;
115 |
116 | DWORD integrity_level = *GetSidSubAuthority(token_label->Label.Sid,
117 | (DWORD)(UCHAR)(*GetSidSubAuthorityCount(token_label->Label.Sid) - 1));
118 |
119 | if(integrity_level < SECURITY_MANDATORY_MEDIUM_RID)
120 | {
121 | *pLevel = LOW_INTEGRITY;
122 | }
123 | else if(integrity_level >= SECURITY_MANDATORY_MEDIUM_RID &&
124 | integrity_level < SECURITY_MANDATORY_HIGH_RID)
125 | {
126 | *pLevel = MEDIUM_INTEGRITY;
127 | }
128 | else if(integrity_level >= SECURITY_MANDATORY_HIGH_RID)
129 | {
130 | *pLevel = HIGH_INTEGRITY;
131 | }
132 | else
133 | {
134 | return FALSE;
135 | }
136 |
137 | delete[] tokenInfo;
138 | tokenInfo = NULL;
139 |
140 | return TRUE;
141 | }
142 |
143 | HANDLE CProcessImpl::GetHandle()
144 | {
145 | return m_hProcess;
146 | }
147 |
148 | DWORD CProcessImpl::FindProcessIDByName(LPCTSTR lpszName)
149 | {
150 | DWORD dwPID = 0;
151 | PROCESSENTRY32 pe32 = {sizeof(pe32)};
152 | HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
153 |
154 | if(INVALID_HANDLE_VALUE == hProcessSnap) return -1;
155 |
156 | if(Process32First(hProcessSnap, &pe32))
157 | {
158 | do
159 | {
160 | if(0 == _tcsicmp(lpszName, pe32.szExeFile))
161 | {
162 | dwPID = pe32.th32ProcessID;
163 | break;
164 | }
165 | }
166 | while(Process32Next(hProcessSnap, &pe32));
167 | }
168 |
169 | CloseHandle(hProcessSnap);
170 | hProcessSnap = NULL;
171 | return dwPID;
172 | }
173 |
174 | BOOL CProcessImpl::EnumProcess(std::vector& proVec)
175 | {
176 | PROCESSENTRY32 pe32 = {sizeof(pe32)};
177 | HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
178 |
179 | if(INVALID_HANDLE_VALUE == hProcessSnap) return FALSE;
180 |
181 | if(Process32First(hProcessSnap, &pe32))
182 | {
183 | do
184 | {
185 | proVec.push_back(pe32);
186 | }
187 | while(Process32Next(hProcessSnap, &pe32));
188 | }
189 |
190 | CloseHandle(hProcessSnap);
191 | hProcessSnap = NULL;
192 | return TRUE;
193 | }
194 |
195 | BOOL CProcessImpl::CreateLowIntegrityProcess(PWSTR pszCommandLine)
196 | {
197 | DWORD dwError = ERROR_SUCCESS;
198 | HANDLE hToken = NULL;
199 | HANDLE hNewToken = NULL;
200 | SID_IDENTIFIER_AUTHORITY MLAuthority = SECURITY_MANDATORY_LABEL_AUTHORITY;
201 | PSID pIntegritySid = NULL;
202 | TOKEN_MANDATORY_LABEL tml = { 0 };
203 | STARTUPINFO si = { sizeof(si) };
204 | PROCESS_INFORMATION pi = { 0 };
205 |
206 | // Open the primary access token of the process.
207 | if(!OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE | TOKEN_QUERY |
208 | TOKEN_ADJUST_DEFAULT | TOKEN_ASSIGN_PRIMARY, &hToken))
209 | {
210 | dwError = GetLastError();
211 | goto Cleanup;
212 | }
213 |
214 | // Duplicate the primary token of the current process.
215 | if(!DuplicateTokenEx(hToken, 0, NULL, SecurityImpersonation,
216 | TokenPrimary, &hNewToken))
217 | {
218 | dwError = GetLastError();
219 | goto Cleanup;
220 | }
221 |
222 | // Create the low integrity SID.
223 | if(!AllocateAndInitializeSid(&MLAuthority, 1, SECURITY_MANDATORY_LOW_RID,
224 | 0, 0, 0, 0, 0, 0, 0, &pIntegritySid))
225 | {
226 | dwError = GetLastError();
227 | goto Cleanup;
228 | }
229 |
230 | tml.Label.Attributes = SE_GROUP_INTEGRITY;
231 | tml.Label.Sid = pIntegritySid;
232 |
233 | // Set the integrity level in the access token to low.
234 | if(!SetTokenInformation(hNewToken, TokenIntegrityLevel, &tml,
235 | (sizeof(tml) + GetLengthSid(pIntegritySid))))
236 | {
237 | dwError = GetLastError();
238 | goto Cleanup;
239 | }
240 |
241 | // Create the new process at the Low integrity level.
242 | if(!CreateProcessAsUser(hNewToken, NULL, pszCommandLine, NULL, NULL,
243 | FALSE, 0, NULL, NULL, &si, &pi))
244 | {
245 | dwError = GetLastError();
246 | goto Cleanup;
247 | }
248 |
249 | Cleanup:
250 |
251 | // Centralized cleanup for all allocated resources.
252 | if(hToken)
253 | {
254 | CloseHandle(hToken);
255 | hToken = NULL;
256 | }
257 |
258 | if(hNewToken)
259 | {
260 | CloseHandle(hNewToken);
261 | hNewToken = NULL;
262 | }
263 |
264 | if(pIntegritySid)
265 | {
266 | FreeSid(pIntegritySid);
267 | pIntegritySid = NULL;
268 | }
269 |
270 | if(pi.hProcess)
271 | {
272 | CloseHandle(pi.hProcess);
273 | pi.hProcess = NULL;
274 | }
275 |
276 | if(pi.hThread)
277 | {
278 | CloseHandle(pi.hThread);
279 | pi.hThread = NULL;
280 | }
281 |
282 | if(ERROR_SUCCESS != dwError)
283 | {
284 | // Make sure that the error code is set for failure.
285 | SetLastError(dwError);
286 | return FALSE;
287 | }
288 | else
289 | {
290 | return TRUE;
291 | }
292 | }
293 |
294 | SIZE_T CProcessImpl::VirtualQueryEx(LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength)
295 | {
296 | return ::VirtualQueryEx(m_hProcess, lpAddress, lpBuffer, dwLength);
297 | }
298 |
299 | BOOL CProcessImpl::IsOpened()
300 | {
301 | return (NULL != m_hProcess);
302 | }
303 |
304 | }
305 |
306 |
--------------------------------------------------------------------------------
/src/ProcessImpl.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "IProcess.h"
3 | #include
4 | #include
5 |
6 | namespace CODELIB
7 | {
8 | class CProcessImpl : public IProcess
9 | {
10 | public:
11 | CProcessImpl(void);
12 | virtual ~CProcessImpl(void);
13 | public:
14 | BOOL IsOpened();
15 | BOOL Open(DWORD dwPID);
16 | void Close();
17 | BOOL Terminate();
18 | BOOL ReadMemory(LPCVOID lpBase, LPVOID lpBuf, DWORD dwWantRead);
19 | BOOL WriteMemory(LPVOID lpBase, LPCVOID lpBuf, DWORD dwWantWrite);
20 | DWORD GetPID();
21 | LPCTSTR GetFullPathName();
22 | BOOL GetIntegrityLevel(INTEGRITYLEVEL* pLevel);
23 | HANDLE GetHandle();
24 | static DWORD FindProcessIDByName(LPCTSTR lpszName);
25 | static BOOL EnumProcess(std::vector& proVec);
26 | static BOOL CreateLowIntegrityProcess(PWSTR pszCommandLine);
27 | SIZE_T VirtualQueryEx(LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength);
28 | private:
29 | DWORD m_dwPID;
30 | HANDLE m_hProcess;
31 | TCHAR m_sFullPathName[MAX_PATH];
32 | };
33 | }
34 |
35 |
36 |
--------------------------------------------------------------------------------
/src/Services/ServiceBase.cpp:
--------------------------------------------------------------------------------
1 | /****************************** Module Header ******************************\
2 | * Module Name: ServiceBase.cpp
3 | * Project: CppWindowsService
4 | * Copyright (c) Microsoft Corporation.
5 | *
6 | * Provides a base class for a service that will exist as part of a service
7 | * application. CServiceBase must be derived from when creating a new service
8 | * class.
9 | *
10 | * This source is subject to the Microsoft Public License.
11 | * See http://www.microsoft.com/en-us/openness/resources/licenses.aspx#MPL.
12 | * All other rights reserved.
13 | *
14 | * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
15 | * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
16 | * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
17 | \***************************************************************************/
18 |
19 | #pragma region Includes
20 | #include "stdafx.h"
21 | #include "ServiceBase.h"
22 | #include
23 | #include
24 | #pragma endregion
25 |
26 |
27 | #pragma region Static Members
28 |
29 | // Initialize the singleton service instance.
30 | CServiceBase *CServiceBase::s_service = NULL;
31 |
32 |
33 | //
34 | // FUNCTION: CServiceBase::Run(CServiceBase &)
35 | //
36 | // PURPOSE: Register the executable for a service with the Service Control
37 | // Manager (SCM). After you call Run(ServiceBase), the SCM issues a Start
38 | // command, which results in a call to the OnStart method in the service.
39 | // This method blocks until the service has stopped.
40 | //
41 | // PARAMETERS:
42 | // * service - the reference to a CServiceBase object. It will become the
43 | // singleton service instance of this service application.
44 | //
45 | // RETURN VALUE: If the function succeeds, the return value is TRUE. If the
46 | // function fails, the return value is FALSE. To get extended error
47 | // information, call GetLastError.
48 | //
49 | BOOL CServiceBase::Run(CServiceBase &service)
50 | {
51 | s_service = &service;
52 |
53 | SERVICE_TABLE_ENTRY serviceTable[] =
54 | {
55 | { service.m_name, ServiceMain },
56 | { NULL, NULL }
57 | };
58 |
59 | // Connects the main thread of a service process to the service control
60 | // manager, which causes the thread to be the service control dispatcher
61 | // thread for the calling process. This call returns when the service has
62 | // stopped. The process should simply terminate when the call returns.
63 | return StartServiceCtrlDispatcher(serviceTable);
64 | }
65 |
66 |
67 | //
68 | // FUNCTION: CServiceBase::ServiceMain(DWORD, PWSTR *)
69 | //
70 | // PURPOSE: Entry point for the service. It registers the handler function
71 | // for the service and starts the service.
72 | //
73 | // PARAMETERS:
74 | // * dwArgc - number of command line arguments
75 | // * lpszArgv - array of command line arguments
76 | //
77 | void WINAPI CServiceBase::ServiceMain(DWORD dwArgc, PWSTR *pszArgv)
78 | {
79 | assert(s_service != NULL);
80 |
81 | // Register the handler function for the service
82 | s_service->m_statusHandle = RegisterServiceCtrlHandler(
83 | s_service->m_name, ServiceCtrlHandler);
84 | if (s_service->m_statusHandle == NULL)
85 | {
86 | throw GetLastError();
87 | }
88 |
89 | // Start the service.
90 | s_service->Start(dwArgc, pszArgv);
91 | }
92 |
93 |
94 | //
95 | // FUNCTION: CServiceBase::ServiceCtrlHandler(DWORD)
96 | //
97 | // PURPOSE: The function is called by the SCM whenever a control code is
98 | // sent to the service.
99 | //
100 | // PARAMETERS:
101 | // * dwCtrlCode - the control code. This parameter can be one of the
102 | // following values:
103 | //
104 | // SERVICE_CONTROL_CONTINUE
105 | // SERVICE_CONTROL_INTERROGATE
106 | // SERVICE_CONTROL_NETBINDADD
107 | // SERVICE_CONTROL_NETBINDDISABLE
108 | // SERVICE_CONTROL_NETBINDREMOVE
109 | // SERVICE_CONTROL_PARAMCHANGE
110 | // SERVICE_CONTROL_PAUSE
111 | // SERVICE_CONTROL_SHUTDOWN
112 | // SERVICE_CONTROL_STOP
113 | //
114 | // This parameter can also be a user-defined control code ranges from 128
115 | // to 255.
116 | //
117 | void WINAPI CServiceBase::ServiceCtrlHandler(DWORD dwCtrl)
118 | {
119 | switch (dwCtrl)
120 | {
121 | case SERVICE_CONTROL_STOP: s_service->Stop(); break;
122 | case SERVICE_CONTROL_PAUSE: s_service->Pause(); break;
123 | case SERVICE_CONTROL_CONTINUE: s_service->Continue(); break;
124 | case SERVICE_CONTROL_SHUTDOWN: s_service->Shutdown(); break;
125 | case SERVICE_CONTROL_INTERROGATE: break;
126 | default: break;
127 | }
128 | }
129 |
130 | #pragma endregion
131 |
132 |
133 | #pragma region Service Constructor and Destructor
134 |
135 | //
136 | // FUNCTION: CServiceBase::CServiceBase(PWSTR, BOOL, BOOL, BOOL)
137 | //
138 | // PURPOSE: The constructor of CServiceBase. It initializes a new instance
139 | // of the CServiceBase class. The optional parameters (fCanStop,
140 | /// fCanShutdown and fCanPauseContinue) allow you to specify whether the
141 | // service can be stopped, paused and continued, or be notified when system
142 | // shutdown occurs.
143 | //
144 | // PARAMETERS:
145 | // * pszServiceName - the name of the service
146 | // * fCanStop - the service can be stopped
147 | // * fCanShutdown - the service is notified when system shutdown occurs
148 | // * fCanPauseContinue - the service can be paused and continued
149 | //
150 | CServiceBase::CServiceBase(PWSTR pszServiceName,
151 | BOOL fCanStop,
152 | BOOL fCanShutdown,
153 | BOOL fCanPauseContinue)
154 | {
155 | // Service name must be a valid string and cannot be NULL.
156 | m_name = (pszServiceName == NULL) ? L"" : pszServiceName;
157 |
158 | m_statusHandle = NULL;
159 |
160 | // The service runs in its own process.
161 | m_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
162 |
163 | // The service is starting.
164 | m_status.dwCurrentState = SERVICE_START_PENDING;
165 |
166 | // The accepted commands of the service.
167 | DWORD dwControlsAccepted = 0;
168 | if (fCanStop)
169 | dwControlsAccepted |= SERVICE_ACCEPT_STOP;
170 | if (fCanShutdown)
171 | dwControlsAccepted |= SERVICE_ACCEPT_SHUTDOWN;
172 | if (fCanPauseContinue)
173 | dwControlsAccepted |= SERVICE_ACCEPT_PAUSE_CONTINUE;
174 | m_status.dwControlsAccepted = dwControlsAccepted;
175 |
176 | m_status.dwWin32ExitCode = NO_ERROR;
177 | m_status.dwServiceSpecificExitCode = 0;
178 | m_status.dwCheckPoint = 0;
179 | m_status.dwWaitHint = 0;
180 | }
181 |
182 |
183 | //
184 | // FUNCTION: CServiceBase::~CServiceBase()
185 | //
186 | // PURPOSE: The virtual destructor of CServiceBase.
187 | //
188 | CServiceBase::~CServiceBase(void)
189 | {
190 | }
191 |
192 | #pragma endregion
193 |
194 |
195 | #pragma region Service Start, Stop, Pause, Continue, and Shutdown
196 |
197 | //
198 | // FUNCTION: CServiceBase::Start(DWORD, PWSTR *)
199 | //
200 | // PURPOSE: The function starts the service. It calls the OnStart virtual
201 | // function in which you can specify the actions to take when the service
202 | // starts. If an error occurs during the startup, the error will be logged
203 | // in the Application event log, and the service will be stopped.
204 | //
205 | // PARAMETERS:
206 | // * dwArgc - number of command line arguments
207 | // * lpszArgv - array of command line arguments
208 | //
209 | void CServiceBase::Start(DWORD dwArgc, PWSTR *pszArgv)
210 | {
211 | try
212 | {
213 | // Tell SCM that the service is starting.
214 | SetServiceStatus(SERVICE_START_PENDING);
215 |
216 | // Perform service-specific initialization.
217 | OnStart(dwArgc, pszArgv);
218 |
219 | // Tell SCM that the service is started.
220 | SetServiceStatus(SERVICE_RUNNING);
221 | }
222 | catch (DWORD dwError)
223 | {
224 | // Log the error.
225 | WriteErrorLogEntry(L"Service Start", dwError);
226 |
227 | // Set the service status to be stopped.
228 | SetServiceStatus(SERVICE_STOPPED, dwError);
229 | }
230 | catch (...)
231 | {
232 | // Log the error.
233 | WriteEventLogEntry(L"Service failed to start.", EVENTLOG_ERROR_TYPE);
234 |
235 | // Set the service status to be stopped.
236 | SetServiceStatus(SERVICE_STOPPED);
237 | }
238 | }
239 |
240 |
241 | //
242 | // FUNCTION: CServiceBase::OnStart(DWORD, PWSTR *)
243 | //
244 | // PURPOSE: When implemented in a derived class, executes when a Start
245 | // command is sent to the service by the SCM or when the operating system
246 | // starts (for a service that starts automatically). Specifies actions to
247 | // take when the service starts. Be sure to periodically call
248 | // CServiceBase::SetServiceStatus() with SERVICE_START_PENDING if the
249 | // procedure is going to take long time. You may also consider spawning a
250 | // new thread in OnStart to perform time-consuming initialization tasks.
251 | //
252 | // PARAMETERS:
253 | // * dwArgc - number of command line arguments
254 | // * lpszArgv - array of command line arguments
255 | //
256 | void CServiceBase::OnStart(DWORD dwArgc, PWSTR *pszArgv)
257 | {
258 | }
259 |
260 |
261 | //
262 | // FUNCTION: CServiceBase::Stop()
263 | //
264 | // PURPOSE: The function stops the service. It calls the OnStop virtual
265 | // function in which you can specify the actions to take when the service
266 | // stops. If an error occurs, the error will be logged in the Application
267 | // event log, and the service will be restored to the original state.
268 | //
269 | void CServiceBase::Stop()
270 | {
271 | DWORD dwOriginalState = m_status.dwCurrentState;
272 | try
273 | {
274 | // Tell SCM that the service is stopping.
275 | SetServiceStatus(SERVICE_STOP_PENDING);
276 |
277 | // Perform service-specific stop operations.
278 | OnStop();
279 |
280 | // Tell SCM that the service is stopped.
281 | SetServiceStatus(SERVICE_STOPPED);
282 | }
283 | catch (DWORD dwError)
284 | {
285 | // Log the error.
286 | WriteErrorLogEntry(L"Service Stop", dwError);
287 |
288 | // Set the orginal service status.
289 | SetServiceStatus(dwOriginalState);
290 | }
291 | catch (...)
292 | {
293 | // Log the error.
294 | WriteEventLogEntry(L"Service failed to stop.", EVENTLOG_ERROR_TYPE);
295 |
296 | // Set the orginal service status.
297 | SetServiceStatus(dwOriginalState);
298 | }
299 | }
300 |
301 |
302 | //
303 | // FUNCTION: CServiceBase::OnStop()
304 | //
305 | // PURPOSE: When implemented in a derived class, executes when a Stop
306 | // command is sent to the service by the SCM. Specifies actions to take
307 | // when a service stops running. Be sure to periodically call
308 | // CServiceBase::SetServiceStatus() with SERVICE_STOP_PENDING if the
309 | // procedure is going to take long time.
310 | //
311 | void CServiceBase::OnStop()
312 | {
313 | }
314 |
315 |
316 | //
317 | // FUNCTION: CServiceBase::Pause()
318 | //
319 | // PURPOSE: The function pauses the service if the service supports pause
320 | // and continue. It calls the OnPause virtual function in which you can
321 | // specify the actions to take when the service pauses. If an error occurs,
322 | // the error will be logged in the Application event log, and the service
323 | // will become running.
324 | //
325 | void CServiceBase::Pause()
326 | {
327 | try
328 | {
329 | // Tell SCM that the service is pausing.
330 | SetServiceStatus(SERVICE_PAUSE_PENDING);
331 |
332 | // Perform service-specific pause operations.
333 | OnPause();
334 |
335 | // Tell SCM that the service is paused.
336 | SetServiceStatus(SERVICE_PAUSED);
337 | }
338 | catch (DWORD dwError)
339 | {
340 | // Log the error.
341 | WriteErrorLogEntry(L"Service Pause", dwError);
342 |
343 | // Tell SCM that the service is still running.
344 | SetServiceStatus(SERVICE_RUNNING);
345 | }
346 | catch (...)
347 | {
348 | // Log the error.
349 | WriteEventLogEntry(L"Service failed to pause.", EVENTLOG_ERROR_TYPE);
350 |
351 | // Tell SCM that the service is still running.
352 | SetServiceStatus(SERVICE_RUNNING);
353 | }
354 | }
355 |
356 |
357 | //
358 | // FUNCTION: CServiceBase::OnPause()
359 | //
360 | // PURPOSE: When implemented in a derived class, executes when a Pause
361 | // command is sent to the service by the SCM. Specifies actions to take
362 | // when a service pauses.
363 | //
364 | void CServiceBase::OnPause()
365 | {
366 | }
367 |
368 |
369 | //
370 | // FUNCTION: CServiceBase::Continue()
371 | //
372 | // PURPOSE: The function resumes normal functioning after being paused if
373 | // the service supports pause and continue. It calls the OnContinue virtual
374 | // function in which you can specify the actions to take when the service
375 | // continues. If an error occurs, the error will be logged in the
376 | // Application event log, and the service will still be paused.
377 | //
378 | void CServiceBase::Continue()
379 | {
380 | try
381 | {
382 | // Tell SCM that the service is resuming.
383 | SetServiceStatus(SERVICE_CONTINUE_PENDING);
384 |
385 | // Perform service-specific continue operations.
386 | OnContinue();
387 |
388 | // Tell SCM that the service is running.
389 | SetServiceStatus(SERVICE_RUNNING);
390 | }
391 | catch (DWORD dwError)
392 | {
393 | // Log the error.
394 | WriteErrorLogEntry(L"Service Continue", dwError);
395 |
396 | // Tell SCM that the service is still paused.
397 | SetServiceStatus(SERVICE_PAUSED);
398 | }
399 | catch (...)
400 | {
401 | // Log the error.
402 | WriteEventLogEntry(L"Service failed to resume.", EVENTLOG_ERROR_TYPE);
403 |
404 | // Tell SCM that the service is still paused.
405 | SetServiceStatus(SERVICE_PAUSED);
406 | }
407 | }
408 |
409 |
410 | //
411 | // FUNCTION: CServiceBase::OnContinue()
412 | //
413 | // PURPOSE: When implemented in a derived class, OnContinue runs when a
414 | // Continue command is sent to the service by the SCM. Specifies actions to
415 | // take when a service resumes normal functioning after being paused.
416 | //
417 | void CServiceBase::OnContinue()
418 | {
419 | }
420 |
421 |
422 | //
423 | // FUNCTION: CServiceBase::Shutdown()
424 | //
425 | // PURPOSE: The function executes when the system is shutting down. It
426 | // calls the OnShutdown virtual function in which you can specify what
427 | // should occur immediately prior to the system shutting down. If an error
428 | // occurs, the error will be logged in the Application event log.
429 | //
430 | void CServiceBase::Shutdown()
431 | {
432 | try
433 | {
434 | // Perform service-specific shutdown operations.
435 | OnShutdown();
436 |
437 | // Tell SCM that the service is stopped.
438 | SetServiceStatus(SERVICE_STOPPED);
439 | }
440 | catch (DWORD dwError)
441 | {
442 | // Log the error.
443 | WriteErrorLogEntry(L"Service Shutdown", dwError);
444 | }
445 | catch (...)
446 | {
447 | // Log the error.
448 | WriteEventLogEntry(L"Service failed to shut down.", EVENTLOG_ERROR_TYPE);
449 | }
450 | }
451 |
452 |
453 | //
454 | // FUNCTION: CServiceBase::OnShutdown()
455 | //
456 | // PURPOSE: When implemented in a derived class, executes when the system
457 | // is shutting down. Specifies what should occur immediately prior to the
458 | // system shutting down.
459 | //
460 | void CServiceBase::OnShutdown()
461 | {
462 | }
463 |
464 | #pragma endregion
465 |
466 |
467 | #pragma region Helper Functions
468 |
469 | //
470 | // FUNCTION: CServiceBase::SetServiceStatus(DWORD, DWORD, DWORD)
471 | //
472 | // PURPOSE: The function sets the service status and reports the status to
473 | // the SCM.
474 | //
475 | // PARAMETERS:
476 | // * dwCurrentState - the state of the service
477 | // * dwWin32ExitCode - error code to report
478 | // * dwWaitHint - estimated time for pending operation, in milliseconds
479 | //
480 | void CServiceBase::SetServiceStatus(DWORD dwCurrentState,
481 | DWORD dwWin32ExitCode,
482 | DWORD dwWaitHint)
483 | {
484 | static DWORD dwCheckPoint = 1;
485 |
486 | // Fill in the SERVICE_STATUS structure of the service.
487 |
488 | m_status.dwCurrentState = dwCurrentState;
489 | m_status.dwWin32ExitCode = dwWin32ExitCode;
490 | m_status.dwWaitHint = dwWaitHint;
491 |
492 | m_status.dwCheckPoint =
493 | ((dwCurrentState == SERVICE_RUNNING) ||
494 | (dwCurrentState == SERVICE_STOPPED)) ?
495 | 0 : dwCheckPoint++;
496 |
497 | // Report the status of the service to the SCM.
498 | ::SetServiceStatus(m_statusHandle, &m_status);
499 | }
500 |
501 |
502 | //
503 | // FUNCTION: CServiceBase::WriteEventLogEntry(PWSTR, WORD)
504 | //
505 | // PURPOSE: Log a message to the Application event log.
506 | //
507 | // PARAMETERS:
508 | // * pszMessage - string message to be logged.
509 | // * wType - the type of event to be logged. The parameter can be one of
510 | // the following values.
511 | //
512 | // EVENTLOG_SUCCESS
513 | // EVENTLOG_AUDIT_FAILURE
514 | // EVENTLOG_AUDIT_SUCCESS
515 | // EVENTLOG_ERROR_TYPE
516 | // EVENTLOG_INFORMATION_TYPE
517 | // EVENTLOG_WARNING_TYPE
518 | //
519 | void CServiceBase::WriteEventLogEntry(PWSTR pszMessage, WORD wType)
520 | {
521 | HANDLE hEventSource = NULL;
522 | LPCWSTR lpszStrings[2] = { NULL, NULL };
523 |
524 | hEventSource = RegisterEventSource(NULL, m_name);
525 | if (hEventSource)
526 | {
527 | lpszStrings[0] = m_name;
528 | lpszStrings[1] = pszMessage;
529 |
530 | ReportEvent(hEventSource, // Event log handle
531 | wType, // Event type
532 | 0, // Event category
533 | 0, // Event identifier
534 | NULL, // No security identifier
535 | 2, // Size of lpszStrings array
536 | 0, // No binary data
537 | lpszStrings, // Array of strings
538 | NULL // No binary data
539 | );
540 |
541 | DeregisterEventSource(hEventSource);
542 | }
543 | }
544 |
545 |
546 | //
547 | // FUNCTION: CServiceBase::WriteErrorLogEntry(PWSTR, DWORD)
548 | //
549 | // PURPOSE: Log an error message to the Application event log.
550 | //
551 | // PARAMETERS:
552 | // * pszFunction - the function that gives the error
553 | // * dwError - the error code
554 | //
555 | void CServiceBase::WriteErrorLogEntry(PWSTR pszFunction, DWORD dwError)
556 | {
557 | wchar_t szMessage[260];
558 | StringCchPrintf(szMessage, ARRAYSIZE(szMessage),
559 | L"%s failed w/err 0x%08lx", pszFunction, dwError);
560 | WriteEventLogEntry(szMessage, EVENTLOG_ERROR_TYPE);
561 | }
562 |
563 | #pragma endregion
--------------------------------------------------------------------------------
/src/Services/ServiceBase.h:
--------------------------------------------------------------------------------
1 | /****************************** Module Header ******************************\
2 | * Module Name: ServiceBase.h
3 | * Project: CppWindowsService
4 | * Copyright (c) Microsoft Corporation.
5 | *
6 | * Provides a base class for a service that will exist as part of a service
7 | * application. CServiceBase must be derived from when creating a new service
8 | * class.
9 | *
10 | * This source is subject to the Microsoft Public License.
11 | * See http://www.microsoft.com/en-us/openness/resources/licenses.aspx#MPL.
12 | * All other rights reserved.
13 | *
14 | * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
15 | * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
16 | * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
17 | \***************************************************************************/
18 |
19 | #pragma once
20 |
21 | #include
22 |
23 |
24 | class CServiceBase
25 | {
26 | public:
27 |
28 | // Register the executable for a service with the Service Control Manager
29 | // (SCM). After you call Run(ServiceBase), the SCM issues a Start command,
30 | // which results in a call to the OnStart method in the service. This
31 | // method blocks until the service has stopped.
32 | static BOOL Run(CServiceBase &service);
33 |
34 | // Service object constructor. The optional parameters (fCanStop,
35 | // fCanShutdown and fCanPauseContinue) allow you to specify whether the
36 | // service can be stopped, paused and continued, or be notified when
37 | // system shutdown occurs.
38 | CServiceBase(PWSTR pszServiceName,
39 | BOOL fCanStop = TRUE,
40 | BOOL fCanShutdown = TRUE,
41 | BOOL fCanPauseContinue = FALSE);
42 |
43 | // Service object destructor.
44 | virtual ~CServiceBase(void);
45 |
46 | // Stop the service.
47 | void Stop();
48 |
49 | protected:
50 |
51 | // When implemented in a derived class, executes when a Start command is
52 | // sent to the service by the SCM or when the operating system starts
53 | // (for a service that starts automatically). Specifies actions to take
54 | // when the service starts.
55 | virtual void OnStart(DWORD dwArgc, PWSTR *pszArgv);
56 |
57 | // When implemented in a derived class, executes when a Stop command is
58 | // sent to the service by the SCM. Specifies actions to take when a
59 | // service stops running.
60 | virtual void OnStop();
61 |
62 | // When implemented in a derived class, executes when a Pause command is
63 | // sent to the service by the SCM. Specifies actions to take when a
64 | // service pauses.
65 | virtual void OnPause();
66 |
67 | // When implemented in a derived class, OnContinue runs when a Continue
68 | // command is sent to the service by the SCM. Specifies actions to take
69 | // when a service resumes normal functioning after being paused.
70 | virtual void OnContinue();
71 |
72 | // When implemented in a derived class, executes when the system is
73 | // shutting down. Specifies what should occur immediately prior to the
74 | // system shutting down.
75 | virtual void OnShutdown();
76 |
77 | // Set the service status and report the status to the SCM.
78 | void SetServiceStatus(DWORD dwCurrentState,
79 | DWORD dwWin32ExitCode = NO_ERROR,
80 | DWORD dwWaitHint = 0);
81 |
82 | // Log a message to the Application event log.
83 | void WriteEventLogEntry(PWSTR pszMessage, WORD wType);
84 |
85 | // Log an error message to the Application event log.
86 | void WriteErrorLogEntry(PWSTR pszFunction,
87 | DWORD dwError = GetLastError());
88 |
89 | private:
90 |
91 | // Entry point for the service. It registers the handler function for the
92 | // service and starts the service.
93 | static void WINAPI ServiceMain(DWORD dwArgc, LPWSTR *lpszArgv);
94 |
95 | // The function is called by the SCM whenever a control code is sent to
96 | // the service.
97 | static void WINAPI ServiceCtrlHandler(DWORD dwCtrl);
98 |
99 | // Start the service.
100 | void Start(DWORD dwArgc, PWSTR *pszArgv);
101 |
102 | // Pause the service.
103 | void Pause();
104 |
105 | // Resume the service after being paused.
106 | void Continue();
107 |
108 | // Execute when the system is shutting down.
109 | void Shutdown();
110 |
111 | // The singleton service instance.
112 | static CServiceBase *s_service;
113 |
114 | // The name of the service
115 | PWSTR m_name;
116 |
117 | // The status of the service
118 | SERVICE_STATUS m_status;
119 |
120 | // The service status handle
121 | SERVICE_STATUS_HANDLE m_statusHandle;
122 | };
--------------------------------------------------------------------------------
/src/Services/ServiceInstaller.cpp:
--------------------------------------------------------------------------------
1 | /****************************** Module Header ******************************\
2 | * Module Name: ServiceInstaller.cpp
3 | * Project: CppWindowsService
4 | * Copyright (c) Microsoft Corporation.
5 | *
6 | * The file implements functions that install and uninstall the service.
7 | *
8 | * This source is subject to the Microsoft Public License.
9 | * See http://www.microsoft.com/en-us/openness/resources/licenses.aspx#MPL.
10 | * All other rights reserved.
11 | *
12 | * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
13 | * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
14 | * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
15 | \***************************************************************************/
16 |
17 | #pragma region "Includes"
18 | #include "stdafx.h"
19 | #include
20 | #include
21 | #include "ServiceInstaller.h"
22 | #pragma endregion
23 |
24 |
25 | //
26 | // FUNCTION: InstallService
27 | //
28 | // PURPOSE: Install the current application as a service to the local
29 | // service control manager database.
30 | //
31 | // PARAMETERS:
32 | // * pszServiceName - the name of the service to be installed
33 | // * pszDisplayName - the display name of the service
34 | // * dwStartType - the service start option. This parameter can be one of
35 | // the following values: SERVICE_AUTO_START, SERVICE_BOOT_START,
36 | // SERVICE_DEMAND_START, SERVICE_DISABLED, SERVICE_SYSTEM_START.
37 | // * pszDependencies - a pointer to a double null-terminated array of null-
38 | // separated names of services or load ordering groups that the system
39 | // must start before this service.
40 | // * pszAccount - the name of the account under which the service runs.
41 | // * pszPassword - the password to the account name.
42 | //
43 | // NOTE: If the function fails to install the service, it prints the error
44 | // in the standard output stream for users to diagnose the problem.
45 | //
46 | void InstallService(PWSTR pszServiceName,
47 | PWSTR pszDisplayName,
48 | DWORD dwStartType,
49 | PWSTR pszDependencies,
50 | PWSTR pszAccount,
51 | PWSTR pszPassword)
52 | {
53 | wchar_t szPath[MAX_PATH];
54 | SC_HANDLE schSCManager = NULL;
55 | SC_HANDLE schService = NULL;
56 |
57 | if (GetModuleFileName(NULL, szPath, ARRAYSIZE(szPath)) == 0)
58 | {
59 | wprintf(L"GetModuleFileName failed w/err 0x%08lx\n", GetLastError());
60 | goto Cleanup;
61 | }
62 |
63 | // Open the local default service control manager database
64 | schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT |
65 | SC_MANAGER_CREATE_SERVICE);
66 | if (schSCManager == NULL)
67 | {
68 | wprintf(L"OpenSCManager failed w/err 0x%08lx\n", GetLastError());
69 | goto Cleanup;
70 | }
71 |
72 | // Install the service into SCM by calling CreateService
73 | schService = CreateService(
74 | schSCManager, // SCManager database
75 | pszServiceName, // Name of service
76 | pszDisplayName, // Name to display
77 | SERVICE_QUERY_STATUS, // Desired access
78 | SERVICE_WIN32_OWN_PROCESS, // Service type
79 | dwStartType, // Service start type
80 | SERVICE_ERROR_NORMAL, // Error control type
81 | szPath, // Service's binary
82 | NULL, // No load ordering group
83 | NULL, // No tag identifier
84 | pszDependencies, // Dependencies
85 | pszAccount, // Service running account
86 | pszPassword // Password of the account
87 | );
88 | if (schService == NULL)
89 | {
90 | wprintf(L"CreateService failed w/err 0x%08lx\n", GetLastError());
91 | goto Cleanup;
92 | }
93 |
94 | wprintf(L"%s is installed.\n", pszServiceName);
95 |
96 | Cleanup:
97 | // Centralized cleanup for all allocated resources.
98 | if (schSCManager)
99 | {
100 | CloseServiceHandle(schSCManager);
101 | schSCManager = NULL;
102 | }
103 | if (schService)
104 | {
105 | CloseServiceHandle(schService);
106 | schService = NULL;
107 | }
108 | }
109 |
110 |
111 | //
112 | // FUNCTION: UninstallService
113 | //
114 | // PURPOSE: Stop and remove the service from the local service control
115 | // manager database.
116 | //
117 | // PARAMETERS:
118 | // * pszServiceName - the name of the service to be removed.
119 | //
120 | // NOTE: If the function fails to uninstall the service, it prints the
121 | // error in the standard output stream for users to diagnose the problem.
122 | //
123 | void UninstallService(PWSTR pszServiceName)
124 | {
125 | SC_HANDLE schSCManager = NULL;
126 | SC_HANDLE schService = NULL;
127 | SERVICE_STATUS ssSvcStatus = {};
128 |
129 | // Open the local default service control manager database
130 | schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
131 | if (schSCManager == NULL)
132 | {
133 | wprintf(L"OpenSCManager failed w/err 0x%08lx\n", GetLastError());
134 | goto Cleanup;
135 | }
136 |
137 | // Open the service with delete, stop, and query status permissions
138 | schService = OpenService(schSCManager, pszServiceName, SERVICE_STOP |
139 | SERVICE_QUERY_STATUS | DELETE);
140 | if (schService == NULL)
141 | {
142 | wprintf(L"OpenService failed w/err 0x%08lx\n", GetLastError());
143 | goto Cleanup;
144 | }
145 |
146 | // Try to stop the service
147 | if (ControlService(schService, SERVICE_CONTROL_STOP, &ssSvcStatus))
148 | {
149 | wprintf(L"Stopping %s.", pszServiceName);
150 | Sleep(1000);
151 |
152 | while (QueryServiceStatus(schService, &ssSvcStatus))
153 | {
154 | if (ssSvcStatus.dwCurrentState == SERVICE_STOP_PENDING)
155 | {
156 | wprintf(L".");
157 | Sleep(1000);
158 | }
159 | else break;
160 | }
161 |
162 | if (ssSvcStatus.dwCurrentState == SERVICE_STOPPED)
163 | {
164 | wprintf(L"\n%s is stopped.\n", pszServiceName);
165 | }
166 | else
167 | {
168 | wprintf(L"\n%s failed to stop.\n", pszServiceName);
169 | }
170 | }
171 |
172 | // Now remove the service by calling DeleteService.
173 | if (!DeleteService(schService))
174 | {
175 | wprintf(L"DeleteService failed w/err 0x%08lx\n", GetLastError());
176 | goto Cleanup;
177 | }
178 |
179 | wprintf(L"%s is removed.\n", pszServiceName);
180 |
181 | Cleanup:
182 | // Centralized cleanup for all allocated resources.
183 | if (schSCManager)
184 | {
185 | CloseServiceHandle(schSCManager);
186 | schSCManager = NULL;
187 | }
188 | if (schService)
189 | {
190 | CloseServiceHandle(schService);
191 | schService = NULL;
192 | }
193 | }
--------------------------------------------------------------------------------
/src/Services/ServiceInstaller.h:
--------------------------------------------------------------------------------
1 | /****************************** Module Header ******************************\
2 | * Module Name: ServiceInstaller.h
3 | * Project: CppWindowsService
4 | * Copyright (c) Microsoft Corporation.
5 | *
6 | * The file declares functions that install and uninstall the service.
7 | *
8 | * This source is subject to the Microsoft Public License.
9 | * See http://www.microsoft.com/en-us/openness/resources/licenses.aspx#MPL.
10 | * All other rights reserved.
11 | *
12 | * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
13 | * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
14 | * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
15 | \***************************************************************************/
16 |
17 | #pragma once
18 |
19 |
20 | //
21 | // FUNCTION: InstallService
22 | //
23 | // PURPOSE: Install the current application as a service to the local
24 | // service control manager database.
25 | //
26 | // PARAMETERS:
27 | // * pszServiceName - the name of the service to be installed
28 | // * pszDisplayName - the display name of the service
29 | // * dwStartType - the service start option. This parameter can be one of
30 | // the following values: SERVICE_AUTO_START, SERVICE_BOOT_START,
31 | // SERVICE_DEMAND_START, SERVICE_DISABLED, SERVICE_SYSTEM_START.
32 | // * pszDependencies - a pointer to a double null-terminated array of null-
33 | // separated names of services or load ordering groups that the system
34 | // must start before this service.
35 | // * pszAccount - the name of the account under which the service runs.
36 | // * pszPassword - the password to the account name.
37 | //
38 | // NOTE: If the function fails to install the service, it prints the error
39 | // in the standard output stream for users to diagnose the problem.
40 | //
41 | void InstallService(PWSTR pszServiceName,
42 | PWSTR pszDisplayName,
43 | DWORD dwStartType,
44 | PWSTR pszDependencies,
45 | PWSTR pszAccount,
46 | PWSTR pszPassword);
47 |
48 |
49 | //
50 | // FUNCTION: UninstallService
51 | //
52 | // PURPOSE: Stop and remove the service from the local service control
53 | // manager database.
54 | //
55 | // PARAMETERS:
56 | // * pszServiceName - the name of the service to be removed.
57 | //
58 | // NOTE: If the function fails to uninstall the service, it prints the
59 | // error in the standard output stream for users to diagnose the problem.
60 | //
61 | void UninstallService(PWSTR pszServiceName);
--------------------------------------------------------------------------------
/src/Services/ThreadPool.h:
--------------------------------------------------------------------------------
1 | /****************************** Module Header ******************************\
2 | * Module Name: ThreadPool.h
3 | * Project: CppWindowsService
4 | * Copyright (c) Microsoft Corporation.
5 | *
6 | * The class was designed by Kenny Kerr. It provides the ability to queue
7 | * simple member functions of a class to the Windows thread pool.
8 | *
9 | * Using the thread pool is simple and feels natural in C++.
10 | *
11 | * class CSampleService
12 | * {
13 | * public:
14 | *
15 | * void AsyncRun()
16 | * {
17 | * CThreadPool::QueueUserWorkItem(&Service::Run, this);
18 | * }
19 | *
20 | * void Run()
21 | * {
22 | * // Some lengthy operation
23 | * }
24 | * };
25 | *
26 | * Kenny Kerr spends most of his time designing and building distributed
27 | * applications for the Microsoft Windows platform. He also has a particular
28 | * passion for C++ and security programming. Reach Kenny at
29 | * http://weblogs.asp.net/kennykerr/ or visit his Web site:
30 | * http://www.kennyandkarin.com/Kenny/.
31 | *
32 | * This source is subject to the Microsoft Public License.
33 | * See http://www.microsoft.com/en-us/openness/resources/licenses.aspx#MPL.
34 | * All other rights reserved.
35 | *
36 | * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
37 | * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
38 | * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
39 | \***************************************************************************/
40 |
41 | #pragma once
42 |
43 | #include
44 |
45 |
46 | class CThreadPool
47 | {
48 | public:
49 |
50 | template
51 | static void QueueUserWorkItem(void (T::*function)(void),
52 | T *object, ULONG flags = WT_EXECUTELONGFUNCTION)
53 | {
54 | typedef std::pair CallbackType;
55 | std::auto_ptr p(new CallbackType(function, object));
56 |
57 | if (::QueueUserWorkItem(ThreadProc, p.get(), flags))
58 | {
59 | // The ThreadProc now has the responsibility of deleting the pair.
60 | p.release();
61 | }
62 | else
63 | {
64 | throw GetLastError();
65 | }
66 | }
67 |
68 | private:
69 |
70 | template
71 | static DWORD WINAPI ThreadProc(PVOID context)
72 | {
73 | typedef std::pair CallbackType;
74 |
75 | std::auto_ptr p(static_cast(context));
76 |
77 | (p->second->*p->first)();
78 | return 0;
79 | }
80 | };
--------------------------------------------------------------------------------
/src/SparseFiles.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 | #include "SparseFiles.h"
3 | #include
4 |
5 |
6 | CSparseFiles::CSparseFiles()
7 | {
8 |
9 | }
10 |
11 | CSparseFiles::~CSparseFiles()
12 | {
13 |
14 | }
15 |
16 |
17 | /*!
18 | * VolumeSupportsSparseFiles determines if the volume supports sparse streams.
19 | *
20 | * \param lpRootPathName
21 | * Volume root path e.g. C:\
22 | */
23 | BOOL CSparseFiles::VolumeSupportsSparseFiles(LPCTSTR lpRootPathName)
24 | {
25 | DWORD dwVolFlags;
26 | GetVolumeInformation(lpRootPathName, NULL, MAX_PATH, NULL, NULL,
27 | &dwVolFlags, NULL, MAX_PATH);
28 |
29 | return (dwVolFlags & FILE_SUPPORTS_SPARSE_FILES) ? TRUE : FALSE;
30 | }
31 |
32 |
33 | /*!
34 | * IsSparseFile determines if a file is sparse.
35 | *
36 | * \param lpFileName
37 | * File name
38 | */
39 | BOOL CSparseFiles::IsSparseFile(LPCTSTR lpFileName)
40 | {
41 | // Open the file for read
42 | HANDLE hFile = CreateFile(lpFileName, GENERIC_READ, 0, NULL,
43 | OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
44 | if (hFile == INVALID_HANDLE_VALUE)
45 | return FALSE;
46 |
47 | // Get file information
48 | BY_HANDLE_FILE_INFORMATION bhfi;
49 | GetFileInformationByHandle(hFile, &bhfi);
50 | CloseHandle(hFile);
51 |
52 | return (bhfi.dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) ? TRUE : FALSE;
53 | }
54 |
55 |
56 | /*!
57 | * Get sparse file sizes.
58 | *
59 | * \param lpFileName
60 | * File name
61 | *
62 | * \see
63 | * http://msdn.microsoft.com/en-us/library/aa365276.aspx
64 | */
65 | BOOL CSparseFiles::GetSparseFileSize(LPCTSTR lpFileName)
66 | {
67 | // Retrieves the size of the specified file, in bytes. The size includes
68 | // both allocated ranges and sparse ranges.
69 | HANDLE hFile = CreateFile(lpFileName, GENERIC_READ, 0, NULL,
70 | OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
71 | if (hFile == INVALID_HANDLE_VALUE)
72 | return FALSE;
73 | LARGE_INTEGER liSparseFileSize;
74 | GetFileSizeEx(hFile, &liSparseFileSize);
75 |
76 | // Retrieves the file's actual size on disk, in bytes. The size does not
77 | // include the sparse ranges.
78 | LARGE_INTEGER liSparseFileCompressedSize;
79 | liSparseFileCompressedSize.LowPart = GetCompressedFileSize(lpFileName,
80 | (LPDWORD)&liSparseFileCompressedSize.HighPart);
81 |
82 | // Print the result
83 | wprintf(L"\nFile total size: %I64uKB\nActual size on disk: %I64uKB\n",
84 | liSparseFileSize.QuadPart / 1024,
85 | liSparseFileCompressedSize.QuadPart / 1024);
86 |
87 | CloseHandle(hFile);
88 | return TRUE;
89 | }
90 |
91 |
92 | /*!
93 | * Create a sparse file.
94 | *
95 | * \param lpFileName
96 | * The name of the sparse file
97 | */
98 | HANDLE CSparseFiles::CreateSparseFile(LPCTSTR lpFileName)
99 | {
100 | // Create a normal file
101 | HANDLE hSparseFile = CreateFile(lpFileName, GENERIC_WRITE, 0, NULL,
102 | CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
103 |
104 | if (hSparseFile == INVALID_HANDLE_VALUE)
105 | return hSparseFile;
106 |
107 | // Use the DeviceIoControl function with the FSCTL_SET_SPARSE control
108 | // code to mark the file as sparse. If you don't mark the file as sparse,
109 | // the FSCTL_SET_ZERO_DATA control code will actually write zero bytes to
110 | // the file instead of marking the region as sparse zero area.
111 | DWORD dwTemp;
112 | DeviceIoControl(hSparseFile, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &dwTemp,
113 | NULL);
114 |
115 | return hSparseFile;
116 | }
117 |
118 |
119 | /*!
120 | * Converting a file region to A sparse zero area.
121 | *
122 | * \param hSparseFile
123 | * Handle of the sparse file
124 | *
125 | * \param start
126 | * Start address of the sparse zero area
127 | *
128 | * \param size
129 | * Size of the sparse zero block. The minimum sparse size is 64KB.
130 | *
131 | * \remarks
132 | * Note that SetSparseRange does not perform actual file I/O, and unlike the
133 | * WriteFile function, it does not move the current file I/O pointer or sets
134 | * the end-of-file pointer. That is, if you want to place a sparse zero block
135 | * in the end of the file, you must move the file pointer accordingly using
136 | * the FileStream.Seek function, otherwise DeviceIoControl will have no effect
137 | */
138 | void CSparseFiles::SetSparseRange(HANDLE hSparseFile, LONGLONG start, LONGLONG size)
139 | {
140 | // Specify the starting and the ending address (not the size) of the
141 | // sparse zero block
142 | FILE_ZERO_DATA_INFORMATION fzdi;
143 | fzdi.FileOffset.QuadPart = start;
144 | fzdi.BeyondFinalZero.QuadPart = start + size;
145 |
146 | // Mark the range as sparse zero block
147 | DWORD dwTemp;
148 | DeviceIoControl(hSparseFile, FSCTL_SET_ZERO_DATA, &fzdi, sizeof(fzdi),
149 | NULL, 0, &dwTemp, NULL);
150 | }
151 |
152 |
153 | /*!
154 | * Query the sparse file layout.
155 | *
156 | * \param lpFileName
157 | * File name
158 | */
159 | BOOL CSparseFiles::GetSparseRanges(LPCTSTR lpFileName)
160 | {
161 | // Open the file for read
162 | HANDLE hFile = CreateFile(lpFileName, GENERIC_READ, 0, NULL,
163 | OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
164 | if (hFile == INVALID_HANDLE_VALUE)
165 | return FALSE;
166 |
167 | LARGE_INTEGER liFileSize;
168 | GetFileSizeEx(hFile, &liFileSize);
169 |
170 | // Range to be examined (the whole file)
171 | FILE_ALLOCATED_RANGE_BUFFER queryRange;
172 | queryRange.FileOffset.QuadPart = 0;
173 | queryRange.Length = liFileSize;
174 |
175 | // Allocated areas info
176 | FILE_ALLOCATED_RANGE_BUFFER allocRanges[1024];
177 |
178 | DWORD nbytes;
179 | BOOL fFinished;
180 | _putws(L"\nAllocated ranges in the file:");
181 | do
182 | {
183 | fFinished = DeviceIoControl(hFile, FSCTL_QUERY_ALLOCATED_RANGES,
184 | &queryRange, sizeof(queryRange), allocRanges,
185 | sizeof(allocRanges), &nbytes, NULL);
186 |
187 | if (!fFinished)
188 | {
189 | DWORD dwError = GetLastError();
190 |
191 | // ERROR_MORE_DATA is the only error that is normal
192 | if (dwError != ERROR_MORE_DATA)
193 | {
194 | wprintf(L"DeviceIoControl failed w/err 0x%08lx\n", dwError);
195 | CloseHandle(hFile);
196 | return FALSE;
197 | }
198 | }
199 |
200 | // Calculate the number of records returned
201 | DWORD dwAllocRangeCount = nbytes /
202 | sizeof(FILE_ALLOCATED_RANGE_BUFFER);
203 |
204 | // Print each allocated range
205 | for (DWORD i = 0; i < dwAllocRangeCount; i++)
206 | {
207 | _tprintf_s(L"allocated range: [%I64u] [%I64u]\n",
208 | allocRanges[i].FileOffset.QuadPart,
209 | allocRanges[i].Length.QuadPart);
210 | }
211 |
212 | // Set starting address and size for the next query
213 | if (!fFinished && dwAllocRangeCount > 0)
214 | {
215 | queryRange.FileOffset.QuadPart =
216 | allocRanges[dwAllocRangeCount - 1].FileOffset.QuadPart +
217 | allocRanges[dwAllocRangeCount - 1].Length.QuadPart;
218 |
219 | queryRange.Length.QuadPart = liFileSize.QuadPart -
220 | queryRange.FileOffset.QuadPart;
221 | }
222 |
223 | } while (!fFinished);
224 |
225 | CloseHandle(hFile);
226 | return TRUE;
227 | }
228 |
--------------------------------------------------------------------------------
/src/SparseFiles.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 |
4 | class CSparseFiles
5 | {
6 | public:
7 | CSparseFiles();
8 | virtual ~CSparseFiles();
9 | static BOOL VolumeSupportsSparseFiles(LPCTSTR lpRootPathName);
10 | static BOOL IsSparseFile(LPCTSTR lpFileName);
11 | static BOOL GetSparseFileSize(LPCTSTR lpFileName);
12 | static HANDLE CreateSparseFile(LPCTSTR lpFileName);
13 | static void SetSparseRange(HANDLE hSparseFile, LONGLONG start, LONGLONG size);
14 | static BOOL GetSparseRanges(LPCTSTR lpFileName);
15 | };
--------------------------------------------------------------------------------
/src/ThreadImpl.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 | #include "ThreadImpl.h"
3 | #include
4 |
5 | namespace CODELIB
6 | {
7 | CThreadImpl::CThreadImpl(): m_hThread(NULL), m_hStopEvent(NULL)
8 | {
9 | m_hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
10 | }
11 |
12 | CThreadImpl::~CThreadImpl()
13 | {
14 | Stop();
15 |
16 | if(NULL != m_hStopEvent)
17 | CloseHandle(m_hStopEvent);
18 | }
19 |
20 | BOOL CThreadImpl::Start()
21 | {
22 | assert(NULL == m_hThread);
23 |
24 | if(NULL == m_hStopEvent)
25 | return FALSE;
26 |
27 | ResetEvent(m_hStopEvent);
28 | DWORD dwThreadId;
29 | m_hThread = CreateThread(NULL, 0, RunThreadFunc, this, 0, &dwThreadId);
30 | return (NULL != m_hThread);
31 | }
32 |
33 | BOOL CThreadImpl::Stop()
34 | {
35 | if(NULL == m_hThread)
36 | return TRUE;
37 |
38 | if(NULL != m_hStopEvent && NULL != m_hThread)
39 | {
40 | SetEvent(m_hStopEvent);
41 | DWORD exit_code;
42 |
43 | if(GetExitCodeThread(m_hThread, &exit_code) && exit_code == STILL_ACTIVE)
44 | WaitForSingleObject(m_hThread, INFINITE);
45 |
46 | CloseHandle(m_hThread);
47 | m_hThread = NULL;
48 | }
49 |
50 | return TRUE;
51 | }
52 |
53 | BOOL CThreadImpl::Run()
54 | {
55 | return TRUE;
56 | }
57 |
58 | DWORD WINAPI CThreadImpl::RunThreadFunc(LPVOID lpParam)
59 | {
60 | CThreadImpl* pThis = (CThreadImpl*)lpParam;
61 |
62 | if(NULL == pThis)
63 | return -1;
64 |
65 | pThis->Run();
66 | return 0;
67 | }
68 |
69 | }
--------------------------------------------------------------------------------
/src/ThreadImpl.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "IThread.h"
3 |
4 | namespace CODELIB
5 | {
6 | class CThreadImpl : public IThread
7 | {
8 | public:
9 | CThreadImpl();
10 | virtual ~CThreadImpl();
11 |
12 | BOOL Start();
13 |
14 | BOOL Stop();
15 |
16 | BOOL Run();
17 | protected:
18 | static DWORD WINAPI RunThreadFunc(LPVOID lpParam);
19 | private:
20 | HANDLE m_hStopEvent;
21 | HANDLE m_hThread;
22 | };
23 | }
--------------------------------------------------------------------------------
/src/ThreadWithFunc.cpp:
--------------------------------------------------------------------------------
1 | #include "stdafx.h"
2 | #include "ThreadWithFunc.h"
3 |
4 | namespace CODELIB
5 | {
6 | CThread::CThread( THREAD_FUNC threadFunc,LPVOID lpParam ):m_hThread(NULL)
7 | ,m_threadFunc(threadFunc)
8 | ,m_lpParam(lpParam)
9 | {
10 | m_hThread=::CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)_ThreadFunc,this,0,NULL);
11 | }
12 |
13 | CThread::~CThread()
14 | {
15 | WaitForSingleObject(m_hThread,INFINITE);
16 | }
17 |
18 | DWORD __stdcall CThread::_ThreadFunc( LPVOID lpParam )
19 | {
20 | CThread* pThis=static_cast(lpParam);
21 | if (NULL==pThis) return -1;
22 |
23 | if (NULL!=pThis->m_threadFunc)
24 | return pThis->m_threadFunc(pThis->m_lpParam);
25 |
26 | return 0;
27 | }
28 |
29 | }
--------------------------------------------------------------------------------
/src/ThreadWithFunc.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 |
4 | namespace CODELIB
5 | {
6 | typedef DWORD (*THREAD_FUNC)(LPVOID);
7 | class CThread
8 | {
9 | public:
10 | CThread(THREAD_FUNC threadFunc,LPVOID lpParam);
11 | virtual ~CThread();
12 | protected:
13 | static DWORD __stdcall _ThreadFunc(LPVOID lpParam);
14 | private:
15 | THREAD_FUNC m_threadFunc;
16 | LPVOID m_lpParam;
17 | HANDLE m_hThread;
18 | };
19 |
20 | }
--------------------------------------------------------------------------------
/stdafx.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wyrover/CodeLib/cee0615b2cba6d1281b93177aea7a64c4a39e1de/stdafx.cpp
--------------------------------------------------------------------------------
/stdafx.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wyrover/CodeLib/cee0615b2cba6d1281b93177aea7a64c4a39e1de/stdafx.h
--------------------------------------------------------------------------------
/targetver.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wyrover/CodeLib/cee0615b2cba6d1281b93177aea7a64c4a39e1de/targetver.h
--------------------------------------------------------------------------------