├── .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 --------------------------------------------------------------------------------