├── .gitignore ├── Makefile ├── build ├── ifslsp │ ├── ifslsp.vcxproj │ └── ifslsp.vcxproj.filters ├── instlsp │ ├── instlsp.vcxproj │ └── instlsp.vcxproj.filters └── nonifslsp │ ├── nonifslsp.vcxproj │ └── nonifslsp.vcxproj.filters ├── common ├── lspcommon.h ├── makefile └── provider.cpp ├── ifslsp ├── Makefile ├── extension.cpp ├── ifslsp.def ├── lspdef.h ├── lspguid.cpp ├── sockinfo.cpp └── spi.cpp ├── install ├── instlsp.cpp ├── instlsp.h ├── instlsp.rc ├── lspadd.cpp ├── lspdel.cpp ├── lspmap.cpp ├── lsputil.cpp ├── makefile └── prnpinfo.cpp ├── lsp.sln ├── nonifslsp ├── Makefile ├── asyncselect.cpp ├── extension.cpp ├── lspdef.h ├── lspguid.cpp ├── nonifslsp.def ├── overlap.cpp ├── sockinfo.cpp └── spi.cpp └── readme.txt /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Aa][Rr][Mm]/ 27 | [Aa][Rr][Mm]64/ 28 | bld/ 29 | [Bb]in/ 30 | [Oo]bj/ 31 | [Ll]og/ 32 | 33 | # Visual Studio 2015/2017 cache/options directory 34 | .vs/ 35 | # Uncomment if you have tasks that create the project's static files in wwwroot 36 | #wwwroot/ 37 | 38 | # Visual Studio 2017 auto generated files 39 | Generated\ Files/ 40 | 41 | # MSTest test Results 42 | [Tt]est[Rr]esult*/ 43 | [Bb]uild[Ll]og.* 44 | 45 | # NUnit 46 | *.VisualState.xml 47 | TestResult.xml 48 | nunit-*.xml 49 | 50 | # Build Results of an ATL Project 51 | [Dd]ebugPS/ 52 | [Rr]eleasePS/ 53 | dlldata.c 54 | 55 | # Benchmark Results 56 | BenchmarkDotNet.Artifacts/ 57 | 58 | # .NET Core 59 | project.lock.json 60 | project.fragment.lock.json 61 | artifacts/ 62 | 63 | # StyleCop 64 | StyleCopReport.xml 65 | 66 | # Files built by Visual Studio 67 | *_i.c 68 | *_p.c 69 | *_h.h 70 | *.ilk 71 | *.meta 72 | *.obj 73 | *.iobj 74 | *.pch 75 | *.pdb 76 | *.ipdb 77 | *.pgc 78 | *.pgd 79 | *.rsp 80 | *.sbr 81 | *.tlb 82 | *.tli 83 | *.tlh 84 | *.tmp 85 | *.tmp_proj 86 | *_wpftmp.csproj 87 | *.log 88 | *.vspscc 89 | *.vssscc 90 | .builds 91 | *.pidb 92 | *.svclog 93 | *.scc 94 | 95 | # Chutzpah Test files 96 | _Chutzpah* 97 | 98 | # Visual C++ cache files 99 | ipch/ 100 | *.aps 101 | *.ncb 102 | *.opendb 103 | *.opensdf 104 | *.sdf 105 | *.cachefile 106 | *.VC.db 107 | *.VC.VC.opendb 108 | 109 | # Visual Studio profiler 110 | *.psess 111 | *.vsp 112 | *.vspx 113 | *.sap 114 | 115 | # Visual Studio Trace Files 116 | *.e2e 117 | 118 | # TFS 2012 Local Workspace 119 | $tf/ 120 | 121 | # Guidance Automation Toolkit 122 | *.gpState 123 | 124 | # ReSharper is a .NET coding add-in 125 | _ReSharper*/ 126 | *.[Rr]e[Ss]harper 127 | *.DotSettings.user 128 | 129 | # JustCode is a .NET coding add-in 130 | .JustCode 131 | 132 | # TeamCity is a build add-in 133 | _TeamCity* 134 | 135 | # DotCover is a Code Coverage Tool 136 | *.dotCover 137 | 138 | # AxoCover is a Code Coverage Tool 139 | .axoCover/* 140 | !.axoCover/settings.json 141 | 142 | # Visual Studio code coverage results 143 | *.coverage 144 | *.coveragexml 145 | 146 | # NCrunch 147 | _NCrunch_* 148 | .*crunch*.local.xml 149 | nCrunchTemp_* 150 | 151 | # MightyMoose 152 | *.mm.* 153 | AutoTest.Net/ 154 | 155 | # Web workbench (sass) 156 | .sass-cache/ 157 | 158 | # Installshield output folder 159 | [Ee]xpress/ 160 | 161 | # DocProject is a documentation generator add-in 162 | DocProject/buildhelp/ 163 | DocProject/Help/*.HxT 164 | DocProject/Help/*.HxC 165 | DocProject/Help/*.hhc 166 | DocProject/Help/*.hhk 167 | DocProject/Help/*.hhp 168 | DocProject/Help/Html2 169 | DocProject/Help/html 170 | 171 | # Click-Once directory 172 | publish/ 173 | 174 | # Publish Web Output 175 | *.[Pp]ublish.xml 176 | *.azurePubxml 177 | # Note: Comment the next line if you want to checkin your web deploy settings, 178 | # but database connection strings (with potential passwords) will be unencrypted 179 | *.pubxml 180 | *.publishproj 181 | 182 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 183 | # checkin your Azure Web App publish settings, but sensitive information contained 184 | # in these scripts will be unencrypted 185 | PublishScripts/ 186 | 187 | # NuGet Packages 188 | *.nupkg 189 | # NuGet Symbol Packages 190 | *.snupkg 191 | # The packages folder can be ignored because of Package Restore 192 | **/[Pp]ackages/* 193 | # except build/, which is used as an MSBuild target. 194 | !**/[Pp]ackages/build/ 195 | # Uncomment if necessary however generally it will be regenerated when needed 196 | #!**/[Pp]ackages/repositories.config 197 | # NuGet v3's project.json files produces more ignorable files 198 | *.nuget.props 199 | *.nuget.targets 200 | 201 | # Microsoft Azure Build Output 202 | csx/ 203 | *.build.csdef 204 | 205 | # Microsoft Azure Emulator 206 | ecf/ 207 | rcf/ 208 | 209 | # Windows Store app package directories and files 210 | AppPackages/ 211 | BundleArtifacts/ 212 | Package.StoreAssociation.xml 213 | _pkginfo.txt 214 | *.appx 215 | *.appxbundle 216 | *.appxupload 217 | 218 | # Visual Studio cache files 219 | # files ending in .cache can be ignored 220 | *.[Cc]ache 221 | # but keep track of directories ending in .cache 222 | !?*.[Cc]ache/ 223 | 224 | # Others 225 | ClientBin/ 226 | ~$* 227 | *~ 228 | *.dbmdl 229 | *.dbproj.schemaview 230 | *.jfm 231 | *.pfx 232 | *.publishsettings 233 | orleans.codegen.cs 234 | 235 | # Including strong name files can present a security risk 236 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 237 | #*.snk 238 | 239 | # Since there are multiple workflows, uncomment next line to ignore bower_components 240 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 241 | #bower_components/ 242 | 243 | # RIA/Silverlight projects 244 | Generated_Code/ 245 | 246 | # Backup & report files from converting an old project file 247 | # to a newer Visual Studio version. Backup files are not needed, 248 | # because we have git ;-) 249 | _UpgradeReport_Files/ 250 | Backup*/ 251 | UpgradeLog*.XML 252 | UpgradeLog*.htm 253 | ServiceFabricBackup/ 254 | *.rptproj.bak 255 | 256 | # SQL Server files 257 | *.mdf 258 | *.ldf 259 | *.ndf 260 | 261 | # Business Intelligence projects 262 | *.rdl.data 263 | *.bim.layout 264 | *.bim_*.settings 265 | *.rptproj.rsuser 266 | *- [Bb]ackup.rdl 267 | *- [Bb]ackup ([0-9]).rdl 268 | *- [Bb]ackup ([0-9][0-9]).rdl 269 | 270 | # Microsoft Fakes 271 | FakesAssemblies/ 272 | 273 | # GhostDoc plugin setting file 274 | *.GhostDoc.xml 275 | 276 | # Node.js Tools for Visual Studio 277 | .ntvs_analysis.dat 278 | node_modules/ 279 | 280 | # Visual Studio 6 build log 281 | *.plg 282 | 283 | # Visual Studio 6 workspace options file 284 | *.opt 285 | 286 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 287 | *.vbw 288 | 289 | # Visual Studio LightSwitch build output 290 | **/*.HTMLClient/GeneratedArtifacts 291 | **/*.DesktopClient/GeneratedArtifacts 292 | **/*.DesktopClient/ModelManifest.xml 293 | **/*.Server/GeneratedArtifacts 294 | **/*.Server/ModelManifest.xml 295 | _Pvt_Extensions 296 | 297 | # Paket dependency manager 298 | .paket/paket.exe 299 | paket-files/ 300 | 301 | # FAKE - F# Make 302 | .fake/ 303 | 304 | # CodeRush personal settings 305 | .cr/personal 306 | 307 | # Python Tools for Visual Studio (PTVS) 308 | __pycache__/ 309 | *.pyc 310 | 311 | # Cake - Uncomment if you are using it 312 | # tools/** 313 | # !tools/packages.config 314 | 315 | # Tabs Studio 316 | *.tss 317 | 318 | # Telerik's JustMock configuration file 319 | *.jmconfig 320 | 321 | # BizTalk build output 322 | *.btp.cs 323 | *.btm.cs 324 | *.odx.cs 325 | *.xsd.cs 326 | 327 | # OpenCover UI analysis results 328 | OpenCover/ 329 | 330 | # Azure Stream Analytics local run output 331 | ASALocalRun/ 332 | 333 | # MSBuild Binary and Structured Log 334 | *.binlog 335 | 336 | # NVidia Nsight GPU debugger configuration file 337 | *.nvuser 338 | 339 | # MFractors (Xamarin productivity tool) working folder 340 | .mfractor/ 341 | 342 | # Local History for Visual Studio 343 | .localhistory/ 344 | 345 | # BeatPulse healthcheck temp database 346 | healthchecksdb 347 | 348 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 349 | MigrationBackup/ 350 | 351 | # Ionide (cross platform F# VS Code tools) working folder 352 | .ionide/ 353 | 354 | build_temp/ 355 | bin/ -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | DIRS = \ 2 | Common\~ \ 3 | Install\~ \ 4 | IfsLsp\~ \ 5 | NonIfsLsp\~ \ 6 | 7 | 8 | SDKPROJ =NetDS\Winsock\LSP 9 | 10 | 11 | # 12 | # This is a Platform SDK non-leaf-node makefile. It is used to allow NMAKE, 13 | # or a similar tool, to recursively build all of the samples in a directory 14 | # tree. To add or remove a directory from the build process, modify the 15 | # DIRS list above. 16 | # 17 | # The SDKPROJ macro (above) is defined solely for the purpose of echoing 18 | # the current directory location to the screen. 19 | # 20 | # Do not modify this makefile except for the DIRS and SDKPROJ macros above. 21 | # 22 | 23 | # 24 | # Include sdkpropbld.mak in order to get standard build options, environment 25 | # variables, and macros. The sdkpropbld.mak file is installed with the SDK 26 | # in the include directory. 27 | # 28 | 29 | !include 30 | 31 | # 32 | # In order to build "all," process each of the entries in the DIRS list. 33 | # 34 | 35 | all: $(DIRS) 36 | 37 | # 38 | # In order to build each of the entries in the DIRS list, change dir into the 39 | # directory in question, echo the current location, run nmake recursively, 40 | # and change dir back to the original directory level. This four step process 41 | # is encapsulated in sdkbld.mak which is installed with the SDK in the include 42 | # directory. 43 | # 44 | 45 | clean: 46 | del /s *.obj *.lib *.exp *.dll *.exe 47 | 48 | $(DIRS): 49 | !include 50 | -------------------------------------------------------------------------------- /build/ifslsp/ifslsp.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 15.0 37 | {7D5C6F64-B1B2-43E5-BA31-5CF5B1A8CFD8} 38 | Win32Proj 39 | ifslsp 40 | 10.0.17763.0 41 | 42 | 43 | 44 | DynamicLibrary 45 | true 46 | v141_xp 47 | MultiByte 48 | 49 | 50 | DynamicLibrary 51 | false 52 | v141_xp 53 | true 54 | MultiByte 55 | 56 | 57 | DynamicLibrary 58 | true 59 | v141 60 | Unicode 61 | 62 | 63 | DynamicLibrary 64 | false 65 | v141 66 | true 67 | Unicode 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | true 89 | 90 | 91 | true 92 | 93 | 94 | false 95 | 96 | 97 | false 98 | 99 | 100 | 101 | NotUsing 102 | Level3 103 | Disabled 104 | true 105 | _PSDK_BLD;_WINSOCK_DEPRECATED_NO_WARNINGS;WIN32;_DEBUG;IFSLSP_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 106 | false 107 | 108 | 109 | Windows 110 | true 111 | ws2_32.lib;ole32.lib;rpcrt4.lib;%(AdditionalDependencies) 112 | 113 | 114 | 115 | 116 | Use 117 | Level3 118 | Disabled 119 | true 120 | _DEBUG;IFSLSP_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 121 | true 122 | 123 | 124 | Windows 125 | true 126 | 127 | 128 | 129 | 130 | NotUsing 131 | Level3 132 | MaxSpeed 133 | true 134 | true 135 | true 136 | _PSDK_BLD;_WINSOCK_DEPRECATED_NO_WARNINGS;WIN32;NDEBUG;IFSLSP_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 137 | false 138 | 139 | 140 | Windows 141 | true 142 | true 143 | true 144 | ws2_32.lib;ole32.lib;rpcrt4.lib;%(AdditionalDependencies) 145 | 146 | 147 | 148 | 149 | Use 150 | Level3 151 | MaxSpeed 152 | true 153 | true 154 | true 155 | NDEBUG;IFSLSP_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 156 | true 157 | 158 | 159 | Windows 160 | true 161 | true 162 | true 163 | 164 | 165 | 166 | 167 | 168 | -------------------------------------------------------------------------------- /build/ifslsp/ifslsp.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;hh;hpp;hxx;hm;inl;inc;ipp;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 | {087c7b07-b5d1-4da5-990c-d66018afc9bc} 18 | 19 | 20 | 21 | 22 | 源文件 23 | 24 | 25 | 源文件 26 | 27 | 28 | 源文件 29 | 30 | 31 | 源文件 32 | 33 | 34 | 源文件\common 35 | 36 | 37 | 38 | 39 | 源文件 40 | 41 | 42 | 43 | 44 | 45 | 头文件 46 | 47 | 48 | -------------------------------------------------------------------------------- /build/instlsp/instlsp.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 15.0 38 | {42AAC990-4ACE-42AF-98B3-8B525F5AACF4} 39 | Win32Proj 40 | instlsp 41 | 7.0 42 | 43 | 44 | 45 | Application 46 | true 47 | v141_xp 48 | MultiByte 49 | 50 | 51 | Application 52 | false 53 | v141_xp 54 | true 55 | MultiByte 56 | 57 | 58 | Application 59 | true 60 | v141_xp 61 | MultiByte 62 | 63 | 64 | Application 65 | false 66 | v141_xp 67 | true 68 | MultiByte 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | true 90 | 91 | 92 | true 93 | 94 | 95 | false 96 | 97 | 98 | false 99 | 100 | 101 | 102 | Level3 103 | Disabled 104 | true 105 | _PSDK_BLD;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 106 | ../../common 107 | false 108 | 109 | 110 | Console 111 | true 112 | ws2_32.lib;ole32.lib;rpcrt4.lib;%(AdditionalDependencies) 113 | 114 | 115 | 116 | 117 | 118 | 119 | Level3 120 | Disabled 121 | true 122 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 123 | ../../common 124 | 125 | 126 | Console 127 | true 128 | ws2_32.lib;ole32.lib;rpcrt4.lib;%(AdditionalDependencies) 129 | 130 | 131 | 132 | 133 | Level3 134 | MaxSpeed 135 | true 136 | true 137 | true 138 | _PSDK_BLD;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 139 | ../../common 140 | false 141 | 142 | 143 | Console 144 | true 145 | true 146 | true 147 | ws2_32.lib;ole32.lib;rpcrt4.lib;%(AdditionalDependencies) 148 | 149 | 150 | 151 | 152 | 153 | 154 | Level3 155 | MaxSpeed 156 | true 157 | true 158 | true 159 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 160 | ../../common 161 | 162 | 163 | Console 164 | true 165 | true 166 | true 167 | ws2_32.lib;ole32.lib;rpcrt4.lib;%(AdditionalDependencies) 168 | 169 | 170 | 171 | 172 | 173 | -------------------------------------------------------------------------------- /build/instlsp/instlsp.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;hh;hpp;hxx;hm;inl;inc;ipp;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 | {b3f6ff48-a897-4cfe-8191-3b481f2bfa27} 18 | 19 | 20 | 21 | 22 | 源文件 23 | 24 | 25 | 源文件 26 | 27 | 28 | 源文件 29 | 30 | 31 | 源文件 32 | 33 | 34 | 源文件 35 | 36 | 37 | 源文件 38 | 39 | 40 | 源文件\common 41 | 42 | 43 | 44 | 45 | 头文件 46 | 47 | 48 | 49 | 50 | 资源文件 51 | 52 | 53 | -------------------------------------------------------------------------------- /build/nonifslsp/nonifslsp.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 15.0 23 | {DB604815-1A6D-4FA2-BD88-EE235D04375E} 24 | nonifslsp 25 | 7.0 26 | 27 | 28 | 29 | DynamicLibrary 30 | true 31 | v141_xp 32 | MultiByte 33 | 34 | 35 | DynamicLibrary 36 | false 37 | v141_xp 38 | true 39 | MultiByte 40 | 41 | 42 | Application 43 | true 44 | v141 45 | MultiByte 46 | 47 | 48 | Application 49 | false 50 | v141 51 | true 52 | MultiByte 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | Level3 76 | Disabled 77 | true 78 | ../../common 79 | _PSDK_BLD;_USING_V110_SDK71_;%(PreprocessorDefinitions) 80 | false 81 | 82 | 83 | ws2_32.lib;ole32.lib;rpcrt4.lib;%(AdditionalDependencies) 84 | Windows 85 | 86 | 87 | 88 | 89 | Level3 90 | Disabled 91 | true 92 | true 93 | 94 | 95 | 96 | 97 | Level3 98 | MaxSpeed 99 | true 100 | true 101 | true 102 | ../../common 103 | _PSDK_BLD;_USING_V110_SDK71_;%(PreprocessorDefinitions) 104 | false 105 | 106 | 107 | true 108 | true 109 | ws2_32.lib;ole32.lib;rpcrt4.lib;%(AdditionalDependencies) 110 | Windows 111 | 112 | 113 | 114 | 115 | Level3 116 | MaxSpeed 117 | true 118 | true 119 | true 120 | true 121 | 122 | 123 | true 124 | true 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /build/nonifslsp/nonifslsp.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;hh;hpp;hxx;hm;inl;inc;ipp;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 | {35183c35-1f8f-46d8-9e9f-6421628512d6} 18 | 19 | 20 | 21 | 22 | 源文件 23 | 24 | 25 | 源文件 26 | 27 | 28 | 源文件 29 | 30 | 31 | 源文件 32 | 33 | 34 | 源文件 35 | 36 | 37 | 源文件 38 | 39 | 40 | 源文件\common 41 | 42 | 43 | 44 | 45 | 头文件 46 | 47 | 48 | 49 | 50 | 源文件 51 | 52 | 53 | -------------------------------------------------------------------------------- /common/lspcommon.h: -------------------------------------------------------------------------------- 1 | // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 2 | // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 3 | // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 4 | // PARTICULAR PURPOSE. 5 | // 6 | // Copyright (C) 2004 Microsoft Corporation. All Rights Reserved. 7 | // 8 | // Module Name: provider.h 9 | // 10 | // Description: 11 | // 12 | // This sample illustrates how to develop a layered service provider that is 13 | // capable of counting all bytes transmitted through a TCP/IP socket. 14 | // 15 | // This file contains all datatypes and function prototypes used 16 | // throughout this project. 17 | // 18 | #ifndef _INSTALL_H_ 19 | #define _INSTALL_H_ 20 | 21 | #include 22 | #include 23 | #include 24 | #define _WINSOCK_DEPRECATED_NO_WARNINGS 1 25 | 26 | // Name of the Winsock DDL which is needed by the installer to determine if 27 | // WSCUpdateProvider is available. 28 | #define WINSOCK_DLL "\\ws2_32.dll" 29 | 30 | //////////////////////////////////////////////////////////////////////////////// 31 | // 32 | // External defines from lspguid.cpp and provider.cpp 33 | // 34 | //////////////////////////////////////////////////////////////////////////////// 35 | 36 | // Private heap used for all allocations in LSP as well as install time 37 | extern HANDLE gLspHeap; 38 | 39 | // Global GUID under which the LSP dummy entry is installed under 40 | extern GUID gProviderGuid; 41 | 42 | // Critical section for printing debug info (to prevent intermingling of messages) 43 | extern CRITICAL_SECTION gDebugCritSec; 44 | 45 | // Function definition for the GetLspGuid export which returns an LSPs dummy provider GUID 46 | typedef 47 | void (*LPFN_GETLSPGUID) (GUID *lpGuid); 48 | 49 | // For 64-bit systems, we need to know which catalog to operate on 50 | typedef enum 51 | { 52 | LspCatalogBoth = 0, 53 | LspCatalog32Only, 54 | LspCatalog64Only 55 | } WINSOCK_CATALOG; 56 | 57 | // 58 | // Extended proc table containing all the Microsoft specific Winsock functions 59 | // 60 | typedef struct _EXT_WSPPROC_TABLE 61 | { 62 | LPFN_ACCEPTEX lpfnAcceptEx; 63 | LPFN_TRANSMITFILE lpfnTransmitFile; 64 | LPFN_GETACCEPTEXSOCKADDRS lpfnGetAcceptExSockaddrs; 65 | LPFN_TRANSMITPACKETS lpfnTransmitPackets; 66 | LPFN_CONNECTEX lpfnConnectEx; 67 | LPFN_DISCONNECTEX lpfnDisconnectEx; 68 | LPFN_WSARECVMSG lpfnWSARecvMsg; 69 | } EXT_WSPPROC_TABLE; 70 | 71 | // 72 | // Describes a single catalog entry over which this LSP is layered on. It keeps track 73 | // of the lower provider's dispatch table as well as a list of all the sockets 74 | // created from our provider 75 | // 76 | typedef struct _PROVIDER 77 | { 78 | WSAPROTOCOL_INFOW NextProvider, // Next provider in chain 79 | LayerProvider; // This layered provider 80 | WSPPROC_TABLE NextProcTable; // Proc table of next provider 81 | EXT_WSPPROC_TABLE NextProcTableExt; // Proc table of next provider's extension 82 | 83 | DWORD LspDummyId; 84 | 85 | WCHAR ProviderPathW[MAX_PATH], 86 | LibraryPathW[MAX_PATH]; 87 | INT ProviderPathLen; 88 | 89 | LPWSPSTARTUP fnWSPStartup; 90 | WSPDATA WinsockVersion; 91 | HMODULE Module; 92 | 93 | INT StartupCount; 94 | 95 | LIST_ENTRY SocketList; // List of socket objects belonging to LSP 96 | 97 | CRITICAL_SECTION ProviderCritSec; 98 | } PROVIDER, * LPPROVIDER; 99 | 100 | 101 | //////////////////////////////////////////////////////////////////////////////// 102 | // 103 | // Provider.cpp prototypes 104 | // 105 | //////////////////////////////////////////////////////////////////////////////// 106 | 107 | BOOL 108 | FindLspEntries( 109 | PROVIDER **lspProviders, 110 | int *lspProviderCount, 111 | int *lpErrno 112 | ); 113 | 114 | PROVIDER * 115 | FindMatchingLspEntryForProtocolInfo( 116 | WSAPROTOCOL_INFOW *inInfo, 117 | PROVIDER *lspProviders, 118 | int lspCount, 119 | BOOL fromStartup = FALSE 120 | ); 121 | 122 | // Initialize the given provider by calling its WSPStartup 123 | int 124 | InitializeProvider( 125 | PROVIDER *provider, 126 | WORD wVersion, 127 | WSAPROTOCOL_INFOW *lpProtocolInfo, 128 | WSPUPCALLTABLE UpCallTable, 129 | int *Error 130 | ); 131 | 132 | BOOL 133 | LoadProviderPath( 134 | PROVIDER *loadProvider, 135 | int *lpErrno 136 | ); 137 | 138 | // Verifies all the function pointers in the proc table are non-NULL 139 | int 140 | VerifyProcTable( 141 | LPWSPPROC_TABLE lpProcTable 142 | ); 143 | 144 | // Returns an array of protocol entries from the given Winsock catalog 145 | LPWSAPROTOCOL_INFOW 146 | EnumerateProviders( 147 | WINSOCK_CATALOG Catalog, 148 | LPINT TotalProtocols 149 | ); 150 | 151 | // Enumerates the given Winsock catalog into the already allocated buffer 152 | int 153 | EnumerateProvidersExisting( 154 | WINSOCK_CATALOG Catalog, 155 | WSAPROTOCOL_INFOW *ProtocolInfo, 156 | LPDWORD ProtocolInfoSize 157 | ); 158 | 159 | // Free the array of protocol entries returned from EnumerateProviders 160 | void 161 | FreeProviders( 162 | LPWSAPROTOCOL_INFOW ProtocolInfo 163 | ); 164 | 165 | // Prints a protocol entry to the console in a readable, formatted form 166 | void 167 | PrintProtocolInfo( 168 | WSAPROTOCOL_INFOW *ProtocolInfo 169 | ); 170 | 171 | // Allocates a buffer from the LSP private heap 172 | void * 173 | LspAlloc( 174 | SIZE_T size, 175 | int *lpErrno 176 | ); 177 | 178 | // Frees a buffer previously allocated by LspAlloc 179 | void 180 | LspFree( 181 | LPVOID buf 182 | ); 183 | 184 | // Creates the private heap used by the LSP and installer 185 | int 186 | LspCreateHeap( 187 | int *lpErrno 188 | ); 189 | 190 | // Destroys the private heap 191 | void 192 | LspDestroyHeap( 193 | ); 194 | 195 | 196 | #ifdef _PSDK_BLD 197 | 198 | /*++ 199 | 200 | LINK list: 201 | 202 | Definitions for a double link list. 203 | 204 | --*/ 205 | 206 | // 207 | // Calculate the address of the base of the structure given its type, and an 208 | // address of a field within the structure. 209 | // 210 | #ifndef CONTAINING_RECORD 211 | #define CONTAINING_RECORD(address, type, field) \ 212 | ((type *)((PCHAR)(address) - (ULONG_PTR)(&((type *)0)->field))) 213 | #endif 214 | 215 | 216 | #ifndef InitializeListHead 217 | // 218 | // VOID 219 | // InitializeListHead( 220 | // PLIST_ENTRY ListHead 221 | // ); 222 | // 223 | 224 | #define InitializeListHead(ListHead) (\ 225 | (ListHead)->Flink = (ListHead)->Blink = (ListHead)) 226 | 227 | // 228 | // BOOLEAN 229 | // IsListEmpty( 230 | // PLIST_ENTRY ListHead 231 | // ); 232 | // 233 | 234 | #define IsListEmpty(ListHead) \ 235 | ((ListHead)->Flink == (ListHead)) 236 | 237 | // 238 | // PLIST_ENTRY 239 | // RemoveHeadList( 240 | // PLIST_ENTRY ListHead 241 | // ); 242 | // 243 | 244 | #define RemoveHeadList(ListHead) \ 245 | (ListHead)->Flink;\ 246 | {RemoveEntryList((ListHead)->Flink)} 247 | 248 | // 249 | // PLIST_ENTRY 250 | // RemoveTailList( 251 | // PLIST_ENTRY ListHead 252 | // ); 253 | // 254 | 255 | #define RemoveTailList(ListHead) \ 256 | (ListHead)->Blink;\ 257 | {RemoveEntryList((ListHead)->Blink)} 258 | 259 | // 260 | // VOID 261 | // RemoveEntryList( 262 | // PLIST_ENTRY Entry 263 | // ); 264 | // 265 | 266 | #define RemoveEntryList(Entry) {\ 267 | PLIST_ENTRY _EX_Blink;\ 268 | PLIST_ENTRY _EX_Flink;\ 269 | _EX_Flink = (Entry)->Flink;\ 270 | _EX_Blink = (Entry)->Blink;\ 271 | _EX_Blink->Flink = _EX_Flink;\ 272 | _EX_Flink->Blink = _EX_Blink;\ 273 | } 274 | 275 | // 276 | // VOID 277 | // InsertTailList( 278 | // PLIST_ENTRY ListHead, 279 | // PLIST_ENTRY Entry 280 | // ); 281 | // 282 | 283 | #define InsertTailList(ListHead,Entry) {\ 284 | PLIST_ENTRY _EX_Blink;\ 285 | PLIST_ENTRY _EX_ListHead;\ 286 | _EX_ListHead = (ListHead);\ 287 | _EX_Blink = _EX_ListHead->Blink;\ 288 | (Entry)->Flink = _EX_ListHead;\ 289 | (Entry)->Blink = _EX_Blink;\ 290 | _EX_Blink->Flink = (Entry);\ 291 | _EX_ListHead->Blink = (Entry);\ 292 | } 293 | 294 | // 295 | // VOID 296 | // InsertHeadList( 297 | // PLIST_ENTRY ListHead, 298 | // PLIST_ENTRY Entry 299 | // ); 300 | // 301 | 302 | #define InsertHeadList(ListHead,Entry) {\ 303 | PLIST_ENTRY _EX_Flink;\ 304 | PLIST_ENTRY _EX_ListHead;\ 305 | _EX_ListHead = (ListHead);\ 306 | _EX_Flink = _EX_ListHead->Flink;\ 307 | (Entry)->Flink = _EX_Flink;\ 308 | (Entry)->Blink = _EX_ListHead;\ 309 | _EX_Flink->Blink = (Entry);\ 310 | _EX_ListHead->Flink = (Entry);\ 311 | } 312 | 313 | 314 | 315 | BOOL IsNodeOnList(PLIST_ENTRY ListHead, PLIST_ENTRY Entry); 316 | 317 | 318 | #endif //InitializeListHead 319 | 320 | 321 | #endif 322 | 323 | 324 | //////////////////////////////////////////////////////////////////////////////// 325 | // 326 | // Macro definitions 327 | // 328 | //////////////////////////////////////////////////////////////////////////////// 329 | 330 | #ifdef ASSERT 331 | #undef ASSERT 332 | #endif 333 | 334 | #ifdef DBG 335 | 336 | // Prints a message to the debugger 337 | void 338 | dbgprint( 339 | char *format, 340 | ... 341 | ); 342 | 343 | #define ASSERT(exp) \ 344 | if ( !(exp) ) \ 345 | dbgprint("\n*** Assertion failed: %s\n" \ 346 | "*** Source file: %s, line: %d\n\n", \ 347 | #exp,__FILE__,__LINE__), DebugBreak() 348 | #else 349 | 350 | // On free builds, define these to be empty 351 | #define ASSERT(exp) 352 | #define dbgprint 353 | 354 | #endif 355 | 356 | #endif 357 | -------------------------------------------------------------------------------- /common/makefile: -------------------------------------------------------------------------------- 1 | !include 2 | 3 | all: $(OUTDIR) $(OUTDIR)\lspcommon.lib 4 | 5 | $(OUTDIR): 6 | if not exist "$(OUTDIR)/$(NULL)" mkdir $(OUTDIR) 7 | 8 | #cflags= $(cflags) -D_PSDK_BLD 9 | 10 | LIB_OBJS= $(OUTDIR)\provider.obj 11 | 12 | LIBS= ws2_32.lib ole32.lib rpcrt4.lib $(baselibs) 13 | 14 | $(OUTDIR)\provider.obj: 15 | $(cc) provider.cpp $(cdebug) $(cflags) -DSTRICT -DFD_SETSIZE=1024 /GS /Fo$(OUTDIR)\provider.obj 16 | 17 | .cpp{$(OUTDIR)}.obj: 18 | $(cc) $(cdebug) $(cflags) -DSTRICT -DFD_SETSIZE=1024 /GS /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\" $** 19 | 20 | $(OUTDIR)\lspcommon.lib: $(LIB_OBJS) 21 | $(link) /lib $(libflags) -out:$*.lib $** 22 | Echo COMPILED LSPCOMMON.LIB 23 | 24 | clean: 25 | rmdir /s /q $(OUTDIR) 26 | -------------------------------------------------------------------------------- /ifslsp/Makefile: -------------------------------------------------------------------------------- 1 | !include 2 | 3 | all: $(OUTDIR) $(OUTDIR)\ifslsp.dll 4 | 5 | $(OUTDIR): 6 | if not exist "$(OUTDIR)/$(NULL)" mkdir $(OUTDIR) 7 | 8 | #cflags= $(cflags) -D_PSDK_BLD 9 | 10 | DLL_OBJS= $(OUTDIR)\spi.obj \ 11 | $(OUTDIR)\extension.obj \ 12 | $(OUTDIR)\sockinfo.obj \ 13 | $(OUTDIR)\lspguid.obj 14 | 15 | LIBS= ws2_32.lib ole32.lib rpcrt4.lib ..\common\$(OUTDIR)\lspcommon.lib $(baselibs) 16 | 17 | .cpp{$(OUTDIR)}.obj: 18 | $(cc) $(cdebug) $(cflags) -DSTRICT -DFD_SETSIZE=1024 /GS /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\" $** 19 | 20 | $(OUTDIR)\ifslsp.dll: $(DLL_OBJS) 21 | $(link) $(linkdebug) $(dlllflags) -def:ifslsp.def \ 22 | -out:$*.dll -pdb:$*.pdb $(guilibsdll) $** $(LIBS) 23 | if not exist "..\bin\$(OUTDIR)/$(NULL)" mkdir "..\bin\$(OUTDIR)/$(NULL)" 24 | copy $(OUTDIR)\ifslsp.dll ..\bin\$(OUTDIR) 25 | if exist $(OUTDIR)\ifslsp.pdb copy $(OUTDIR)\ifslsp.pdb ..\bin\$(OUTDIR) 26 | Echo COMPILED IFSLSP.DLL 27 | 28 | clean: 29 | rmdir /s /q $(OUTDIR) 30 | -------------------------------------------------------------------------------- /ifslsp/extension.cpp: -------------------------------------------------------------------------------- 1 | // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 2 | // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 3 | // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 4 | // PARTICULAR PURPOSE. 5 | // 6 | // Copyright (C) 2004 Microsoft Corporation. All Rights Reserved. 7 | // 8 | // Module Name: extension.cpp 9 | // 10 | // Description: 11 | // 12 | // This sample illustrates an IFS based LSP which implements basic proxying 13 | // capabilities. 14 | // 15 | // This file contains all of the Winsock extension functions that the LSP needs 16 | // to intercept in order to proxy connections. In terms of Winsock extension 17 | // functions this means only the ConnectEx function needs to be intercepted. 18 | // 19 | 20 | #include "lspdef.h" 21 | 22 | // 23 | // Function: LoadExtensionFunction 24 | // 25 | // Description: 26 | // This function dynamically loads the given extension function from the 27 | // underlying provider. Each extension function checks to see if the 28 | // corresponding extension function for the lower provider is loaded 29 | // before calling. If not, it will load it as needed. This is necessary 30 | // if the app loads the extension function for say TCP and then calls 31 | // that extension function on a UDP socket. Normally this isn't the case 32 | // but we're being defensive here. 33 | // 34 | BOOL 35 | LoadExtensionFunction( 36 | FARPROC **func, 37 | GUID ExtensionGuid, 38 | LPWSPIOCTL fnIoctl, 39 | SOCKET s 40 | ) 41 | { 42 | DWORD dwBytes; 43 | int rc, 44 | error; 45 | 46 | // Use the lower provider's WSPIoctl to load the extension function 47 | rc = fnIoctl( 48 | s, 49 | SIO_GET_EXTENSION_FUNCTION_POINTER, 50 | &ExtensionGuid, 51 | sizeof(GUID), 52 | func, 53 | sizeof(FARPROC), 54 | &dwBytes, 55 | NULL, 56 | NULL, 57 | NULL, 58 | &error 59 | ); 60 | if ( SOCKET_ERROR == rc ) 61 | { 62 | dbgprint("LoadExtensionFunction: WSAIoctl (SIO_GET_EXTENSION_FUNCTION) failed: %d", 63 | error); 64 | return FALSE; 65 | } 66 | else 67 | { 68 | return TRUE; 69 | } 70 | } 71 | 72 | // 73 | // Function: ExtConnectEx 74 | // 75 | // Description: 76 | // This is our provider's ConnectEx function. When an app calls WSAIoctl 77 | // to request the function pointer to ConnectEx, we intercept the call 78 | // and return a pointer to our extension function instead. This ConnectEx 79 | // implementation needs to perform the same proxying check that WSPConnect 80 | // does. 81 | // 82 | BOOL PASCAL FAR 83 | ExtConnectEx( 84 | IN SOCKET s, 85 | IN const struct sockaddr FAR *name, 86 | IN int namelen, 87 | IN PVOID lpSendBuffer OPTIONAL, 88 | IN DWORD dwSendDataLength, 89 | OUT LPDWORD lpdwBytesSent, 90 | IN LPOVERLAPPED lpOverlapped 91 | ) 92 | { 93 | SOCKET_CONTEXT *sockContext = NULL; 94 | SOCKADDR *proxyAddr = NULL; 95 | int Errno = NO_ERROR, 96 | proxyLen = 0, 97 | rc = FALSE; 98 | 99 | sockContext = FindSocketContext( s ); 100 | if ( NULL == sockContext ) 101 | { 102 | dbgprint("ExtConnectEx: FindSocketContext failed!"); 103 | Errno = WSAENOTSOCK; 104 | goto cleanup; 105 | } 106 | 107 | // Make sure we already have the extension function 108 | if ( NULL == sockContext->Provider->NextProcTableExt.lpfnConnectEx ) 109 | { 110 | GUID guidConnectEx = WSAID_CONNECTEX; 111 | 112 | rc = LoadExtensionFunction( 113 | (FARPROC **)&sockContext->Provider->NextProcTableExt.lpfnConnectEx, 114 | guidConnectEx, 115 | sockContext->Provider->NextProcTable.lpWSPIoctl, 116 | s 117 | ); 118 | if ( FALSE == rc ) 119 | { 120 | dbgprint("Next proc table ConnectEx == NULL!"); 121 | Errno = WSAEFAULT; 122 | goto cleanup; 123 | } 124 | } 125 | 126 | // See if the connect needs to be proxied 127 | FindDestinationAddress( sockContext, name, namelen, &proxyAddr, &proxyLen ); 128 | 129 | rc = sockContext->Provider->NextProcTableExt.lpfnConnectEx( 130 | s, 131 | proxyAddr, 132 | proxyLen, 133 | lpSendBuffer, 134 | dwSendDataLength, 135 | lpdwBytesSent, 136 | lpOverlapped 137 | ); 138 | 139 | cleanup: 140 | 141 | if ( NO_ERROR != Errno ) 142 | WSASetLastError( Errno ); 143 | 144 | return rc; 145 | } 146 | -------------------------------------------------------------------------------- /ifslsp/ifslsp.def: -------------------------------------------------------------------------------- 1 | LIBRARY ifslsp 2 | EXPORTS 3 | WSPStartup 4 | GetLspGuid 5 | -------------------------------------------------------------------------------- /ifslsp/lspdef.h: -------------------------------------------------------------------------------- 1 | // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 2 | // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 3 | // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 4 | // PARTICULAR PURPOSE. 5 | // 6 | // Copyright (C) 2004 Microsoft Corporation. All Rights Reserved. 7 | // 8 | // Module Name: provider.h 9 | // 10 | // Description: 11 | // 12 | // This sample illustrates how to develop a layered service provider that is 13 | // capable of counting all bytes transmitted through a TCP/IP socket. 14 | // 15 | // This file contains all datatypes and function prototypes used 16 | // throughout this project. 17 | // 18 | #ifndef _PROVIDER_H_ 19 | #define _PROVIDER_H_ 20 | 21 | #ifndef _PSDK_BLD 22 | #include 23 | #include 24 | #include 25 | #endif 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #ifndef _PSDK_BLD 33 | #include 34 | #else 35 | #include "..\common\lspcommon.h" 36 | #endif 37 | 38 | // 39 | // This is the socket context data that we associate with each socket 40 | // that is passed back to the user app. That way when another API 41 | // is called we can query for this context information and find out 42 | // the socket handle to the lower provider. 43 | // 44 | typedef struct _SOCKET_CONTEXT 45 | { 46 | SOCKET Socket; // Lower provider socket handle 47 | PROVIDER *Provider; // Pointer to the provider from which socket was created 48 | 49 | SOCKADDR_STORAGE ProxiedAddress; 50 | SOCKADDR_STORAGE OriginalAddress; 51 | 52 | int AddressLength; 53 | 54 | BOOL Proxied; 55 | 56 | LIST_ENTRY Link; 57 | 58 | } SOCKET_CONTEXT; 59 | 60 | //////////////////////////////////////////////////////////////////////////////// 61 | // 62 | // Spi.cpp prototypes 63 | // 64 | //////////////////////////////////////////////////////////////////////////////// 65 | 66 | // 67 | // These are the Winsock functions that this particular IFS LSP wishes to intercept. 68 | // In this case, the LSP is just acting as a TCP proxy so it is only interested in the 69 | // following functions. 70 | // 71 | 72 | void 73 | FreeLspProviders( 74 | PROVIDER *lspProvider, 75 | int lspProviderCount, 76 | int *lpErrno 77 | ); 78 | 79 | void 80 | FindDestinationAddress( 81 | SOCKET_CONTEXT *context, 82 | const SOCKADDR *destAddr, 83 | int destLen, 84 | SOCKADDR **proxyAddr, 85 | int *proxyLen 86 | ); 87 | 88 | 89 | int WSPAPI 90 | WSPCloseSocket( 91 | SOCKET s, 92 | LPINT lpErrno 93 | ); 94 | 95 | int WSPAPI 96 | WSPConnect( 97 | SOCKET s, 98 | const struct sockaddr FAR * name, 99 | int namelen, 100 | LPWSABUF lpCallerData, 101 | LPWSABUF lpCalleeData, 102 | LPQOS lpSQOS, 103 | LPQOS lpGQOS, 104 | LPINT lpErrno 105 | ); 106 | 107 | int WSPAPI 108 | WSPGetPeerName( 109 | SOCKET s, 110 | struct sockaddr FAR * name, 111 | LPINT namelen, 112 | LPINT lpErrno 113 | ); 114 | 115 | int WSPAPI 116 | WSPIoctl( 117 | SOCKET s, 118 | DWORD dwIoControlCode, 119 | LPVOID lpvInBuffer, 120 | DWORD cbInBuffer, 121 | LPVOID lpvOutBuffer, 122 | DWORD cbOutBuffer, 123 | LPDWORD lpcbBytesReturned, 124 | LPWSAOVERLAPPED lpOverlapped, 125 | LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, 126 | LPWSATHREADID lpThreadId, 127 | LPINT lpErrno 128 | ); 129 | 130 | SOCKET WSPAPI 131 | WSPSocket( 132 | int af, 133 | int type, 134 | int protocol, 135 | LPWSAPROTOCOL_INFOW lpProtocolInfo, 136 | GROUP g, 137 | DWORD dwFlags, 138 | LPINT lpErrno 139 | ); 140 | 141 | //////////////////////////////////////////////////////////////////////////////// 142 | // 143 | // Sockinfo.cpp prototypes 144 | // 145 | //////////////////////////////////////////////////////////////////////////////// 146 | 147 | // Looks up the SOCKET_CONTEXT structure belonging to the given socket handle 148 | SOCKET_CONTEXT * 149 | FindSocketContext( 150 | SOCKET s, 151 | BOOL Remove = FALSE 152 | ); 153 | 154 | // Allocates a SOCKET_CONTEXT structure, initializes it, and inserts into the provider list 155 | SOCKET_CONTEXT * 156 | CreateSocketContext( 157 | PROVIDER *Provider, 158 | SOCKET Socket, 159 | int *lpErrno 160 | ); 161 | 162 | // Frees a previously allocated SOCKET_CONTEXT structure 163 | void 164 | FreeSocketContext( 165 | PROVIDER *Provider, 166 | SOCKET_CONTEXT *Context 167 | ); 168 | 169 | // Frees all socket context strcutures belonging to the provider 170 | void 171 | FreeSocketContextList( 172 | PROVIDER *Provider 173 | ); 174 | 175 | //////////////////////////////////////////////////////////////////////////////// 176 | // 177 | // Extension.cpp prototypes 178 | // 179 | //////////////////////////////////////////////////////////////////////////////// 180 | 181 | BOOL PASCAL FAR 182 | ExtConnectEx( 183 | IN SOCKET s, 184 | IN const struct sockaddr FAR *name, 185 | IN int namelen, 186 | IN PVOID lpSendBuffer OPTIONAL, 187 | IN DWORD dwSendDataLength, 188 | OUT LPDWORD lpdwBytesSent, 189 | IN LPOVERLAPPED lpOverlapped 190 | ); 191 | 192 | //////////////////////////////////////////////////////////////////////////////// 193 | // 194 | // External variable definitions 195 | // 196 | //////////////////////////////////////////////////////////////////////////////// 197 | 198 | extern CRITICAL_SECTION gCriticalSection; // Critical section for initialization and 199 | extern INT gLayerCount; // Number of layered protocol entries for LSP 200 | extern PROVIDER *gLayerInfo; // Provider structures for each layered protocol 201 | extern WSPUPCALLTABLE gMainUpCallTable; // Upcall functions given to us by Winsock 202 | extern GUID gProviderGuid; // GUID of our dummy hidden entry 203 | 204 | #endif 205 | -------------------------------------------------------------------------------- /ifslsp/lspguid.cpp: -------------------------------------------------------------------------------- 1 | // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 2 | // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 3 | // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 4 | // PARTICULAR PURPOSE. 5 | // 6 | // Copyright (C) 2004 Microsoft Corporation. All Rights Reserved. 7 | // 8 | // Module Name: lspguid.cpp 9 | // 10 | // Description: 11 | // 12 | // This module defines the GUID under which the LSP's hidden dummy 13 | // entry is to be installed under. This GUID must be hard coded in 14 | // this file so that the DLL instance can find itself in the Winsock 15 | // catalog. Once it finds the dummy hidden entry, it can then find 16 | // the layered protocol entries belonging to the LSP (since these 17 | // entries will reference the catalog ID of the hidden dummy entry). 18 | // 19 | // It is possible to create multiple LSPs by simply copying this project 20 | // to another directory, changing the GUID in this file, and changing 21 | // the DLL name. The LSP installer (instlsp.exe) can then install each 22 | // LSP with the -d flag which is the full path to each LSP to install. 23 | // 24 | // A new export has been added: GetLspGuid. This allows the LSP installer 25 | // to install an arbitrary LSP as long as it exports this function as the 26 | // installer needs to find the GUID to install the hidden dummy entry 27 | // with. The GUIDs for the layered protocol entries are generated on the 28 | // fly. 29 | // 30 | #include "lspdef.h" 31 | #include 32 | 33 | 34 | // 35 | // This is the hardcoded guid for our dummy (hidden) catalog entry 36 | // 37 | GUID gProviderGuid = { //f345d288-21e2-441d-a7d1-eb4c6e001e3d 38 | 0xf345d288, 39 | 0x21e2, 40 | 0x441d, 41 | {0xa7, 0xd1, 0xeb, 0x4c, 0x6e, 0x00, 0x1e, 0x3d} 42 | }; 43 | 44 | // 45 | // Function: GetLspGuid 46 | // 47 | // Description: 48 | // This function is exported by the DLL and it returns the GUID under 49 | // which the LSP (hidden) entry is to be installed. Note that this export 50 | // is not required to write an LSP but it is here to make the installer code 51 | // easier since the LSP DLL and the installer at least need to know the GUID 52 | // of the hidden dummy entry of the LSP. Using this export allows the installer 53 | // to query each LSP instance of its GUID so that it may install it. 54 | // 55 | void 56 | WSPAPI 57 | GetLspGuid( 58 | LPGUID lpGuid 59 | ) 60 | { 61 | memcpy( lpGuid, &gProviderGuid, sizeof( GUID ) ); 62 | } 63 | -------------------------------------------------------------------------------- /ifslsp/sockinfo.cpp: -------------------------------------------------------------------------------- 1 | // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 2 | // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 3 | // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 4 | // PARTICULAR PURPOSE. 5 | // 6 | // Copyright (C) 2004 Microsoft Corporation. All Rights Reserved. 7 | // 8 | // Module Name: sockinfo.cpp 9 | // 10 | // Description: 11 | // 12 | // This sample illustrates an IFS based LSP which implements basic proxying 13 | // capabilities. 14 | // 15 | // This file contains routines associated with the SOCKET_CONTEXT structure. This 16 | // structure maintains the mapping between the upper layer's socket and the 17 | // corresponding lower layer's socket. The routines in this file are for allocating, 18 | // linked list management, etc. 19 | // 20 | 21 | #include "lspdef.h" 22 | 23 | // 24 | // Function: FindAndRefSocketContext 25 | // 26 | // Description: 27 | // This routine grabs the LSP critical seciton to lookup the socket context 28 | // and increase its ref count. Any operation on the socket context holds 29 | // the critical section so that it cannot be freed while its state changes. 30 | // 31 | SOCKET_CONTEXT * 32 | FindSocketContext( 33 | SOCKET s, 34 | BOOL Remove 35 | ) 36 | { 37 | SOCKET_CONTEXT *SocketContext = NULL, 38 | *info = NULL; 39 | LIST_ENTRY *lptr = NULL; 40 | int i; 41 | 42 | EnterCriticalSection( &gCriticalSection ); 43 | 44 | for(i=0; i < gLayerCount ;i++) 45 | { 46 | EnterCriticalSection( &gLayerInfo[ i ].ProviderCritSec ); 47 | 48 | for(lptr = gLayerInfo[ i ].SocketList.Flink ; 49 | lptr != &gLayerInfo[ i ].SocketList ; 50 | lptr = lptr->Flink ) 51 | { 52 | info = CONTAINING_RECORD( lptr, SOCKET_CONTEXT, Link ); 53 | 54 | if ( s == info->Socket ) 55 | { 56 | SocketContext = info; 57 | 58 | if ( TRUE == Remove ) 59 | { 60 | RemoveEntryList( &info->Link ); 61 | } 62 | break; 63 | } 64 | } 65 | 66 | LeaveCriticalSection( &gLayerInfo[ i ].ProviderCritSec ); 67 | 68 | if ( NULL != SocketContext ) 69 | break; 70 | } 71 | 72 | LeaveCriticalSection( &gCriticalSection ); 73 | 74 | return SocketContext; 75 | } 76 | 77 | // 78 | // Function: CreateSockInfo 79 | // 80 | // Description: 81 | // Allocates a new socket info context structure and initializes the fields 82 | // except for the LayeredSocket field. The context must be allocated first, 83 | // then the layered socket is created (with the SOCKET_CONTEXT structure as the 84 | // context information), and then the LayeredSocket field is set. If 85 | // the Inherit context is provided, information is copied to the new socket 86 | // context structure (such as with WSPAccept). If the Insert flag is TRUE 87 | // then the context is automatically inserted into the list of sockets 88 | // for the given provider. If not then the caller must insert the context 89 | // (WSPAccept does this to ensure all fields of the context are valid 90 | // including LayeredSocket before insertion so that the async thread 91 | // handler will work properly). 92 | // 93 | SOCKET_CONTEXT * 94 | CreateSocketContext( 95 | PROVIDER *Provider, 96 | SOCKET Socket, 97 | int *lpErrno 98 | ) 99 | { 100 | SOCKET_CONTEXT *newContext = NULL; 101 | 102 | newContext = (SOCKET_CONTEXT *) LspAlloc( 103 | sizeof( SOCKET_CONTEXT ), 104 | lpErrno 105 | ); 106 | if ( NULL == newContext ) 107 | { 108 | dbgprint("CreateSocketContext: LspAlloc failed: %d", *lpErrno ); 109 | goto cleanup; 110 | } 111 | 112 | newContext->Socket = Socket; 113 | newContext->Provider = Provider; 114 | newContext->Proxied = FALSE; 115 | 116 | EnterCriticalSection( &Provider->ProviderCritSec ); 117 | 118 | InsertHeadList( &Provider->SocketList, &newContext->Link ); 119 | 120 | LeaveCriticalSection( &Provider->ProviderCritSec ); 121 | 122 | return newContext; 123 | 124 | cleanup: 125 | 126 | return NULL; 127 | } 128 | 129 | // 130 | // Function: FreeSockInfo 131 | // 132 | // Description: 133 | // This routine frees the socket context structure. 134 | // 135 | void 136 | FreeSocketContext( 137 | PROVIDER *Provider, 138 | SOCKET_CONTEXT *Context 139 | ) 140 | { 141 | EnterCriticalSection( &Provider->ProviderCritSec ); 142 | 143 | RemoveEntryList( &Context->Link ); 144 | LspFree( Context ); 145 | 146 | LeaveCriticalSection( &Provider->ProviderCritSec ); 147 | 148 | return; 149 | } 150 | 151 | // 152 | // Function: CloseAndFreeSocketInfo 153 | // 154 | // Description: 155 | // Closes all sockets belonging to the specified provider and frees 156 | // the context information. If the lower provider socket is still 157 | // valid, set an abortive linger, and close the socket. 158 | // 159 | void 160 | FreeSocketContextList( 161 | PROVIDER *provider 162 | ) 163 | { 164 | LIST_ENTRY *lptr = NULL; 165 | SOCKET_CONTEXT *context = NULL; 166 | 167 | ASSERT( provider ); 168 | 169 | // Walk the list of sockets 170 | while ( !IsListEmpty( &provider->SocketList ) ) 171 | { 172 | lptr = RemoveHeadList( &provider->SocketList ); 173 | 174 | ASSERT( lptr ); 175 | 176 | context = CONTAINING_RECORD( lptr, SOCKET_CONTEXT, Link ); 177 | 178 | // Context is already removed so just free it 179 | LspFree( context ); 180 | } 181 | 182 | return; 183 | } 184 | -------------------------------------------------------------------------------- /install/instlsp.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 3 | // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 4 | // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 5 | // PARTICULAR PURPOSE. 6 | // 7 | // Copyright (C) 2004 Microsoft Corporation. All Rights Reserved. 8 | // 9 | // Module Name: instlsp.cpp 10 | // 11 | // Description: 12 | // 13 | // This sample illustrates how to develop a layered service provider. 14 | // This LSP is simply a pass through sample which counts the bytes transfered 15 | // on each socket. 16 | // 17 | // This file contains an installation program to insert the layered sample 18 | // into the Winsock catalog of providers. 19 | // 20 | // 21 | // Compile: 22 | // 23 | // Compile with the Makefile: 24 | // nmake /f Makefile 25 | // 26 | // Execute: 27 | // 28 | // This project produces a executable file instlsp.exe. The installation app 29 | // allows you to install the LSP over any provider. Note however that if you 30 | // choose to install over a single provider, you should install over all 31 | // providers of that address family (e.g. if you install over UDP, install 32 | // over TCP and RAW providers as well). The arguments are: 33 | // 34 | // -a Install over all providers 35 | // -c Catalog Indicates which catalog to operate on (for Win64) 36 | // -d Full path and filename of LSP dll 37 | // -f Remove all layered providers (last ditch recovery) 38 | // -i Install the LSP 39 | // -l Print the layered entries only 40 | // -m Displays a logical, ordered map of the LSPs installed 41 | // -n "String" Name of the layered provider (catalog name, not dll name) 42 | // -o CatID Layer over the given provider (indicated by the catalog id) 43 | // -p Print the Winsock catalog (and catalog ids) 44 | // -r CatID Remove the LSP 45 | // 46 | // For example, first print out the catalog: 47 | // instlsp.exe -p 48 | // 1001 - MSAFD ATM AAL5 49 | // 1002 - MSAFD Tcpip [TCP/IP] 50 | // 1003 - MSAFD Tcpip [UDP/IP] 51 | // 1004 - MSAFD Tcpip [RAW/IP] 52 | // 1005 - RSVP UDP Service Provider 53 | // 1006 - RSVP TCP Service Provider 54 | // 1019 - MSAFD AppleTalk [ADSP] 55 | // 1020 - MSAFD AppleTalk [ADSP] [Pseudo Stream] 56 | // 1021 - MSAFD AppleTalk [PAP] 57 | // 1022 - MSAFD AppleTalk [RTMP] 58 | // 1023 - MSAFD AppleTalk [ZIP] 59 | // 60 | // To install over AppleTalk 61 | // instlsp.exe -i -o 1019 -o 1020 -o 1021 -o 1022 -o 1023 -n "Foobar LSP" -d c:\path\lsp.dll 62 | // 63 | // Print the new catalog out: 64 | // instlsp.exe -p 65 | // 1041 - Foobar LSP over [MSAFD AppleTalk [ADSP]] 66 | // 1042 - Foobar LSP over [MSAFD AppleTalk [PAP]] 67 | // 1043 - Foobar LSP over [MSAFD AppleTalk [RTMP]] 68 | // 1044 - Foobar LSP over [MSAFD AppleTalk [ZIP]] 69 | // 1001 - MSAFD ATM AAL5 70 | // 1002 - MSAFD Tcpip [TCP/IP] 71 | // 1003 - MSAFD Tcpip [UDP/IP] 72 | // 1004 - MSAFD Tcpip [RAW/IP] 73 | // 1005 - RSVP UDP Service Provider 74 | // 1006 - RSVP TCP Service Provider 75 | // 1019 - MSAFD AppleTalk [ADSP] 76 | // 1020 - MSAFD AppleTalk [ADSP] [Pseudo Stream] 77 | // 1021 - MSAFD AppleTalk [PAP] 78 | // 1022 - MSAFD AppleTalk [RTMP] 79 | // 1023 - MSAFD AppleTalk [ZIP] 80 | // 1040 - Foobar LSP 81 | // 82 | // To remove the LSP, supply the catalog ID of the hidden entry to remove: 83 | // instlsp.exe -r 1040 84 | // 85 | // In case all else fails (removes all LSPs installed): 86 | // instlsp.exe -f 87 | // 88 | #include "instlsp.h" 89 | 90 | // 91 | // Global variable: Function pointer to WSCUpdateProvider if on Windows XP or greater. 92 | // Uninstalling an LSP when other LSPs are layered over it is really 93 | // difficult; however on Windows XP and greater the WSCUpdateProvider 94 | // function makes this much simpler. On older platforms its a real 95 | // pain. 96 | LPWSCUPDATEPROVIDER fnWscUpdateProvider = NULL, 97 | fnWscUpdateProvider32 = NULL; 98 | HMODULE gModule = NULL; 99 | GUID gProviderGuid; 100 | 101 | // Prototype for usage information 102 | void usage( __in_z char *progname ); 103 | 104 | //////////////////////////////////////////////////////////////////////////////// 105 | // 106 | // Function Implementation 107 | // 108 | //////////////////////////////////////////////////////////////////////////////// 109 | 110 | // 111 | // Function: main 112 | // 113 | // Description: 114 | // Parse the command line arguments and call either the install, remove, 115 | // print, etc. routines. 116 | // 117 | int _cdecl main(int argc, char *argv[]) 118 | { 119 | WSADATA wsd; 120 | LPWSAPROTOCOL_INFOW pProtocolInfo = NULL; 121 | LSP_ENTRY *pLspMap=NULL; 122 | #ifdef _WIN64 123 | WINSOCK_CATALOG eCatalog = LspCatalog64Only; 124 | #else 125 | WINSOCK_CATALOG eCatalog = LspCatalog32Only; 126 | #endif 127 | INT iTotalProtocols = 0, 128 | iLspCount = 0, 129 | i; 130 | DWORD *pdwCatalogIdArray = NULL, 131 | dwCatalogIdArrayCount = 0, // How many to install over 132 | dwRemoveCatalogId = 0; 133 | BOOL bInstall = TRUE, 134 | bInstallOverAll = FALSE, 135 | bRemoveAllLayeredEntries = FALSE, 136 | bPrintProviders = FALSE, 137 | bDisplayOnlyLayeredEntries = FALSE, 138 | bVerbose = FALSE, 139 | bMapLsp = FALSE, 140 | bArgsOkay = FALSE, 141 | bIFSProvider = FALSE; 142 | char *lpszLspName = NULL, 143 | *lpszLspPathAndFile = NULL, 144 | *lpszLspPathAndFile32 = NULL; 145 | int rc; 146 | 147 | //////////////////////////////////////////////////////////////////////////// 148 | // 149 | // Initialization and Command Line Parsing 150 | // 151 | //////////////////////////////////////////////////////////////////////////// 152 | 153 | // Load Winsock 154 | rc = WSAStartup( MAKEWORD(2,2), &wsd ); 155 | if ( 0 != rc ) 156 | { 157 | fprintf( stderr, "Unable to load Winsock: %d\n", rc ); 158 | return -1; 159 | } 160 | 161 | // Initialize data structures 162 | LspCreateHeap( &rc ); 163 | 164 | __try 165 | { 166 | InitializeCriticalSection( &gDebugCritSec ); 167 | } 168 | __except( EXCEPTION_EXECUTE_HANDLER ) 169 | { 170 | goto cleanup; 171 | } 172 | 173 | 174 | // First count how many catalog parameters are supplied so we can dynamically 175 | // allocate the right sized buffer 176 | for(i=1; i < argc ;i++) 177 | { 178 | if ( strncmp( argv[ i ], "-o", 2 ) == 0 ) 179 | dwCatalogIdArrayCount++; 180 | } 181 | 182 | // Allocate space for the array of catalog IDs 183 | if ( 0 < dwCatalogIdArrayCount ) 184 | { 185 | pdwCatalogIdArray = (DWORD *) LspAlloc( 186 | sizeof( DWORD ) * dwCatalogIdArrayCount, 187 | &rc 188 | ); 189 | if ( NULL == pdwCatalogIdArray ) 190 | { 191 | goto cleanup; 192 | } 193 | } 194 | 195 | // Set back to zero so we can use it as the index into our array 196 | dwCatalogIdArrayCount = 0; 197 | 198 | // Parse the command line 199 | for(i=1; i < argc ;i++) 200 | { 201 | if ( ( 2 != strlen( argv[i] ) ) && 202 | ( '-' != argv[i][0] ) && 203 | ( '/' != argv[i][0] ) 204 | ) 205 | { 206 | goto cleanup; 207 | } 208 | 209 | switch ( tolower( argv[i][1] ) ) 210 | { 211 | case 'a': // Install LSP over all currently installed providers 212 | bInstallOverAll = TRUE; 213 | break; 214 | 215 | case 'c': // For 64-bit: which catalog to operate on? 216 | if (i+1 >= argc) 217 | goto cleanup; 218 | 219 | switch (tolower(argv[i+1][0])) 220 | { 221 | case 'b': // Both Winsock catalogs 222 | eCatalog = LspCatalogBoth; 223 | break; 224 | case '6': // 64-bit Winsock catalog only 225 | eCatalog = LspCatalog64Only; 226 | break; 227 | case '3': // 32-bit Winsock catalog only 228 | eCatalog = LspCatalog32Only; 229 | break; 230 | default: 231 | goto cleanup; 232 | break; 233 | } 234 | i++; 235 | break; 236 | 237 | case 'd': // Full path and filename to LSP 238 | if ( i+1 >= argc ) 239 | goto cleanup; 240 | if (_strnicmp(argv[i], "-d32", 4)) 241 | lpszLspPathAndFile32 = argv[ ++i ]; 242 | else 243 | lpszLspPathAndFile = argv[ ++i ]; 244 | 245 | break; 246 | 247 | case 'f': // Uninstall all layered providers 248 | bRemoveAllLayeredEntries = TRUE; 249 | bInstall = FALSE; 250 | break; 251 | 252 | case 'h': // Install as an IFS provider 253 | bIFSProvider = TRUE; 254 | break; 255 | 256 | case 'i': // install 257 | bInstall = TRUE; 258 | break; 259 | 260 | case 'l': // print the layered providers only 261 | bPrintProviders = TRUE; 262 | bDisplayOnlyLayeredEntries = TRUE; 263 | break; 264 | 265 | case 'm': // Map and print the LSP structure 266 | bMapLsp = TRUE; 267 | bInstall = FALSE; 268 | break; 269 | 270 | case 'n': // name of the LSP to install (not the DLL name) 271 | if (i+1 >= argc) 272 | goto cleanup; 273 | 274 | lpszLspName = argv[++i]; 275 | break; 276 | 277 | case 'o': // catalog id (to install over) 278 | if (i+1 >= argc) 279 | goto cleanup; 280 | 281 | pdwCatalogIdArray[dwCatalogIdArrayCount++] = atoi(argv[++i]); 282 | break; 283 | 284 | case 'p': // print the catalog 285 | bPrintProviders = TRUE; 286 | bDisplayOnlyLayeredEntries = FALSE; 287 | break; 288 | 289 | case 'r': // remove an LSP 290 | bInstall = FALSE; 291 | if (i+1 >= argc) 292 | goto cleanup; 293 | dwRemoveCatalogId = atol(argv[++i]); 294 | break; 295 | 296 | case 'v': // verbose mode (when printing with -p option) 297 | bVerbose = TRUE; 298 | break; 299 | 300 | default: 301 | goto cleanup; 302 | break; 303 | } 304 | } 305 | 306 | #ifndef _WIN64 307 | if ( LspCatalog64Only == eCatalog ) 308 | { 309 | fprintf(stderr, "\n\nUnable to manipulate 64-bit Winsock catalog from 32-bit process!\n\n"); 310 | goto cleanup; 311 | } 312 | #endif 313 | 314 | bArgsOkay = TRUE; 315 | 316 | gModule = LoadUpdateProviderFunction(); 317 | 318 | if ( TRUE == bPrintProviders ) 319 | { 320 | // Print the 32-bit catalog 321 | if ( ( LspCatalogBoth == eCatalog ) || ( LspCatalog32Only == eCatalog ) ) 322 | { 323 | printf( "\n\nWinsock 32-bit Catalog:\n" ); 324 | printf( "=======================\n" ); 325 | PrintProviders( LspCatalog32Only, bDisplayOnlyLayeredEntries, bVerbose ); 326 | } 327 | // Print the 64-bit catalog 328 | if ( ( LspCatalogBoth == eCatalog ) || ( LspCatalog64Only == eCatalog ) ) 329 | { 330 | printf( "\n\nWinsock 64-bit Catalog:\n" ); 331 | printf( "=======================\n" ); 332 | PrintProviders( LspCatalog64Only, bDisplayOnlyLayeredEntries, bVerbose ); 333 | } 334 | } 335 | else if ( TRUE == bInstall ) 336 | { 337 | if ( NULL == lpszLspPathAndFile ) 338 | { 339 | fprintf( stderr, "\n\nError! Please specify path and filename of LSP!\n\n"); 340 | bArgsOkay = FALSE; 341 | goto cleanup; 342 | } 343 | 344 | if ( TRUE == bInstallOverAll ) 345 | { 346 | // Make sure user didn't specify '-a' and '-o' flags 347 | if ( 0 != dwCatalogIdArrayCount ) 348 | { 349 | fprintf( stderr, "\n\nError! Cannot specify both '-a' and '-o' flags!\n\n" ); 350 | goto cleanup; 351 | } 352 | 353 | // Enumerate the appropriate catalog we will be working on 354 | pProtocolInfo = EnumerateProviders( eCatalog, &iTotalProtocols ); 355 | if ( NULL == pProtocolInfo ) 356 | { 357 | fprintf( stderr, "%s: EnumerateProviders: Unable to enumerate Winsock catalog\n", 358 | argv[ 0 ] 359 | ); 360 | goto cleanup; 361 | } 362 | 363 | // Count how many non layered protocol entries there are 364 | for(i=0; i < iTotalProtocols ;i++) 365 | { 366 | if ( LAYERED_PROTOCOL != pProtocolInfo[ i ].ProtocolChain.ChainLen ) 367 | dwCatalogIdArrayCount++; 368 | } 369 | 370 | // Allocate space for all the entries 371 | pdwCatalogIdArray = (DWORD *) LspAlloc( 372 | sizeof( DWORD ) * dwCatalogIdArrayCount, 373 | &rc 374 | ); 375 | if ( NULL == pdwCatalogIdArray ) 376 | { 377 | fprintf( stderr, "%s: LspAlloc failed: %d\n", argv[ 0 ], rc ); 378 | goto cleanup; 379 | } 380 | 381 | // Get the catalog IDs for all existing providers 382 | dwCatalogIdArrayCount = 0 ; 383 | for(i=0; i < iTotalProtocols ;i++) 384 | { 385 | if ( LAYERED_PROTOCOL != pProtocolInfo[ i ].ProtocolChain.ChainLen ) 386 | { 387 | pdwCatalogIdArray[ dwCatalogIdArrayCount++ ] = pProtocolInfo[ i ].dwCatalogEntryId; 388 | } 389 | } 390 | 391 | FreeProviders( pProtocolInfo ); 392 | pProtocolInfo = NULL; 393 | } 394 | 395 | // Install the LSP with the supplied parameters 396 | rc = InstallLsp( 397 | eCatalog, 398 | lpszLspName, 399 | lpszLspPathAndFile, 400 | lpszLspPathAndFile32, 401 | dwCatalogIdArrayCount, 402 | pdwCatalogIdArray, 403 | bIFSProvider, 404 | bInstallOverAll 405 | ); 406 | } 407 | else if ( TRUE == bMapLsp ) 408 | { 409 | // Display the 32-bit LSP catalog map 410 | if ( ( LspCatalogBoth == eCatalog ) || ( LspCatalog32Only == eCatalog ) ) 411 | { 412 | printf("\n32-bit Winsock LSP Map:\n\n"); 413 | 414 | pProtocolInfo = EnumerateProviders( LspCatalog32Only, &iTotalProtocols ); 415 | if ( NULL == pProtocolInfo ) 416 | { 417 | fprintf(stderr, "%s: EnumerateProviders: Unable to enumerate Winsock catalog\n", 418 | argv[ 0 ] 419 | ); 420 | goto cleanup; 421 | } 422 | 423 | pLspMap = BuildLspMap( pProtocolInfo, iTotalProtocols, &iLspCount ); 424 | if ( NULL == pLspMap ) 425 | { 426 | printf( "\nNo LSPs are installed\n\n" ); 427 | } 428 | else 429 | { 430 | PrintLspMap( pLspMap, iLspCount ); 431 | 432 | FreeLspMap( pLspMap, iLspCount ); 433 | pLspMap = NULL; 434 | } 435 | 436 | FreeProviders( pProtocolInfo ); 437 | pProtocolInfo = NULL; 438 | } 439 | 440 | // Display the 64-bit LSP catalog map 441 | if ( ( LspCatalogBoth == eCatalog ) || ( LspCatalog64Only == eCatalog ) ) 442 | { 443 | printf("\n64-bit Winsock LSP Map:\n\n"); 444 | 445 | pProtocolInfo = EnumerateProviders( LspCatalog64Only, &iTotalProtocols ); 446 | if ( NULL == pProtocolInfo ) 447 | { 448 | fprintf(stderr, "%s: EnumerateProviders: Unable to enumerate Winsock catalog\n", 449 | argv[ 0 ] 450 | ); 451 | goto cleanup; 452 | } 453 | 454 | pLspMap = BuildLspMap( pProtocolInfo, iTotalProtocols, &iLspCount ); 455 | if ( NULL == pLspMap ) 456 | { 457 | printf( "\nNo LSPs are installed\n\n" ); 458 | } 459 | else 460 | { 461 | PrintLspMap( pLspMap, iLspCount ); 462 | 463 | FreeLspMap( pLspMap, iLspCount ); 464 | pLspMap = NULL; 465 | } 466 | 467 | FreeProviders( pProtocolInfo ); 468 | pProtocolInfo = NULL; 469 | } 470 | } 471 | else 472 | { 473 | // We must be removing an LSP 474 | 475 | if ( TRUE == bRemoveAllLayeredEntries ) 476 | { 477 | if ( ( LspCatalogBoth == eCatalog ) || ( LspCatalog32Only == eCatalog ) ) 478 | RemoveAllLayeredEntries( LspCatalog32Only ); 479 | 480 | if ( ( LspCatalogBoth == eCatalog ) || ( LspCatalog64Only == eCatalog ) ) 481 | RemoveAllLayeredEntries( LspCatalog64Only ); 482 | } 483 | else 484 | { 485 | 486 | // Make sure a catalog entry to remove was supplied 487 | if ( dwRemoveCatalogId == 0 ) 488 | { 489 | bArgsOkay = FALSE; 490 | goto cleanup; 491 | } 492 | 493 | if ( ( LspCatalogBoth == eCatalog ) || ( LspCatalog32Only == eCatalog ) ) 494 | RemoveProvider( LspCatalog32Only, dwRemoveCatalogId ); 495 | 496 | if ( ( LspCatalogBoth == eCatalog ) || ( LspCatalog64Only == eCatalog ) ) 497 | RemoveProvider( LspCatalog64Only, dwRemoveCatalogId ); 498 | 499 | } 500 | } 501 | 502 | cleanup: 503 | 504 | if ( FALSE == bArgsOkay ) 505 | usage( argv[ 0 ] ); 506 | 507 | // 508 | // When invoked on Vista under non elevated permissions, the EXE is launched in 509 | // a new CMD window. The following getchar stops the window from exiting 510 | // immediately so you can see what its output was. 511 | // 512 | printf("Press any key to continue...\n"); 513 | getchar(); 514 | 515 | // 516 | // Free any dynamic allocations and/or handles 517 | // 518 | 519 | if ( NULL != pdwCatalogIdArray ) 520 | LspFree( pdwCatalogIdArray ); 521 | 522 | if ( NULL != pProtocolInfo) 523 | FreeProviders( pProtocolInfo ); 524 | 525 | if ( NULL != pLspMap ) 526 | FreeLspMap( pLspMap, iLspCount ); 527 | 528 | if ( NULL != gModule ) 529 | FreeLibrary( gModule ); 530 | 531 | LspDestroyHeap( ); 532 | 533 | DeleteCriticalSection( &gDebugCritSec ); 534 | 535 | WSACleanup(); 536 | 537 | return 0; 538 | } 539 | 540 | // 541 | // Function: usage 542 | // 543 | // Description: 544 | // Prints usage information. 545 | // 546 | void usage( __in_z char *progname ) 547 | { 548 | printf("usage: %s -i -r [CatId] -o [CatId] -p ...\n", progname); 549 | printf( 550 | " -a Install over all providers (base or layered)\n" 551 | " Cannot be combined with '-o' option\n" 552 | " -c Catalog Indicates which catalog to operate on\n" 553 | " b Both 64-bit and 32-bit Winsock catalogs\n" 554 | " 6 64-bit Winsock catalog only\n" 555 | " 3 32-bit Winsock catalog only\n" 556 | " -d Full path and filename of LSP DLL to install\n" 557 | " -d32 Full path and filename of 32-bit DLL to install\n" 558 | " (Only needed when installing on 64-bit OS\n" 559 | " -h LSP is an IFS provider (by default its non-IFS)\n" 560 | " -i Install LSP\n" 561 | " -f Remove all layered entries\n" 562 | " -l Print layered providers only\n" 563 | " -m Display a map of the LSPs and the order they are\n" 564 | " installed in\n" 565 | " -n Str Name of LSP\n" 566 | " -o CatId Install over specified LSP\n" 567 | " This option may be specified multiple times\n" 568 | " Cannot be combined with '-a' option\n" 569 | " -p Print all layers and their catalog IDs\n" 570 | " -r CatId Remove LSP\n" 571 | " -v Print verbose catalog information (used with -p)\n" 572 | "\n" 573 | "Example:\n\n" 574 | " install:\n\tinstlsp.exe -i -o 1001 -o 1002 -n \"MyLsp\" -d c:\\lsp\\mylsp.dll\n\n" 575 | " remove:\n\tinstlsp.exe -r \n\n" 576 | " remove all LSPs:\n\tinstlsp.exe -f\n" 577 | ); 578 | } 579 | -------------------------------------------------------------------------------- /install/instlsp.h: -------------------------------------------------------------------------------- 1 | // 2 | // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 3 | // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 4 | // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 5 | // PARTICULAR PURPOSE. 6 | // 7 | // Copyright (C) 2004 Microsoft Corporation. All Rights Reserved. 8 | // 9 | // Module Name: instlsp.h 10 | // 11 | // Description: 12 | // 13 | // This sample illustrates how to develop a layered service provider. 14 | // This LSP is simply a pass through sample which counts the bytes transfered 15 | // on each socket. 16 | // 17 | // This file contains function prototypes and structure definitions used in 18 | // the installation and removal of LSPs. 19 | // 20 | // 21 | #ifndef _INSTLSP_H_ 22 | #define _INSTLSP_H_ 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #ifndef _PSDK_BLD 35 | #include "lspcommon.h" 36 | #else 37 | #include "..\common\lspcommon.h" 38 | #endif 39 | #include 40 | #include 41 | 42 | #define DEFAULT_LSP_NAME "Test LSP" 43 | 44 | #define LAYERED_CHAIN ( BASE_PROTOCOL + 1 ) 45 | 46 | #define UPDATE_LSP_ENTRY 0 47 | 48 | #define MAX(a,b) ( (a) > (b) ? (a) : (b) ) 49 | #define MIN(a,b) ( (a) < (b) ? (a) : (b) ) 50 | 51 | typedef int (WSAAPI * LPWSCINSTALLPROVIDERANDCHAINS)( 52 | LPGUID lpProviderId, 53 | LPWSTR lpszProviderDllPath, 54 | #ifdef _WIN64 55 | LPWSTR lpszProviderDllPath32, 56 | #endif 57 | LPWSTR lpszLspName, 58 | DWORD dwServiceFlags, 59 | LPWSAPROTOCOL_INFOW lpProtocolInfoList, 60 | DWORD dwNumberOfEntries, 61 | LPDWORD lpdwCatalogEntryId, 62 | LPINT lpErrno 63 | ); 64 | 65 | // This structure is used to create the logical ordered LSP mappings 66 | typedef struct _LSP_ENTRY 67 | { 68 | WCHAR wszLspDll[ MAX_PATH ]; // LSPs DLL name (and possible path) 69 | WSAPROTOCOL_INFOW DummyEntry; // Provider entry for dummy LSP entry 70 | 71 | BOOL OrphanedEntries; // Indicates this LSP entry contains 72 | // only orphaned protocol chains 73 | 74 | WSAPROTOCOL_INFOW *LayeredEntries; // All layered providers beloging to LSP 75 | int Count; // Number of layered providers 76 | 77 | int *LayerChanged; // Indicates if the entry was changed -- 78 | // Used when removing providers 79 | 80 | GUID *LayeredGuids; // List of GUIDs the LAYERED providers 81 | // are installed under (doesn't include 82 | // the GUID the dummy entry is installed 83 | // under) 84 | int LayeredGuidCount; // Number of GUIDs in the array 85 | 86 | int MaxChainLength; // Used for sorting: the longest protocol 87 | // chain of all the layered providers 88 | int LspOrder; // Used for sorting: the lowest position 89 | // within a layered entries protocol 90 | // chain that a base provider sits 91 | 92 | int DependentCount; // Number of LSPs layered over this one 93 | int *DependentLspIndexArray; // Indices into LSP map of dependent LSPs 94 | 95 | } LSP_ENTRY; 96 | 97 | //////////////////////////////////////////////////////////////////////////////// 98 | // 99 | // External Global Variable Definitions 100 | // 101 | //////////////////////////////////////////////////////////////////////////////// 102 | extern LPWSCUPDATEPROVIDER fnWscUpdateProvider, 103 | fnWscUpdateProvider32; 104 | extern HMODULE gModule; 105 | extern GUID gProviderGuid; 106 | 107 | //////////////////////////////////////////////////////////////////////////////// 108 | // 109 | // LspAdd.cpp Prototypes 110 | // 111 | //////////////////////////////////////////////////////////////////////////////// 112 | 113 | // Install an LSP into the given Winsock catalog 114 | int 115 | InstallLsp( 116 | WINSOCK_CATALOG eCatalog, 117 | __in_z char *lpszLspName, 118 | __in_z char *lpszLspPathAndFile, 119 | __in_z char *lpszLspPathAndFile32, 120 | DWORD dwCatalogIdArrayCount, 121 | DWORD *pdwCatalogIdArray, 122 | BOOL IfsProvider, 123 | BOOL InstallOverAll 124 | ); 125 | 126 | // Installs one or more protocol entries into the given Winsock catalog under a GUID 127 | int 128 | InstallProvider( 129 | WINSOCK_CATALOG Catalog, 130 | GUID *Guid, 131 | __in_z WCHAR *lpwszLspPath, 132 | WSAPROTOCOL_INFOW *pProvider, 133 | INT iProviderCount 134 | ); 135 | 136 | int 137 | InstallProviderVista( 138 | WINSOCK_CATALOG eCatalog, // Which catalog to install LSP into 139 | __in_z WCHAR *lpszLspName, // String name of LSP 140 | __in_z WCHAR *lpszLspPathAndFile, // Location of 64-bit LSP dll and dll name 141 | __in_z WCHAR *lpszLspPathAndFile32, // Location of 32-bit LSP dll and dll name 142 | GUID *providerGuid, 143 | DWORD dwCatalogIdArrayCount, // Number of entries in pdwCatalogIdArray 144 | DWORD *pdwCatalogIdArray, // Array of IDs to install over 145 | BOOL IfsProvider, 146 | BOOL InstallOverAll 147 | ); 148 | 149 | // Creates the protocol entry for the hidden dummy entry which must be installed first 150 | WSAPROTOCOL_INFOW * 151 | CreateDummyEntry( 152 | WINSOCK_CATALOG Catalog, 153 | INT CatalogId, 154 | __in_z WCHAR *lpwszLspName, 155 | BOOL IfsProvider 156 | ); 157 | 158 | int 159 | InstallIfsLspProtocolChains( 160 | WINSOCK_CATALOG eCatalog, 161 | GUID *Guid, 162 | __in_z WCHAR *lpszLspName, 163 | __in_z WCHAR *lpszLspFullPathAndFile, 164 | DWORD *pdwCatalogIdArray, 165 | DWORD dwCatalogIdArrayCount 166 | ); 167 | 168 | int 169 | InstallNonIfsLspProtocolChains( 170 | WINSOCK_CATALOG eCatalog, 171 | GUID *Guid, 172 | __in_z WCHAR *lpszLspName, 173 | __in_z WCHAR *lpszLspFullPathAndFile, 174 | DWORD *pdwCatalogIdArray, 175 | DWORD dwCatalogIdArrayCount 176 | ); 177 | 178 | int 179 | InsertIfsLspIntoAllChains( 180 | WSAPROTOCOL_INFOW *OriginalEntry, // Original (unmodified) entry to follow chains 181 | WSAPROTOCOL_INFOW *Catalog, // Array of catalog entries 182 | int CatalogCount, // Number of entries in Catalog array 183 | int IfsEntryIdx, // Index into IFS standalone entry array 184 | int ChainIdx // Chain index in OriginalEntry to start at 185 | ); 186 | 187 | // Reorder the given Winsock catalog such that the providers beloging to the given 188 | // dummy hidden provider are at the head of the catalog 189 | int 190 | ReorderCatalog( 191 | WINSOCK_CATALOG Catalog, 192 | DWORD dwLayeredId 193 | ); 194 | 195 | // Write the Winsock catalog order according to the given list of catalog IDs 196 | DWORD * 197 | ReorderACatalog( 198 | WINSOCK_CATALOG Catalog, 199 | DWORD dwLayerId, 200 | INT *dwEntryCount 201 | ); 202 | 203 | // Rearrange the given Winsock catalog in the order specified as an array of catalog IDs 204 | int 205 | WriteProviderOrder( 206 | WINSOCK_CATALOG Catalog, 207 | DWORD *pdwCatalogOrder, 208 | DWORD dwNumberOfEntries, 209 | INT *lpErrno 210 | ); 211 | 212 | //////////////////////////////////////////////////////////////////////////////// 213 | // 214 | // LspDel.cpp Prototypes 215 | // 216 | //////////////////////////////////////////////////////////////////////////////// 217 | 218 | // Remove all layered service providers installed in the given catalog 219 | int 220 | RemoveAllLayeredEntries( 221 | WINSOCK_CATALOG Catalog 222 | ); 223 | 224 | // Remove all provider entries associated with the given GUID from the given catalog 225 | int 226 | DeinstallProvider( 227 | WINSOCK_CATALOG Catalog, 228 | GUID *Guid 229 | ); 230 | 231 | // Replaces/updates the protocol entries associated with the given GUID with the supplied 232 | // provider structures 233 | int 234 | UpdateProvider( 235 | WINSOCK_CATALOG Catalog, 236 | LPGUID ProviderId, 237 | WCHAR *DllPath, 238 | WSAPROTOCOL_INFOW *ProtocolInfoList, 239 | DWORD NumberOfEntries, 240 | LPINT lpErrno 241 | ); 242 | 243 | // Removes a single provider from the catalog that matches the given catalog ID 244 | int 245 | RemoveProvider( 246 | WINSOCK_CATALOG Catalog, 247 | DWORD dwProviderId 248 | ); 249 | 250 | //////////////////////////////////////////////////////////////////////////////// 251 | // 252 | // LspMap.cpp Prototypes 253 | // 254 | //////////////////////////////////////////////////////////////////////////////// 255 | 256 | // Prints all provider entries from the given catalog to the console 257 | void 258 | PrintProviders( 259 | WINSOCK_CATALOG Catalog, 260 | BOOL bLayeredOnly, 261 | BOOL bVerbose 262 | ); 263 | 264 | // Build a map of what LSPs are installed on the system, including their order 265 | LSP_ENTRY * 266 | BuildLspMap( 267 | WSAPROTOCOL_INFOW *pProviders, 268 | int iProviderCount, 269 | int *pLspCount 270 | ); 271 | 272 | // Print the LSP map to the console 273 | void 274 | PrintLspMap( 275 | LSP_ENTRY *pLspMap, 276 | int iLspCount 277 | ); 278 | 279 | // Free all resources associated with an already created LSP map 280 | void 281 | FreeLspMap( 282 | LSP_ENTRY *pLspMap, 283 | int iLspCount 284 | ); 285 | 286 | // Looks for dependencies between LSPs 287 | int 288 | LspDependencyCheck( 289 | LSP_ENTRY *pLspMap, 290 | int iLspCount 291 | ); 292 | 293 | // Updates the catalog ID for all providers in an LSP map 294 | void 295 | UpdateLspMap( 296 | LSP_ENTRY *pLspMap, 297 | DWORD dwOldValue, 298 | DWORD dwNewValue 299 | ); 300 | 301 | // After updating the catalog map the new entries over the old ones in the LSP map 302 | void 303 | MapNewEntriesToOld( 304 | LSP_ENTRY *pEntry, 305 | WSAPROTOCOL_INFOW *pProvider, 306 | int iProviderCount 307 | ); 308 | 309 | // Adds a GUID into the LSP_ENTRY array of unique guids 310 | int 311 | AddGuidToLspEntry( 312 | LSP_ENTRY *entry, 313 | GUID *guid, 314 | int *lpErrno 315 | ); 316 | 317 | // Updates the catalog IDs in the an array after a catalog entry changes 318 | void 319 | UpdateProviderOrder( 320 | LSP_ENTRY *UpdatedEntry, 321 | DWORD *OrderArray, 322 | int ArrayCount 323 | ); 324 | 325 | // Determines the "deepest" LSP installed in the catalog 326 | int 327 | MaxLayeredChainCount( 328 | LSP_ENTRY *pLspMap, 329 | int LspCount 330 | ); 331 | 332 | 333 | //////////////////////////////////////////////////////////////////////////////// 334 | // 335 | // LspUtil.cpp Prototypes 336 | // 337 | //////////////////////////////////////////////////////////////////////////////// 338 | 339 | // Compresses an protocol chain by removing the given ID 340 | BOOL 341 | RemoveIdFromChain( 342 | WSAPROTOCOL_INFOW *pInfo, 343 | DWORD dwCatalogId 344 | ); 345 | 346 | // Looks for the given catalog ID in the protocol chain 347 | BOOL 348 | IsIdInChain( 349 | WSAPROTOCOL_INFOW *pInfo, 350 | DWORD dwId 351 | ); 352 | 353 | // Returns the number of protocol entries of the given type (base or dummy entries) 354 | int 355 | GetProviderCount( 356 | WSAPROTOCOL_INFOW *pProviders, 357 | int iProviderCount, 358 | int iProviderType 359 | ); 360 | 361 | // Returns all the catalog entries belonging to the given GUID 362 | int 363 | GetLayeredEntriesByGuid( 364 | WSAPROTOCOL_INFOW *pMatchLayers, 365 | int *iLayeredCount, 366 | WSAPROTOCOL_INFOW *pEntries, 367 | int iEntryCount, 368 | GUID *MatchGuid 369 | ); 370 | 371 | // Determines if two entries are the same after reinstalling an LSP (since the IDs are different now) 372 | BOOL 373 | IsEqualProtocolEntries( 374 | WSAPROTOCOL_INFOW *pInfo1, 375 | WSAPROTOCOL_INFOW *pInfo2 376 | ); 377 | 378 | // Given the full path and name of LSP, load it and call the GetLspGuid export 379 | int 380 | RetrieveLspGuid( 381 | __in_z char *LspPath, 382 | GUID *Guid 383 | ); 384 | 385 | // Looks up whether the given provider is an IFS provider or not 386 | BOOL 387 | IsNonIfsProvider( 388 | WSAPROTOCOL_INFOW *pProvider, 389 | int iProviderCount, 390 | DWORD dwProviderId 391 | ); 392 | 393 | // Loads the WSCUpdateProvider function if available 394 | HMODULE 395 | LoadUpdateProviderFunction( 396 | ); 397 | 398 | // Counts how many orphaned layered chain entries exist 399 | int 400 | CountOrphanedChainEntries( 401 | WSAPROTOCOL_INFOW *pCatalog, 402 | int iCatalogCount 403 | ); 404 | 405 | WSAPROTOCOL_INFOW * 406 | FindProviderById( 407 | DWORD CatalogId, 408 | WSAPROTOCOL_INFOW *Catalog, 409 | int CatalogCount 410 | ); 411 | 412 | WSAPROTOCOL_INFOW * 413 | FindProviderByGuid( 414 | GUID *Guid, 415 | WSAPROTOCOL_INFOW *Catalog, 416 | int CatalogCount 417 | ); 418 | 419 | DWORD 420 | GetCatalogIdForProviderGuid( 421 | GUID *Guid, 422 | WSAPROTOCOL_INFOW *Catalog, 423 | int CatalogCount 424 | ); 425 | 426 | DWORD 427 | FindDummyIdFromProtocolChainId( 428 | DWORD CatalogId, 429 | WSAPROTOCOL_INFOW *Catalog, 430 | int CatalogCount 431 | ); 432 | 433 | void 434 | InsertIdIntoProtocolChain( 435 | WSAPROTOCOL_INFOW *Entry, 436 | int Index, 437 | DWORD InsertId 438 | ); 439 | 440 | void 441 | BuildSubsetLspChain( 442 | WSAPROTOCOL_INFOW *Entry, 443 | int Index, 444 | DWORD DummyId 445 | ); 446 | #endif 447 | -------------------------------------------------------------------------------- /install/instlsp.rc: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | #define MANIFEST_RESOURCE_ID 1 6 | //MANIFEST_RESOURCE_ID RT_MANIFEST "instlsp.exe.manifest" 7 | 8 | #define VER_FILETYPE VFT_APP 9 | #define VER_FILESUBTYPE VFT2_UNKNOWN 10 | #define VER_FILEDESCRIPTION_STR "Sample LSP Installer" 11 | #define VER_INTERNALNAME_STR "instlsp.exe" 12 | #define VER_ORIGINALFILENAME_STR "instlsp.exe" 13 | 14 | #include "common.ver" 15 | -------------------------------------------------------------------------------- /install/lsputil.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 3 | // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 4 | // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 5 | // PARTICULAR PURPOSE. 6 | // 7 | // Copyright (C) 2004 Microsoft Corporation. All Rights Reserved. 8 | // 9 | // Module Name: lsputil.cpp 10 | // 11 | // Description: 12 | // 13 | // This file contains miscellaneous utility functions used by the other major 14 | // LSP installer components (install, remove, LSP map). 15 | // See instlsp.cpp for more information on running this code. 16 | // 17 | #include "instlsp.h" 18 | 19 | // 20 | // Function: RemoveIdFromChain 21 | // 22 | // Description: 23 | // This function removes the given CatalogId from the protocol chain 24 | // for pinfo. 25 | // 26 | BOOL 27 | RemoveIdFromChain( 28 | WSAPROTOCOL_INFOW *pInfo, 29 | DWORD dwCatalogId 30 | ) 31 | { 32 | int i, 33 | j; 34 | 35 | for(i=0; i < pInfo->ProtocolChain.ChainLen ;i++) 36 | { 37 | if ( pInfo->ProtocolChain.ChainEntries[ i ] == dwCatalogId ) 38 | { 39 | for(j=i; j < pInfo->ProtocolChain.ChainLen-1 ; j++) 40 | { 41 | pInfo->ProtocolChain.ChainEntries[ j ] = 42 | pInfo->ProtocolChain.ChainEntries[ j+1 ]; 43 | } 44 | pInfo->ProtocolChain.ChainLen--; 45 | return TRUE; 46 | } 47 | } 48 | return FALSE; 49 | } 50 | 51 | // 52 | // Function: IsIdinChain 53 | // 54 | // Description: 55 | // This function determines whether the given catalog id is referenced 56 | // in the protocol chain of pinfo. 57 | // 58 | BOOL 59 | IsIdInChain( 60 | WSAPROTOCOL_INFOW *pInfo, 61 | DWORD dwId) 62 | { 63 | int i; 64 | 65 | for(i=0; i < pInfo->ProtocolChain.ChainLen ;i++) 66 | { 67 | if ( pInfo->ProtocolChain.ChainEntries[ i ] == dwId ) 68 | return TRUE; 69 | } 70 | return FALSE; 71 | } 72 | 73 | // 74 | // Function: GetProviderCount 75 | // 76 | // Description: 77 | // Returns the number of providers installed matching the given Provider Type. 78 | // The possible provider types are BASE_PROTOCOL or LAYERED_PROTOCOL. That is, 79 | // this function either returns the count of base providers or the number of 80 | // dummy LSP providers installed. 81 | // 82 | int 83 | GetProviderCount( 84 | WSAPROTOCOL_INFOW *pProviders, 85 | int iProviderCount, 86 | int iProviderType 87 | ) 88 | { 89 | int Count, i; 90 | 91 | Count = 0; 92 | for(i=0; i < iProviderCount ;i++) 93 | { 94 | if ( ( LAYERED_CHAIN == iProviderType ) && ( pProviders[ i ].ProtocolChain.ChainLen > 1 ) ) 95 | Count++; 96 | else if ( ( LAYERED_CHAIN != iProviderType) && ( pProviders[ i ].ProtocolChain.ChainLen == iProviderType ) ) 97 | Count++; 98 | } 99 | return Count; 100 | } 101 | 102 | // 103 | // Function: GetLayeredEntriesByGuid 104 | // 105 | // Description: 106 | // This routine is used by the uninstaller when WSCUpdateProvider is not 107 | // available. If after an LSP is removed, there are other LSPs which depend 108 | // on that LSP, the uninstaller must remove and reinstall all LSPs and fix up 109 | // the catalog ID references within the protocol chain. This routine is used 110 | // when reinstalling LSP providers. Because the layered entries belonging to 111 | // an LSP may be installed either under individual GUIDs or whole 112 | // groups of providers may be installed under the same GUID. This routine 113 | // Takes an array of WSAPROTOCOL_INFOW entries belonging to one LSP along with 114 | // a GUID and copies all WSAPROTOCOL_INFOW structures having the same GUID 115 | // to an array. The count of how many structures were copied is returned. 116 | // 117 | int 118 | GetLayeredEntriesByGuid( 119 | WSAPROTOCOL_INFOW *pMatchLayers, 120 | int *iLayeredCount, 121 | WSAPROTOCOL_INFOW *pEntries, 122 | int iEntryCount, 123 | GUID *MatchGuid 124 | ) 125 | { 126 | int count, 127 | err = SOCKET_ERROR, 128 | i; 129 | 130 | // First count how many entries belong to this GUID 131 | count = 0; 132 | for(i=0; i < iEntryCount ;i++) 133 | { 134 | if ( 0 == memcmp( MatchGuid, &pEntries[i].ProviderId, sizeof( GUID ) ) ) 135 | count++; 136 | } 137 | 138 | // Make sure the array passed in is large enough to hold the results 139 | if ( count > *iLayeredCount ) 140 | { 141 | *iLayeredCount = count; 142 | goto cleanup; 143 | } 144 | 145 | // Go back and copy the matching providers into our array 146 | count = 0; 147 | for(i=0; i < iEntryCount ;i++) 148 | { 149 | if ( 0 == memcmp( MatchGuid, &pEntries[ i ].ProviderId, sizeof( GUID ) ) ) 150 | { 151 | memcpy( &pMatchLayers[ count++ ], &pEntries[ i ], sizeof( WSAPROTOCOL_INFOW ) ); 152 | } 153 | } 154 | 155 | *iLayeredCount = count; 156 | 157 | err = NO_ERROR; 158 | 159 | cleanup: 160 | 161 | return err; 162 | } 163 | 164 | // 165 | // Function: IsEqualProtocolEntries 166 | // 167 | // Description: 168 | // This routine compares two WSAPROTOCOL_INFOW structures to determine 169 | // whether they are equal. This is done when a provider is uninstalled 170 | // and then reinstalled. After reinstallation we need to match the old 171 | // provider to the new (after reenumerating the catalog) so we can find 172 | // its new catalog ID. The fields used for determining a match are all 173 | // fields except the catalog ID (dwCatalogEntryId) and the protocol 174 | // string (szProtocol). 175 | // 176 | BOOL 177 | IsEqualProtocolEntries( 178 | WSAPROTOCOL_INFOW *pInfo1, 179 | WSAPROTOCOL_INFOW *pInfo2 180 | ) 181 | { 182 | if ( (memcmp(&pInfo1->ProviderId, &pInfo2->ProviderId, sizeof(GUID)) == 0) && 183 | (pInfo1->dwServiceFlags1 == pInfo2->dwServiceFlags1) && 184 | (pInfo1->dwServiceFlags2 == pInfo2->dwServiceFlags2) && 185 | (pInfo1->dwServiceFlags3 == pInfo2->dwServiceFlags3) && 186 | (pInfo1->dwServiceFlags4 == pInfo2->dwServiceFlags4) && 187 | (pInfo1->ProtocolChain.ChainLen == pInfo2->ProtocolChain.ChainLen) && 188 | (pInfo1->iVersion == pInfo2->iVersion) && 189 | (pInfo1->iAddressFamily == pInfo2->iAddressFamily) && 190 | (pInfo1->iMaxSockAddr == pInfo2->iMaxSockAddr) && 191 | (pInfo1->iMinSockAddr == pInfo2->iMinSockAddr) && 192 | (pInfo1->iSocketType == pInfo2->iSocketType) && 193 | (pInfo1->iProtocol == pInfo2->iProtocol) && 194 | (pInfo1->iProtocolMaxOffset == pInfo2->iProtocolMaxOffset) && 195 | (pInfo1->iNetworkByteOrder == pInfo2->iNetworkByteOrder) && 196 | (pInfo1->iSecurityScheme == pInfo2->iSecurityScheme) && 197 | (pInfo1->dwMessageSize == pInfo2->dwMessageSize) 198 | ) 199 | { 200 | return TRUE; 201 | } 202 | else 203 | { 204 | return FALSE; 205 | } 206 | } 207 | 208 | // 209 | // Function: RetrieveLspGuid 210 | // 211 | // Description: 212 | // This routine loads the given DLL and retrieves its GetLspGuid function 213 | // which returns the GUID under which the LSP's hidden dummy entry is to be 214 | // installed under. By exporting this function the uninstaller is decoupled 215 | // from a specific LSP. 216 | // 217 | int 218 | RetrieveLspGuid( 219 | __in_z char *LspPath, 220 | GUID *Guid 221 | ) 222 | { 223 | HMODULE hMod = NULL; 224 | LPFN_GETLSPGUID fnGetLspGuid = NULL; 225 | int retval = SOCKET_ERROR; 226 | 227 | // Load teh library 228 | hMod = LoadLibraryA( LspPath ); 229 | if ( NULL == hMod ) 230 | { 231 | fprintf( stderr, "RetrieveLspGuid: LoadLibraryA failed: %d\n", GetLastError() ); 232 | goto cleanup; 233 | } 234 | 235 | // Get a pointer to the LSPs GetLspGuid function 236 | fnGetLspGuid = (LPFN_GETLSPGUID) GetProcAddress( hMod, "GetLspGuid" ); 237 | if ( NULL == fnGetLspGuid ) 238 | { 239 | fprintf( stderr, "RetrieveLspGuid: GetProcAddress failed: %d\n", GetLastError() ); 240 | goto cleanup; 241 | } 242 | 243 | // Retrieve the LSPs GUID 244 | fnGetLspGuid( Guid ); 245 | 246 | retval = NO_ERROR; 247 | 248 | cleanup: 249 | 250 | if ( NULL != hMod ) 251 | FreeLibrary( hMod ); 252 | 253 | return retval; 254 | } 255 | 256 | 257 | #pragma warning(push) 258 | #pragma warning(disable: 4127) 259 | 260 | // 261 | // Function: IsNonIfsProvider 262 | // 263 | // Description: 264 | // This routine searches the catalog for a given provider (based on catalog ID) 265 | // and returns whether or not it is an IFS provider. This routine is used when 266 | // installing an IFS provider since all IFS providers have to appear in the 267 | // protocol chain beneath any non-IFS providers. 268 | // 269 | BOOL 270 | IsNonIfsProvider( 271 | WSAPROTOCOL_INFOW *pProvider, 272 | int iProviderCount, 273 | DWORD dwProviderId 274 | ) 275 | { 276 | int i; 277 | 278 | for(i=0; i < iProviderCount ;i++) 279 | { 280 | if ( pProvider[ i ].dwCatalogEntryId == dwProviderId ) 281 | { 282 | return !( pProvider[ i ].dwServiceFlags1 & XP1_IFS_HANDLES ); 283 | } 284 | } 285 | 286 | return FALSE; 287 | } 288 | 289 | #pragma warning(pop) 290 | 291 | // 292 | // Function: LoadUpdateProviderFunction 293 | // 294 | // Description: 295 | // This routine loads the WSCUpdateProvider function from ws2_32.dll. 296 | // This function is used when removing LSP entries and other LSPs are layered 297 | // on top of the one to be removed. If this API is present (which it is on 298 | // Windows XP and later), then the logic is much simpler. This routien will 299 | // load both the 32-bit and 64-bit versions of the function. 300 | // 301 | HMODULE 302 | LoadUpdateProviderFunction() 303 | { 304 | HMODULE hModule = NULL; 305 | HRESULT hr; 306 | char WinsockLibraryPath[ MAX_PATH+1 ], 307 | szExpandPath[ MAX_PATH+1 ]; 308 | 309 | // 310 | // See if we're on a platform that supports WSCUpdateProvider. If so then 311 | // uninstalling an LSP is easy; otherwise, it is very painful if you're 312 | // removing an LSP that has other LSPs on top if it. 313 | // 314 | if ( GetSystemDirectoryA( WinsockLibraryPath, MAX_PATH+1 ) == 0 ) 315 | { 316 | hr = StringCchCopyA( szExpandPath, MAX_PATH+1, "%SYSTEMROOT%\\system32" ); 317 | if ( FAILED( hr ) ) 318 | { 319 | fprintf( stderr, "LoadUpdateProviderFunctions: StringCchCopyA failed: 0x%x\n", hr ); 320 | goto cleanup; 321 | } 322 | 323 | if ( ExpandEnvironmentStringsA( WinsockLibraryPath, szExpandPath, MAX_PATH+1 ) == 0 ) 324 | { 325 | fprintf(stderr, "LoadUpdateProviderFunctions: Unable to expand environment string: %d\n", 326 | GetLastError() 327 | ); 328 | goto cleanup; 329 | } 330 | } 331 | 332 | hr = StringCchCatA( WinsockLibraryPath, MAX_PATH+1, WINSOCK_DLL ); 333 | if ( FAILED( hr ) ) 334 | { 335 | fprintf( stderr, "LoadUpdateProviderFunctions: StringCchCatA failed: 0x%x\n", hr ); 336 | goto cleanup; 337 | } 338 | 339 | hModule = LoadLibraryA( WinsockLibraryPath ); 340 | if (hModule == NULL) 341 | { 342 | fprintf(stderr, "LoadUpdateProviderFunctions: Unable to load %s: %d\n", 343 | WinsockLibraryPath, GetLastError() 344 | ); 345 | goto cleanup; 346 | } 347 | #ifdef _WIN64 348 | fnWscUpdateProvider = (LPWSCUPDATEPROVIDER)GetProcAddress(hModule, "WSCUpdateProvider"); 349 | 350 | fnWscUpdateProvider32 = (LPWSCUPDATEPROVIDER)GetProcAddress(hModule, "WSCUpdateProvider32"); 351 | #else 352 | fnWscUpdateProvider = (LPWSCUPDATEPROVIDER)GetProcAddress(hModule, "WSCUpdateProvider"); 353 | #endif 354 | 355 | return hModule; 356 | 357 | cleanup: 358 | 359 | if ( NULL != hModule ) 360 | { 361 | FreeLibrary( hModule ); 362 | hModule = NULL; 363 | } 364 | 365 | return NULL; 366 | } 367 | 368 | // 369 | // Function: CountOrphanedChainEntries 370 | // 371 | // Description: 372 | // This routne counts how many orphaned layered protocol entries exist. An 373 | // orphaned protocol entry is a protocol entry whose chain length greater 374 | // than one and whose dummy hidden entry (i.e. index 0 of its protocol chain 375 | // array) is missing. When building the LSP map, it normally finds entries 376 | // based upon the dummy hidden entries. This method is used to determine 377 | // if orphaned entries exist so they can be removed as well. 378 | // 379 | int 380 | CountOrphanedChainEntries( 381 | WSAPROTOCOL_INFOW *pCatalog, 382 | int iCatalogCount 383 | ) 384 | { 385 | int orphanCount = 0, 386 | i, j; 387 | 388 | for(i=0; i < iCatalogCount ;i++) 389 | { 390 | if ( pCatalog[ i ].ProtocolChain.ChainLen > 1 ) 391 | { 392 | for(j=0; j < iCatalogCount ;j++) 393 | { 394 | if ( i == j ) 395 | continue; 396 | if ( pCatalog[ j ].dwCatalogEntryId == pCatalog[ i ].ProtocolChain.ChainEntries[ 0 ] ) 397 | { 398 | break; 399 | } 400 | } 401 | if ( j >= iCatalogCount ) 402 | orphanCount++; 403 | } 404 | } 405 | 406 | return orphanCount; 407 | } 408 | 409 | // 410 | // Function: FindProviderById 411 | // 412 | // Description: 413 | // This routine searches the Winsock catalog for the provider entry which matches 414 | // the supplied catalog ID. 415 | // 416 | WSAPROTOCOL_INFOW * 417 | FindProviderById( 418 | DWORD CatalogId, 419 | WSAPROTOCOL_INFOW *Catalog, 420 | int CatalogCount 421 | ) 422 | { 423 | int i; 424 | 425 | for(i=0; i < CatalogCount ;i++) 426 | { 427 | if ( Catalog[ i ].dwCatalogEntryId == CatalogId ) 428 | return &Catalog[ i ]; 429 | } 430 | return NULL; 431 | } 432 | 433 | 434 | // 435 | // Function: FindProviderByGuid 436 | // 437 | // Description: 438 | // This routine searches the Winsock catalog for the entry which matches the 439 | // supplied GUID. 440 | // 441 | WSAPROTOCOL_INFOW * 442 | FindProviderByGuid( 443 | GUID *Guid, 444 | WSAPROTOCOL_INFOW *Catalog, 445 | int CatalogCount 446 | ) 447 | { 448 | int i; 449 | 450 | for(i=0; i < CatalogCount ;i++) 451 | { 452 | if ( 0 == memcmp( &Catalog[ i ].ProviderId, Guid, sizeof( GUID ) ) ) 453 | { 454 | return &Catalog[ i ]; 455 | } 456 | } 457 | 458 | return NULL; 459 | } 460 | 461 | // 462 | // Function: GetCatalogIdForProviderGuid 463 | // 464 | // Description: 465 | // This routine finds the WInsock catalog entry for the GUID and returns the 466 | // catalog ID for that entry. 467 | // 468 | DWORD 469 | GetCatalogIdForProviderGuid( 470 | GUID *Guid, 471 | WSAPROTOCOL_INFOW *Catalog, 472 | int CatalogCount 473 | ) 474 | { 475 | WSAPROTOCOL_INFOW *match = NULL; 476 | 477 | match = FindProviderByGuid( Guid, Catalog, CatalogCount ); 478 | if ( NULL != match ) 479 | { 480 | return match->dwCatalogEntryId; 481 | } 482 | 483 | return 0; 484 | } 485 | 486 | #pragma warning(push) 487 | #pragma warning(disable: 4127 ) 488 | 489 | // 490 | // Function: FindDummyIdFromProtocolChain 491 | // 492 | // Description: 493 | // This routine searches the catalog for the dummy LSP entry associated 494 | // with the given catalog ID. If the catalog ID pass is actually the 495 | // dummy entry, that provider is found and returned. If the ID is a 496 | // protocol chain, then the first entry in that provider's protocol chain 497 | // will reference the dummy ID of the LSP so that entry is then found 498 | // and returned. 499 | // 500 | DWORD 501 | FindDummyIdFromProtocolChainId( 502 | DWORD CatalogId, 503 | WSAPROTOCOL_INFOW *Catalog, 504 | int CatalogCount 505 | ) 506 | { 507 | int i; 508 | 509 | for(i=0; i < CatalogCount ;i++) 510 | { 511 | if ( CatalogId == Catalog[ i ].dwCatalogEntryId ) 512 | { 513 | if ( Catalog[ i ].ProtocolChain.ChainLen == LAYERED_PROTOCOL ) 514 | return Catalog[ i ].dwCatalogEntryId; 515 | else 516 | return Catalog[ i ].ProtocolChain.ChainEntries[ 0 ]; 517 | } 518 | } 519 | 520 | ASSERT( 0 ); 521 | 522 | return 0; 523 | } 524 | 525 | #pragma warning(pop) 526 | 527 | // 528 | // Function: InsertIdIntoProtocolChain 529 | // 530 | // Description: 531 | // This routine inserts the given ID into an existing catalog entry at 532 | // the given index location within the chain array. 533 | // 534 | void 535 | InsertIdIntoProtocolChain( 536 | WSAPROTOCOL_INFOW *Entry, 537 | int Index, 538 | DWORD InsertId 539 | ) 540 | { 541 | int i; 542 | 543 | for(i=Entry->ProtocolChain.ChainLen; i > Index ;i--) 544 | { 545 | Entry->ProtocolChain.ChainEntries[ i ] = Entry->ProtocolChain.ChainEntries[ i - 1 ]; 546 | } 547 | 548 | Entry->ProtocolChain.ChainEntries[ Index ] = InsertId; 549 | Entry->ProtocolChain.ChainLen++; 550 | } 551 | 552 | // 553 | // Function: BuildSubsetLspChain 554 | // 555 | // Description: 556 | // This routine takes a portion of an existing protocol chain (from the specified 557 | // index to the end) and makes it the new protocol chain while inserting the 558 | // specified DummyId in index 0. For example, 559 | // 560 | // Array Indices: 0 1 2 3 561 | // | 1400 | 1301 | 1201 | 1001 | Len = 4 562 | // 563 | // If this routine is called with Index == 2 and DummyId == 1500 then 564 | // the protocol chain would be: 565 | // 566 | // Array Indices: 0 1 2 3 567 | // | 1500 | 1201 | 1001 | | Len = 3 568 | // 569 | void 570 | BuildSubsetLspChain( 571 | WSAPROTOCOL_INFOW *Entry, 572 | int Index, 573 | DWORD DummyId 574 | ) 575 | { 576 | int Idx, i; 577 | 578 | for(i=Index,Idx=1; i < Entry->ProtocolChain.ChainLen ;i++,Idx++) 579 | { 580 | Entry->ProtocolChain.ChainEntries[ Idx ] = Entry->ProtocolChain.ChainEntries[ i ]; 581 | } 582 | 583 | Entry->ProtocolChain.ChainEntries[ 0 ] = DummyId; 584 | Entry->ProtocolChain.ChainLen = Entry->ProtocolChain.ChainLen - Index + 1; 585 | } 586 | -------------------------------------------------------------------------------- /install/makefile: -------------------------------------------------------------------------------- 1 | !include 2 | 3 | all: $(OUTDIR) $(OUTDIR)\instlsp.exe 4 | 5 | $(OUTDIR): 6 | if not exist "$(OUTDIR)/$(NULL)" mkdir $(OUTDIR) 7 | 8 | cflags= $(cflags) -D_PSDK_BLD 9 | 10 | INSTALL_OBJS= $(OUTDIR)\lspadd.obj \ 11 | $(OUTDIR)\lspdel.obj \ 12 | $(OUTDIR)\lspmap.obj \ 13 | $(OUTDIR)\lsputil.obj \ 14 | $(OUTDIR)\instlsp.obj \ 15 | $(OUTDIR)\prnpinfo.obj 16 | 17 | LIBS= ws2_32.lib ole32.lib rpcrt4.lib ..\common\$(OUTDIR)\lspcommon.lib $(baselibs) 18 | 19 | .cpp{$(OUTDIR)}.obj: 20 | $(cc) $(cdebug) $(cflags) -DSTRICT -DFD_SETSIZE=1024 /GS /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\" $** 21 | 22 | $(OUTDIR)\instlsp.res: instlsp.rc 23 | rc -r $(rcvars) /fo $(OUTDIR)\instlsp.res instlsp.rc 24 | 25 | $(OUTDIR)\instlsp.exe: $(INSTALL_OBJS) $(OUTDIR)\instlsp.res 26 | $(link) $(linkdebug) $(conlflags) -out:$*.exe -pdb:$*.pdb $** $(LIBS) 27 | if not exist "..\bin\$(OUTDIR)/$(NULL)" mkdir "..\bin\$(OUTDIR)/$(NULL)" 28 | copy $(OUTDIR)\instlsp.exe ..\bin\$(OUTDIR) 29 | if exist $(OUTDIR)\instlsp.pdb copy $(OUTDIR)\instlsp.pdb ..\bin\$(OUTDIR) 30 | Echo COMPILED INSTLSP.EXE 31 | 32 | clean: 33 | rmdir /s /q $(OUTDIR) 34 | -------------------------------------------------------------------------------- /install/prnpinfo.cpp: -------------------------------------------------------------------------------- 1 | // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 2 | // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 3 | // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 4 | // PARTICULAR PURPOSE. 5 | // 6 | // Copyright (C) 2004 Microsoft Corporation. All Rights Reserved. 7 | // 8 | // Module Name: prnpinfo.cpp 9 | // 10 | // Description: 11 | // 12 | // This file contains a single routine for printing the contents of a 13 | // WSAPROTOCOL_INFOW structure. 14 | // 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #ifndef _WIN32_WINNT 23 | #define _WIN32_WINNT 24 | #endif 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #pragma warning(push) 32 | #pragma warning(disable:4201) 33 | 34 | #include 35 | 36 | #pragma warning(pop) 37 | 38 | // 39 | // Function: PrintProtocolInfo 40 | // 41 | // Description: 42 | // Decode a WSAPROTOCOL_INFO entry and print the member fields 43 | // in a readable format. There's no secret voodoo here, just 44 | // interpret all the fields of the structure. 45 | // 46 | void 47 | PrintProtocolInfo( 48 | WSAPROTOCOL_INFOW *wsapi 49 | ) 50 | { 51 | WCHAR szGuidString[MAX_PATH], 52 | wszProviderPath[MAX_PATH]; 53 | INT dwProviderPathLen=MAX_PATH-1; 54 | int rc, error, i; 55 | 56 | rc = WSCGetProviderPath( 57 | &wsapi->ProviderId, 58 | wszProviderPath, 59 | &dwProviderPathLen, 60 | &error 61 | ); 62 | if ( 0 != rc ) 63 | { 64 | fprintf(stderr, "WSCGetProviderPath failed: %d\n", error); 65 | lstrcpyW(wszProviderPath, L"(error)"); 66 | } 67 | 68 | // 69 | // Display address family and protocol information 70 | // 71 | 72 | printf("\nProtocol: %S\n", wsapi->szProtocol); 73 | printf("\n Path: %S\n", wszProviderPath); 74 | printf(" Address Family: "); 75 | switch ( wsapi->iAddressFamily ) 76 | { 77 | case AF_INET: 78 | case AF_INET6: 79 | printf("%s\n", (wsapi->iAddressFamily == AF_INET ? "AF_INET" : "AF_INET6")); 80 | printf(" Protocol: "); 81 | switch (wsapi->iProtocol) 82 | { 83 | case IPPROTO_IP: 84 | printf("IPROTO_IP\n"); 85 | break; 86 | case IPPROTO_ICMP: 87 | printf("IPROTO_ICMP\n"); 88 | break; 89 | case IPPROTO_IGMP: 90 | printf("IPROTO_IGMP\n"); 91 | break; 92 | case IPPROTO_GGP: 93 | printf("IPROTO_GGP\n"); 94 | break; 95 | case IPPROTO_TCP: 96 | printf("IPROTO_TCP\n"); 97 | break; 98 | case IPPROTO_PUP: 99 | printf("IPROTO_PUP\n"); 100 | break; 101 | case IPPROTO_UDP: 102 | printf("IPROTO_UDP\n"); 103 | break; 104 | case IPPROTO_IDP: 105 | printf("IPROTO_IDP\n"); 106 | break; 107 | case IPPROTO_ND: 108 | printf("IPROTO_ND\n"); 109 | break; 110 | case IPPROTO_RM: 111 | printf("IPPROTO_RM\n"); 112 | break; 113 | case IPPROTO_RAW: 114 | printf("IPROTO_RAW\n"); 115 | break; 116 | } 117 | break; 118 | 119 | case AF_UNSPEC: 120 | printf("AF_UNSPEC\n"); 121 | printf(" Protocol: UNKNOWN: %d", wsapi->iProtocol); 122 | break; 123 | 124 | case AF_UNIX: 125 | printf("AF_UNIX\n"); 126 | printf(" Protocol: UNKNOWN: %d", wsapi->iProtocol); 127 | break; 128 | 129 | case AF_IMPLINK: 130 | printf("AF_IMPLINK\n"); 131 | printf(" Protocol: UNKNOWN: %d", wsapi->iProtocol); 132 | break; 133 | 134 | case AF_PUP: 135 | printf("AF_PUP\n"); 136 | printf(" Protocol: UNKNOWN: %d", wsapi->iProtocol); 137 | break; 138 | 139 | case AF_CHAOS: 140 | printf("AF_CHAOS\n"); 141 | printf(" Protocol: UNKNOWN: %d", wsapi->iProtocol); 142 | break; 143 | 144 | case AF_NS: 145 | printf("AF_NS or AF_IPX\n"); 146 | printf(" Protocol: "); 147 | 148 | switch ( wsapi->iProtocol ) 149 | { 150 | case NSPROTO_IPX: 151 | printf("NSPROTO_IPX\n"); 152 | break; 153 | case NSPROTO_SPX: 154 | printf("NSPROTO_SPX\n"); 155 | break; 156 | case NSPROTO_SPXII: 157 | printf("NSPROTO_SPXII\n"); 158 | break; 159 | } 160 | break; 161 | 162 | case AF_ISO: 163 | printf("AF_ISO or AF_OSI\n"); 164 | printf(" Protocol: UNKNOWN: %d", wsapi->iProtocol); 165 | break; 166 | 167 | case AF_ECMA: 168 | printf("AF_ECMA\n"); 169 | printf(" Protocol: UNKNOWN: %d", wsapi->iProtocol); 170 | break; 171 | 172 | case AF_DATAKIT: 173 | printf("AF_DATAKIT\n"); 174 | printf(" Protocol: UNKNOWN: %d", wsapi->iProtocol); 175 | break; 176 | 177 | case AF_CCITT: 178 | printf("AF_CCITT\n"); 179 | printf(" Protocol: UNKNOWN: %d", wsapi->iProtocol); 180 | break; 181 | 182 | case AF_SNA: 183 | printf("AF_SNA\n"); 184 | printf(" Protocol: UNKNOWN: %d", wsapi->iProtocol); 185 | break; 186 | 187 | case AF_DECnet: 188 | printf("AF_DECnet\n"); 189 | printf(" Protocol: UNKNOWN: %d", wsapi->iProtocol); 190 | break; 191 | 192 | case AF_DLI: 193 | printf("AF_DLI\n"); 194 | printf(" Protocol: UNKNOWN: %d", wsapi->iProtocol); 195 | break; 196 | 197 | case AF_LAT: 198 | printf("AF_LAT\n"); 199 | printf(" Protocol: UNKNOWN: %d", wsapi->iProtocol); 200 | break; 201 | 202 | case AF_HYLINK: 203 | printf("AF_HYLINK\n"); 204 | printf(" Protocol: UNKNOWN: %d", wsapi->iProtocol); 205 | break; 206 | 207 | case AF_APPLETALK: 208 | printf("AF_APPLETALK\n"); 209 | printf(" Protocol: "); 210 | 211 | switch ( wsapi->iProtocol ) 212 | { 213 | case DDPPROTO_RTMP: 214 | printf("DDPPROTO_RTMP\n"); 215 | break; 216 | case DDPPROTO_NBP: 217 | printf("DDPPROTO_NBP\n"); 218 | break; 219 | case DDPPROTO_ATP: 220 | printf("DDPROTO_ATP\n"); 221 | break; 222 | case DDPPROTO_AEP: 223 | printf("DDPPROTO_AEP\n"); 224 | break; 225 | case DDPPROTO_RTMPRQ: 226 | printf("DDPPROTO_RTMPRQ\n"); 227 | break; 228 | case DDPPROTO_ZIP: 229 | printf("DDPPROTO_ZIP\n"); 230 | break; 231 | case DDPPROTO_ADSP: 232 | printf("DDPPROTO_ADSP\n"); 233 | break; 234 | case ATPROTO_ADSP: 235 | printf("ATPROTO_ADSP\n"); 236 | break; 237 | case ATPROTO_ATP: 238 | printf("ATPROTO_ATP\n"); 239 | break; 240 | case ATPROTO_ASP: 241 | printf("ATPROTO_ASP\n"); 242 | break; 243 | case ATPROTO_PAP: 244 | printf("ATPROTO_PAP\n"); 245 | break; 246 | } 247 | break; 248 | 249 | case AF_NETBIOS: 250 | printf("AF_NETBIOS\n"); 251 | printf(" Protocol: "); 252 | printf("NetBIOS LANA %d\n", ((wsapi->iProtocol == 0x80000000) ? 0: abs(wsapi->iProtocol))); 253 | break; 254 | 255 | case AF_VOICEVIEW: 256 | printf("AF_VOICEVIEW\n"); 257 | printf(" Protocol: UNKNOWN: %d", wsapi->iProtocol); 258 | break; 259 | 260 | case AF_FIREFOX: 261 | printf("AF_FIREFOX\n"); 262 | printf(" Protocol: UNKNOWN: %d", wsapi->iProtocol); 263 | break; 264 | 265 | case AF_UNKNOWN1: 266 | printf("AF_UNKNOWN1\n"); 267 | printf(" Protocol: UNKNOWN: %d", wsapi->iProtocol); 268 | break; 269 | 270 | case AF_BAN: 271 | printf("AF_BAN\n"); 272 | printf(" Protocol: UNKNOWN: %d", wsapi->iProtocol); 273 | break; 274 | 275 | case AF_ATM: 276 | printf("AF_ATM\n"); 277 | printf(" Protocol: "); 278 | 279 | switch ( wsapi->iProtocol ) 280 | { 281 | case ATMPROTO_AALUSER: 282 | printf("ATMPROTO_AALUSER\n"); 283 | break; 284 | case ATMPROTO_AAL1: 285 | printf("ATMPROTO_AAL1\n"); 286 | break; 287 | case ATMPROTO_AAL2: 288 | printf("ATMPROTO_AAL2\n"); 289 | break; 290 | case ATMPROTO_AAL34: 291 | printf("ATMPROTO_AAL34\n"); 292 | break; 293 | case ATMPROTO_AAL5: 294 | printf("ATMPROTO_AAL5\n"); 295 | break; 296 | } 297 | break; 298 | 299 | case AF_CLUSTER: 300 | printf("AF_CLUSTER\n"); 301 | printf(" Protocol: UNKNOWN: %d", wsapi->iProtocol); 302 | break; 303 | case AF_12844: 304 | printf("AF_12844\n"); 305 | printf(" Protocol: UNKNOWN: %d", wsapi->iProtocol); 306 | break; 307 | case AF_IRDA: 308 | printf("AF_IRDA\n"); 309 | printf(" Protocol: "); 310 | 311 | switch (wsapi->iProtocol) 312 | { 313 | case IRDA_PROTO_SOCK_STREAM: 314 | printf("IRDA_PROTO_SOCK_STREAM\n"); 315 | break; 316 | } 317 | break; 318 | 319 | default: 320 | printf("Unknown: %d\n", wsapi->iAddressFamily); 321 | } 322 | 323 | // 324 | // Display socket type information 325 | // 326 | 327 | printf(" Socket Type: "); 328 | switch (wsapi->iSocketType) 329 | { 330 | case SOCK_STREAM: 331 | printf("SOCK_STREAM\n"); 332 | break; 333 | case SOCK_DGRAM: 334 | printf("SOCK_DGRAM\n"); 335 | break; 336 | case SOCK_RAW: 337 | printf("SOCK_RAW\n"); 338 | break; 339 | case SOCK_RDM: 340 | printf("SOCK_RDM\n"); 341 | break; 342 | case SOCK_SEQPACKET: 343 | printf("SOCK_SEQPACKET\n"); 344 | break; 345 | } 346 | 347 | // 348 | // Display the various provider flags for this entry 349 | // 350 | 351 | printf(" Connectionless: "); 352 | if (wsapi->dwServiceFlags1 & XP1_CONNECTIONLESS) 353 | printf("YES\n"); 354 | else 355 | printf("NO\n"); 356 | printf(" Guaranteed Delivery: "); 357 | if (wsapi->dwServiceFlags1 & XP1_GUARANTEED_DELIVERY) 358 | printf("YES\n"); 359 | else 360 | printf("NO\n"); 361 | printf(" Guaranteed Order: "); 362 | if (wsapi->dwServiceFlags1 & XP1_GUARANTEED_ORDER) 363 | printf("YES\n"); 364 | else 365 | printf("NO\n"); 366 | printf(" Message Oriented: "); 367 | if (wsapi->dwServiceFlags1 & XP1_MESSAGE_ORIENTED) 368 | printf("YES\n"); 369 | else 370 | printf("NO\n"); 371 | printf(" Pseudo Stream: "); 372 | if (wsapi->dwServiceFlags1 & XP1_PSEUDO_STREAM) 373 | printf("YES\n"); 374 | else 375 | printf("NO\n"); 376 | printf(" Graceful Close: "); 377 | if (wsapi->dwServiceFlags1 & XP1_GRACEFUL_CLOSE) 378 | printf("YES\n"); 379 | else 380 | printf("NO\n"); 381 | printf(" Expedited Data: "); 382 | if (wsapi->dwServiceFlags1 & XP1_EXPEDITED_DATA) 383 | printf("YES\n"); 384 | else 385 | printf("NO\n"); 386 | printf(" Connect Data: "); 387 | if (wsapi->dwServiceFlags1 & XP1_CONNECT_DATA) 388 | printf("YES\n"); 389 | else 390 | printf("NO\n"); 391 | printf(" Disconnect Data: "); 392 | if (wsapi->dwServiceFlags1 & XP1_DISCONNECT_DATA) 393 | printf("YES\n"); 394 | else 395 | printf("NO\n"); 396 | printf(" Supports Broadcast: "); 397 | if (wsapi->dwServiceFlags1 & XP1_SUPPORT_BROADCAST) 398 | printf("YES\n"); 399 | else 400 | printf("NO\n"); 401 | printf(" Supports Multipoint: "); 402 | if (wsapi->dwServiceFlags1 & XP1_SUPPORT_MULTIPOINT) 403 | printf("YES\n"); 404 | else 405 | printf("NO\n"); 406 | printf(" Multipoint Control Plane: "); 407 | if (wsapi->dwServiceFlags1 & XP1_MULTIPOINT_CONTROL_PLANE) 408 | printf("ROOTED\n"); 409 | else 410 | printf("NON-ROOTED\n"); 411 | printf(" Multipoint Data Plane: "); 412 | if (wsapi->dwServiceFlags1 & XP1_MULTIPOINT_DATA_PLANE) 413 | printf("ROOTED\n"); 414 | else 415 | printf("NON-ROOTED\n"); 416 | printf(" QoS Supported: "); 417 | if (wsapi->dwServiceFlags1 & XP1_QOS_SUPPORTED) 418 | printf("YES\n"); 419 | else 420 | printf("NO\n"); 421 | printf(" Unidirectional Sends: "); 422 | if (wsapi->dwServiceFlags1 & XP1_UNI_SEND) 423 | printf("YES\n"); 424 | else 425 | printf("NO\n"); 426 | printf(" Unidirection Receives: "); 427 | if (wsapi->dwServiceFlags1 & XP1_UNI_RECV) 428 | printf("YES\n"); 429 | else 430 | printf("NO\n"); 431 | printf(" IFS Handles: "); 432 | if (wsapi->dwServiceFlags1 & XP1_IFS_HANDLES) 433 | printf("YES\n"); 434 | else 435 | printf("NO\n"); 436 | printf(" Partial Messages: "); 437 | if (wsapi->dwServiceFlags1 & XP1_PARTIAL_MESSAGE) 438 | printf("YES\n"); 439 | else 440 | printf("NO\n"); 441 | printf(" Provider Flags: "); 442 | if (wsapi->dwProviderFlags & PFL_MULTIPLE_PROTO_ENTRIES) 443 | { 444 | printf("PFL_MULTIPLE_PROTO_ENTRIES "); 445 | } 446 | if (wsapi->dwProviderFlags & PFL_RECOMMENDED_PROTO_ENTRY) 447 | { 448 | printf("PFL_RECOMMENDED_PROT_ENTRY "); 449 | } 450 | if (wsapi->dwProviderFlags & PFL_HIDDEN) 451 | { 452 | printf("PFL_HIDDEN "); 453 | } 454 | if (wsapi->dwProviderFlags & PFL_MATCHES_PROTOCOL_ZERO) 455 | { 456 | printf("PFL_MATCHES_PROTOCOL_ZERO "); 457 | } 458 | if (wsapi->dwProviderFlags == 0) 459 | { 460 | printf("NONE"); 461 | } 462 | printf("\n"); 463 | 464 | // 465 | // Display provider ID and catalog ID as well as LSP chain information 466 | // 467 | 468 | StringFromGUID2( wsapi->ProviderId, szGuidString, MAX_PATH-1 ); 469 | 470 | printf(" Provider Id: %S\n", szGuidString); 471 | printf(" Catalog Entry Id: %ld\n", wsapi->dwCatalogEntryId); 472 | printf(" Number of Chain Entries: %d {", 473 | wsapi->ProtocolChain.ChainLen); 474 | 475 | for(i=0; i < wsapi->ProtocolChain.ChainLen ;i++) 476 | printf("%ld ", wsapi->ProtocolChain.ChainEntries[i]); 477 | 478 | printf("}\n"); 479 | 480 | // 481 | // Display the remaining information 482 | // 483 | 484 | printf(" Version: %d\n", wsapi->iVersion); 485 | printf("Max Socket Address Length: %d\n", wsapi->iMaxSockAddr); 486 | printf("Min Socket Address Length: %d\n", wsapi->iMinSockAddr); 487 | printf(" Protocol Max Offset: %d\n", wsapi->iProtocolMaxOffset); 488 | 489 | printf(" Network Byte Order: "); 490 | if (wsapi->iNetworkByteOrder == 0) 491 | printf("BIG-ENDIAN\n"); 492 | else 493 | printf("LITLE-ENDIAN\n"); 494 | 495 | printf(" Security Scheme: "); 496 | if (wsapi->iSecurityScheme == SECURITY_PROTOCOL_NONE) 497 | printf("NONE\n"); 498 | else 499 | printf("%d\n", wsapi->iSecurityScheme); 500 | 501 | printf(" Message Size: "); 502 | if (wsapi->dwMessageSize == 0) 503 | printf("N/A (Stream Oriented)\n"); 504 | else if (wsapi->dwMessageSize == 1) 505 | printf("Depended on underlying MTU\n"); 506 | else if (wsapi->dwMessageSize == 0xFFFFFFFF) 507 | printf("No limit\n"); 508 | else 509 | printf("%ld\n", wsapi->dwMessageSize); 510 | 511 | printf(" Provider Reserved: %d\n", wsapi->dwProviderReserved); 512 | } 513 | -------------------------------------------------------------------------------- /lsp.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.852 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "instlsp", "build\instlsp\instlsp.vcxproj", "{42AAC990-4ACE-42AF-98B3-8B525F5AACF4}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ifslsp", "build\ifslsp\ifslsp.vcxproj", "{7D5C6F64-B1B2-43E5-BA31-5CF5B1A8CFD8}" 9 | EndProject 10 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nonifslsp", "build\nonifslsp\nonifslsp.vcxproj", "{DB604815-1A6D-4FA2-BD88-EE235D04375E}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|x64 = Debug|x64 15 | Debug|x86 = Debug|x86 16 | Release|x64 = Release|x64 17 | Release|x86 = Release|x86 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {42AAC990-4ACE-42AF-98B3-8B525F5AACF4}.Debug|x64.ActiveCfg = Debug|x64 21 | {42AAC990-4ACE-42AF-98B3-8B525F5AACF4}.Debug|x64.Build.0 = Debug|x64 22 | {42AAC990-4ACE-42AF-98B3-8B525F5AACF4}.Debug|x86.ActiveCfg = Debug|Win32 23 | {42AAC990-4ACE-42AF-98B3-8B525F5AACF4}.Debug|x86.Build.0 = Debug|Win32 24 | {42AAC990-4ACE-42AF-98B3-8B525F5AACF4}.Release|x64.ActiveCfg = Release|x64 25 | {42AAC990-4ACE-42AF-98B3-8B525F5AACF4}.Release|x64.Build.0 = Release|x64 26 | {42AAC990-4ACE-42AF-98B3-8B525F5AACF4}.Release|x86.ActiveCfg = Release|Win32 27 | {42AAC990-4ACE-42AF-98B3-8B525F5AACF4}.Release|x86.Build.0 = Release|Win32 28 | {7D5C6F64-B1B2-43E5-BA31-5CF5B1A8CFD8}.Debug|x64.ActiveCfg = Debug|x64 29 | {7D5C6F64-B1B2-43E5-BA31-5CF5B1A8CFD8}.Debug|x64.Build.0 = Debug|x64 30 | {7D5C6F64-B1B2-43E5-BA31-5CF5B1A8CFD8}.Debug|x86.ActiveCfg = Debug|Win32 31 | {7D5C6F64-B1B2-43E5-BA31-5CF5B1A8CFD8}.Debug|x86.Build.0 = Debug|Win32 32 | {7D5C6F64-B1B2-43E5-BA31-5CF5B1A8CFD8}.Release|x64.ActiveCfg = Release|x64 33 | {7D5C6F64-B1B2-43E5-BA31-5CF5B1A8CFD8}.Release|x64.Build.0 = Release|x64 34 | {7D5C6F64-B1B2-43E5-BA31-5CF5B1A8CFD8}.Release|x86.ActiveCfg = Release|Win32 35 | {7D5C6F64-B1B2-43E5-BA31-5CF5B1A8CFD8}.Release|x86.Build.0 = Release|Win32 36 | {DB604815-1A6D-4FA2-BD88-EE235D04375E}.Debug|x64.ActiveCfg = Debug|x64 37 | {DB604815-1A6D-4FA2-BD88-EE235D04375E}.Debug|x64.Build.0 = Debug|x64 38 | {DB604815-1A6D-4FA2-BD88-EE235D04375E}.Debug|x86.ActiveCfg = Debug|Win32 39 | {DB604815-1A6D-4FA2-BD88-EE235D04375E}.Debug|x86.Build.0 = Debug|Win32 40 | {DB604815-1A6D-4FA2-BD88-EE235D04375E}.Release|x64.ActiveCfg = Release|x64 41 | {DB604815-1A6D-4FA2-BD88-EE235D04375E}.Release|x64.Build.0 = Release|x64 42 | {DB604815-1A6D-4FA2-BD88-EE235D04375E}.Release|x86.ActiveCfg = Release|Win32 43 | {DB604815-1A6D-4FA2-BD88-EE235D04375E}.Release|x86.Build.0 = Release|Win32 44 | EndGlobalSection 45 | GlobalSection(SolutionProperties) = preSolution 46 | HideSolutionNode = FALSE 47 | EndGlobalSection 48 | GlobalSection(ExtensibilityGlobals) = postSolution 49 | SolutionGuid = {340D5BA1-45A8-401A-9FAA-3DF208EBF496} 50 | EndGlobalSection 51 | EndGlobal 52 | -------------------------------------------------------------------------------- /nonifslsp/Makefile: -------------------------------------------------------------------------------- 1 | !include 2 | 3 | all: $(OUTDIR) $(OUTDIR)\nonifslsp.dll 4 | 5 | $(OUTDIR): 6 | if not exist "$(OUTDIR)/$(NULL)" mkdir $(OUTDIR) 7 | 8 | cflags= $(cflags) -D_PSDK_BLD 9 | 10 | DLL_OBJS= $(OUTDIR)\spi.obj \ 11 | $(OUTDIR)\extension.obj \ 12 | $(OUTDIR)\overlap.obj \ 13 | $(OUTDIR)\sockinfo.obj \ 14 | $(OUTDIR)\lspguid.obj \ 15 | $(OUTDIR)\asyncselect.obj 16 | 17 | LIBS= ws2_32.lib ole32.lib rpcrt4.lib ..\common\$(OUTDIR)\lspcommon.lib $(baselibs) 18 | 19 | .cpp{$(OUTDIR)}.obj: 20 | $(cc) $(cdebug) $(cflags) -DSTRICT -DFD_SETSIZE=1024 /GS /Fo"$(OUTDIR)\\" /Fd"$(OUTDIR)\\" $** 21 | 22 | $(OUTDIR)\nonifslsp.dll: $(DLL_OBJS) 23 | $(link) $(linkdebug) $(dlllflags) -def:nonifslsp.def \ 24 | -out:$*.dll -pdb:$*.pdb $(guilibsdll) $** $(LIBS) 25 | if not exist "..\bin\$(OUTDIR)/$(NULL)" mkdir "..\bin\$(OUTDIR)/$(NULL)" 26 | copy $(OUTDIR)\nonifslsp.dll ..\bin\$(OUTDIR) 27 | if exist $(OUTDIR)\nonifslsp.pdb copy $(OUTDIR)\nonifslsp.pdb ..\bin\$(OUTDIR) 28 | Echo COMPILED NONIFSLSP.DLL 29 | 30 | clean: 31 | rmdir /s /q $(OUTDIR) 32 | -------------------------------------------------------------------------------- /nonifslsp/asyncselect.cpp: -------------------------------------------------------------------------------- 1 | // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 2 | // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 3 | // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 4 | // PARTICULAR PURPOSE. 5 | // 6 | // Copyright (C) 2004 Microsoft Corporation. All Rights Reserved. 7 | // 8 | // Module Name: asyncselect.cpp 9 | // 10 | // Description: 11 | // This file contains the routines necessary to implement the WSPAsyncSelect 12 | // API. In order for our LSP to count the bytes sent and received by an 13 | // application when the app uses WSAAsyncSelect we need to intercept all 14 | // of the app's send and receive calls. To do this we implement a hidden 15 | // window. When the app makes a send/recv call we intercept this and post 16 | // the operation with the provider's socket to our own window. This allows 17 | // the LSP to receive the completion notification. At this point we will 18 | // update the statistics and then post the completion to the app's window 19 | // so that it may continue as expected. 20 | // 21 | // Note that any LSP which uses WPUCreateSocketHandle to return socket handles 22 | // to the upper layer must intercept all WSAAsyncSelect calls to use this 23 | // hidden window method. This is required since the wParam parameter passed 24 | // into the window's async handler is the socket handle on which the event 25 | // occured. If the LSP doesn't capture this then the wrong socket handle 26 | // will be passed directly to the upper layer's window handler. 27 | // 28 | // This file contains the I/O manager for all WSAAsyncselect I/O operations 29 | // 30 | #include "lspdef.h" 31 | #include 32 | 33 | #define STRSAFE_NO_DEPRECATE 34 | #include 35 | 36 | // 37 | // We must register a window class with a unique name. To do so we'll 38 | // use PROVIDER_CLASS string to format one which includes the current 39 | // process ID. This string will be formatted into a buffer of 40 | // PROVIDER_CLASS_CHAR_LEN length. 41 | // 42 | #define PROVIDER_CLASS TEXT("Layered WS2 Provider 0x%08x") 43 | #define PROVIDER_CLASS_CHAR_LEN 32 44 | 45 | // 46 | // When handing window messages it is possible we'll get a message for a 47 | // socket not in our list of created sockets. This can occur on an accepted 48 | // socket since some messages may be posted to the accepted socket before 49 | // the SOCK_INFO structure is inserted into the socket list in WSPAccept. 50 | // So if we don't find a SOCK_INFO structure, we'll sleep and try again 51 | // (up to MAX_ASYNC_RETRIES). 52 | // 53 | #define MAX_ASYNC_RETRIES 7 54 | #define ASYNC_TIMEOUT 500 // half a second 55 | 56 | #pragma warning(disable:4127) // Disable conditional expression is constant warning 57 | #pragma warning(disable:4706) // Disable assignment within conditional warning (message pump) 58 | 59 | // 60 | // Function Prototypes 61 | // 62 | 63 | // Creates the hidden window and is the message pump for it 64 | static DWORD WINAPI 65 | AsyncMsgHandler( 66 | LPVOID lpParameter 67 | ); 68 | 69 | // Handler function for our Winsock FD_* events which posts completions to upper layer 70 | static LRESULT CALLBACK 71 | AsyncWndProc( 72 | HWND hwnd, 73 | UINT uMsg, 74 | WPARAM wParam, 75 | LPARAM lParam 76 | ); 77 | 78 | // 79 | // Globals to this file 80 | // 81 | static HANDLE WorkerThreadHandle = NULL; // Dispatch thread for handing window messages 82 | static HWND AsyncWindow = NULL; // Handle to the hidden window 83 | static TCHAR AsyncProviderClassName[ PROVIDER_CLASS_CHAR_LEN ]; 84 | 85 | // 86 | // Function: StopAsyncWindowManager 87 | // 88 | // Description: 89 | // This function cleans up the subsystem that handles asynchronous 90 | // window IO (e.g. WSAAsyncSelect). Basically, it destroys the the 91 | // hidden window if its been created. Note that this function is 92 | // only called from WSPCleanup when the DLL is about to be unloaded, 93 | // and we've already entered the critical section (gCriticalSection). 94 | // 95 | int 96 | StopAsyncWindowManager( 97 | ) 98 | { 99 | int rc, 100 | code; 101 | 102 | if ( NULL != AsyncWindow ) 103 | { 104 | // Post a quit message to the thread 105 | PostMessage( AsyncWindow, WM_DESTROY, 0, 0 ); 106 | 107 | // Wait for the thread to cleanup and exit 108 | rc = WaitForSingleObject( WorkerThreadHandle, 10000 ); 109 | if ( WAIT_TIMEOUT == rc ) 110 | { 111 | dbgprint("StopAsyncWindowManager: Timed out waiting for async thread!"); 112 | goto cleanup; 113 | } 114 | 115 | // Retrieve the exit code and display a simple message 116 | rc = GetExitCodeThread( WorkerThreadHandle, (LPDWORD) &code ); 117 | if ( 0 == rc ) 118 | dbgprint("StopAsyncWindowManager: Unable to retrieve thread exit code: %d", 119 | GetLastError() ); 120 | else if ( 0 != code ) 121 | dbgprint("StopAsyncWindowManager: Async window thread exited abnormally!"); 122 | 123 | cleanup: 124 | 125 | CloseHandle( WorkerThreadHandle ); 126 | 127 | WorkerThreadHandle = NULL; 128 | } 129 | 130 | return 0; 131 | } 132 | 133 | // 134 | // Function: GetWorkerWindow 135 | // 136 | // Description: 137 | // This returns a handle to our hidden window that acts as an 138 | // intermediary between the apps window and winsock. If the window 139 | // hasn't already been created, then create it. 140 | // 141 | HWND 142 | GetWorkerWindow( 143 | ) 144 | { 145 | HANDLE ReadyEvent = NULL; 146 | int rc; 147 | 148 | EnterCriticalSection( &gCriticalSection ); 149 | if ( NULL == WorkerThreadHandle ) 150 | { 151 | // Create an event which the worker thread will signal when its ready 152 | ReadyEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); 153 | if ( NULL == ReadyEvent ) 154 | { 155 | dbgprint("GetWorkerWindow: CreateEvent failed: %d", GetLastError() ); 156 | goto cleanup; 157 | } 158 | 159 | // Create the asyn window message thread 160 | WorkerThreadHandle = CreateThread( 161 | NULL, 162 | 0, 163 | AsyncMsgHandler, 164 | (LPVOID)ReadyEvent, 165 | 0, 166 | NULL 167 | ); 168 | if ( NULL == WorkerThreadHandle ) 169 | { 170 | dbgprint( "GetWorkerWindow: CreateThread failed: %d", GetLastError() ); 171 | goto cleanup; 172 | } 173 | 174 | // Wait for the window to become initialized 175 | rc = WaitForSingleObject( ReadyEvent, INFINITE ); 176 | if ( ( WAIT_FAILED == rc ) || ( WAIT_TIMEOUT == rc ) ) 177 | dbgprint( "GetWorkerWindow: WaitForSingleObject failed: %d! (error = %d)", 178 | rc, GetLastError() ); 179 | } 180 | 181 | cleanup: 182 | 183 | if ( NULL != ReadyEvent ) 184 | { 185 | // Close the ready event 186 | rc = CloseHandle( ReadyEvent ); 187 | if ( 0 == rc ) 188 | { 189 | dbgprint("GetWorkerWindow: CloseHandle failed: %d", GetLastError() ); 190 | } 191 | } 192 | 193 | LeaveCriticalSection( &gCriticalSection ); 194 | 195 | return AsyncWindow; 196 | } 197 | 198 | // 199 | // Function: AsyncMsgHandler 200 | // 201 | // Description: 202 | // This is the message pump for our hidden window. 203 | // 204 | static DWORD WINAPI 205 | AsyncMsgHandler( 206 | LPVOID lpParameter 207 | ) 208 | { 209 | MSG msg; 210 | DWORD Ret; 211 | HANDLE readyEvent; 212 | HRESULT hr; 213 | WNDCLASS wndclass; 214 | 215 | 216 | // Event to signal when window is ready 217 | readyEvent = (HANDLE) lpParameter; 218 | 219 | hr = StringCchPrintf( 220 | AsyncProviderClassName, 221 | PROVIDER_CLASS_CHAR_LEN, 222 | PROVIDER_CLASS, 223 | GetCurrentProcessId() 224 | ); 225 | if ( FAILED( hr ) ) 226 | { 227 | dbgprint("AsyncMsgHandler: StringCchPrintf failed: %d", GetLastError()); 228 | goto cleanup; 229 | } 230 | 231 | dbgprint("AsyncMsgHandler: Class name is '%s'", AsyncProviderClassName ); 232 | 233 | memset( &wndclass, 0, sizeof( wndclass ) ); 234 | wndclass.lpfnWndProc = (WNDPROC)AsyncWndProc; 235 | wndclass.hInstance = gDllInstance; 236 | wndclass.lpszClassName = AsyncProviderClassName; 237 | 238 | if ( 0 == RegisterClass( &wndclass ) ) 239 | { 240 | dbgprint("AsyncMsgHandle: RegisterClass failed: %d", GetLastError()); 241 | goto cleanup; 242 | } 243 | 244 | // Create a window. 245 | AsyncWindow = CreateWindow( 246 | AsyncProviderClassName, 247 | TEXT("Layered Hidden Window"), 248 | WS_OVERLAPPEDWINDOW, 249 | CW_USEDEFAULT, 250 | CW_USEDEFAULT, 251 | CW_USEDEFAULT, 252 | CW_USEDEFAULT, 253 | NULL, 254 | NULL, 255 | gDllInstance, 256 | NULL 257 | ); 258 | 259 | if ( NULL == AsyncWindow ) 260 | { 261 | dbgprint("AsyncMessageHandler: CreateWindow failed: %d", GetLastError() ); 262 | goto cleanup; 263 | } 264 | 265 | // Indicate the window is ready 266 | SetEvent( readyEvent ); 267 | 268 | // Message pump 269 | while ( ( Ret = GetMessage( &msg, NULL, 0, 0 ) ) ) 270 | { 271 | if ( -1 == Ret ) 272 | { 273 | dbgprint("AsyncMessageHandler: GetMessage returned -1, exiting loop"); 274 | break; 275 | } 276 | TranslateMessage( &msg ); 277 | DispatchMessage( &msg ); 278 | } 279 | 280 | // Clean up the window and window class which were created in this thread 281 | if ( NULL != AsyncWindow ) 282 | { 283 | DestroyWindow( AsyncWindow ); 284 | AsyncWindow = NULL; 285 | } 286 | 287 | UnregisterClass( AsyncProviderClassName, gDllInstance ); 288 | 289 | ExitThread(0); 290 | 291 | cleanup: 292 | 293 | SetEvent( readyEvent ); 294 | 295 | ExitThread( (DWORD) -1); 296 | } 297 | 298 | // 299 | // Function: AsyncWndProc 300 | // 301 | // Description: 302 | // This is the window proc for our hidden window. Once we receive a message 303 | // on our hidden window we must translate our lower provider's socket handle 304 | // to the app's socket handle and then complete the notification to the user. 305 | // 306 | static LRESULT CALLBACK 307 | AsyncWndProc( 308 | HWND hWnd, 309 | UINT uMsg, 310 | WPARAM wParam, 311 | LPARAM lParam 312 | ) 313 | { 314 | SOCK_INFO *si = NULL; 315 | int retries, 316 | rc; 317 | 318 | if ( WM_SOCKET == uMsg ) 319 | { 320 | retries = 0; 321 | 322 | // 323 | // Given the lower provider's socket handle (the wParam), do a reverse lookup 324 | // to find the socket context structure. It is possible we received a message 325 | // for a socket not in our list of sockets. This usually occurs after WSPAccept 326 | // completes and we immediately get a message for the accepted socket but the 327 | // LSP code to insert the new context object hasn't executed yet. If this is 328 | // the case wait on an event until a new context object is added (which 329 | // signals the event). Note we'll wait only MAX_ASYNC_RETRIES times before 330 | // bailing. 331 | // 332 | while ( retries < MAX_ASYNC_RETRIES ) 333 | { 334 | dbgprint("hWnd 0x%p, uMsg 0x%x, WPARAM 0x%p, LPARAM 0x%p (retries %d)", 335 | hWnd, uMsg, wParam, lParam, retries); 336 | 337 | // Find the context for this lower provider socket handle 338 | si = GetCallerSocket( NULL, wParam ); 339 | if ( NULL == si ) 340 | { 341 | dbgprint("Unable to find socket context for 0x%p", wParam); 342 | 343 | // Wait on an event which is signaled when context is added 344 | rc = WaitForSingleObject( gAddContextEvent, ASYNC_TIMEOUT ); 345 | if ( WAIT_FAILED == rc ) 346 | { 347 | dbgprint("AsyncWndProc: WaitForSingleObject failed: %d", 348 | GetLastError()); 349 | break; 350 | } 351 | else // timeout or success 352 | { 353 | // Reset the event if it was signaled 354 | if ( WAIT_OBJECT_0 == rc ) 355 | ResetEvent( gAddContextEvent ); 356 | 357 | // If signaled, hopefully next lookup will succeed 358 | retries++; 359 | continue; 360 | } 361 | } 362 | 363 | gMainUpCallTable.lpWPUPostMessage( 364 | si->hWnd, 365 | si->uMsg, 366 | si->LayeredSocket, 367 | lParam 368 | ); 369 | 370 | return 0; 371 | } 372 | } 373 | else if ( WM_DESTROY == uMsg ) 374 | { 375 | // Post a quit message to exit our async message pump thread 376 | PostQuitMessage( 0 ); 377 | return 0; 378 | } 379 | 380 | return DefWindowProc( hWnd, uMsg, wParam, lParam ); 381 | } 382 | -------------------------------------------------------------------------------- /nonifslsp/lspdef.h: -------------------------------------------------------------------------------- 1 | // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 2 | // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 3 | // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 4 | // PARTICULAR PURPOSE. 5 | // 6 | // Copyright (C) 2004 Microsoft Corporation. All Rights Reserved. 7 | // 8 | // Module Name: provider.h 9 | // 10 | // Description: 11 | // 12 | // This sample illustrates how to develop a layered service provider that is 13 | // capable of counting all bytes transmitted through a TCP/IP socket. 14 | // 15 | // This file contains all datatypes and function prototypes used 16 | // throughout this project. 17 | // 18 | #ifndef _PROVIDER_H_ 19 | #define _PROVIDER_H_ 20 | 21 | #ifndef _PSDK_BLD 22 | #include 23 | #include 24 | #include 25 | #endif 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #ifndef _PSDK_BLD 33 | #include 34 | #else 35 | #include "..\common\lspcommon.h" 36 | #include 37 | #endif 38 | 39 | #define WM_SOCKET ( WM_USER + 321 ) // Message for our async window events 40 | 41 | // 42 | // This is the socket context data that we associate with each socket 43 | // that is passed back to the user app. That way when another API 44 | // is called we can query for this context information and find out 45 | // the socket handle to the lower provider. 46 | // 47 | typedef struct _SOCK_INFO 48 | { 49 | SOCKET ProviderSocket; // lower provider socket handle 50 | SOCKET LayeredSocket; // app's socket handle 51 | DWORD dwOutstandingAsync; // count of outstanding async operations 52 | BOOL bClosing; // has the app closed the socket? 53 | 54 | volatile LONG RefCount; // How many threads are accessing this info? 55 | 56 | ULONGLONG BytesSent; // Byte counts 57 | ULONGLONG BytesRecv; 58 | HANDLE hIocp; // associated with an IOCP? 59 | 60 | int LastError; // Last error that occured on this socket 61 | 62 | HWND hWnd; // Window (if any) associated with socket 63 | UINT uMsg; // Message for socket events 64 | 65 | CRITICAL_SECTION SockCritSec; // Synchronize access to this object 66 | 67 | PROVIDER *Provider;// Pointer to the provider from which socket was created 68 | 69 | LIST_ENTRY Link; 70 | 71 | } SOCK_INFO; 72 | 73 | // 74 | // Structure for mapping upper layer sockets to lower provider sockets in WSPSelect 75 | // 76 | typedef struct _FD_MAP 77 | { 78 | SOCKET ClientSocket; // Upper layer socket handle 79 | SOCKET ProvSocket; // Lower layer socket handle 80 | SOCK_INFO *Context; // Pointer to the socket context 81 | } FD_MAP; 82 | 83 | //////////////////////////////////////////////////////////////////////////////// 84 | // 85 | // Structures for each overlapped enabled API containing the arguments to that 86 | // function. 87 | // 88 | //////////////////////////////////////////////////////////////////////////////// 89 | 90 | // Argument list for the AcceptEx API 91 | typedef struct _ACCEPTEXARGS 92 | { 93 | SOCKET sAcceptSocket, 94 | sProviderAcceptSocket; 95 | PVOID lpOutputBuffer; 96 | DWORD dwReceiveDataLength, 97 | dwLocalAddressLength, 98 | dwRemoteAddressLength; 99 | DWORD dwBytesReceived; 100 | } ACCEPTEXARGS; 101 | 102 | // Argument list for the TransmitFile API 103 | typedef struct _TRANSMITFILEARGS 104 | { 105 | HANDLE hFile; 106 | DWORD nNumberOfBytesToWrite, 107 | nNumberOfBytesPerSend; 108 | LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers; 109 | DWORD dwFlags; 110 | } TRANSMITFILEARGS; 111 | 112 | // Argument list for the ConnectEx API 113 | typedef struct _CONNECTEXARGS 114 | { 115 | SOCKET s; 116 | SOCKADDR_STORAGE name; 117 | int namelen; 118 | PVOID lpSendBuffer; 119 | DWORD dwSendDataLength; 120 | DWORD dwBytesSent; 121 | } CONNECTEXARGS; 122 | 123 | // Argument list for TransmitPackets API 124 | typedef struct _TRANSMITPACKETSARGS 125 | { 126 | SOCKET s; 127 | LPTRANSMIT_PACKETS_ELEMENT lpPacketArray; 128 | DWORD nElementCount; 129 | DWORD nSendSize; 130 | DWORD dwFlags; 131 | } TRANSMITPACKETSARGS; 132 | 133 | // Argument list for DisconnectEx API 134 | typedef struct _DISCONNECTEXARGS 135 | { 136 | SOCKET s; 137 | DWORD dwFlags; 138 | DWORD dwReserved; 139 | } DISCONNECTEXARGS; 140 | 141 | // Argument list for WSARecvMsg API 142 | typedef struct _WSARECVMSGARGS 143 | { 144 | WSAMSG WsaMsg; 145 | DWORD dwNumberOfBytesRecvd; 146 | } WSARECVMSGARGS; 147 | 148 | // Argument list for the WSARecv API 149 | typedef struct _RECVARGS 150 | { 151 | LPWSABUF lpBuffers; 152 | DWORD dwBufferCount; 153 | DWORD dwNumberOfBytesRecvd, 154 | dwFlags; 155 | } RECVARGS; 156 | 157 | // Argument list for the WSARecvFrom API 158 | typedef struct _RECVFROMARGS 159 | { 160 | LPWSABUF lpBuffers; 161 | DWORD dwBufferCount; 162 | DWORD dwNumberOfBytesRecvd, 163 | dwFlags; 164 | LPSOCKADDR lpFrom; 165 | LPINT lpFromLen; 166 | } RECVFROMARGS; 167 | 168 | // Argument list for the WSASend API 169 | typedef struct _SENDARGS 170 | { 171 | LPWSABUF lpBuffers; 172 | DWORD dwBufferCount; 173 | DWORD dwNumberOfBytesSent; 174 | DWORD dwFlags; 175 | } SENDARGS; 176 | 177 | // Argument list for the WSASendTo API 178 | typedef struct _SENDTOARGS 179 | { 180 | LPWSABUF lpBuffers; 181 | DWORD dwBufferCount; 182 | DWORD dwNumberOfBytesSent; 183 | DWORD dwFlags; 184 | SOCKADDR_STORAGE To; 185 | int iToLen; 186 | } SENDTOARGS; 187 | 188 | // Argument list for the WSASendMsg API 189 | typedef struct _WSASENDMSGARGS 190 | { 191 | WSASENDMSG SendMsg; 192 | WSAMSG WsaMsg; 193 | DWORD dwNumberOfBytesSent; 194 | } WSASENDMSGARGS; 195 | 196 | // Argument list for the WSAIoctl API 197 | typedef struct _IOCTLARGS 198 | { 199 | DWORD dwIoControlCode; 200 | LPVOID lpvInBuffer; 201 | DWORD cbInBuffer; 202 | LPVOID lpvOutBuffer; 203 | DWORD cbOutBuffer; 204 | DWORD cbBytesReturned; 205 | } IOCTLARGS; 206 | 207 | // Enumerated type of all asynchronous Winsock operations 208 | typedef enum 209 | { 210 | LSP_OP_IOCTL = 1, 211 | LSP_OP_RECV, 212 | LSP_OP_RECVFROM, 213 | LSP_OP_SEND, 214 | LSP_OP_SENDTO, 215 | LSP_OP_TRANSMITFILE, 216 | LSP_OP_ACCEPTEX, 217 | LSP_OP_CONNECTEX, 218 | LSP_OP_DISCONNECTEX, 219 | LSP_OP_TRANSMITPACKETS, 220 | LSP_OP_RECVMSG, 221 | LSP_OP_SENDMSG 222 | } LspOperation; 223 | 224 | // 225 | // Our OVERLAPPED structure that includes state and argument 226 | // information. This structure is used for all overlapped IO 227 | // operations. Whenever the user app requests overlapped IO 228 | // we intercept this and make our own call with our own 229 | // structure. This way we will receive notification first 230 | // at which time we can perform post processesing. When we 231 | // are done we can then post the completion to the user app. 232 | // 233 | typedef struct _WSAOVERLAPPEDPLUS 234 | { 235 | WSAOVERLAPPED ProviderOverlapped; // Overlap to pass to lower layer 236 | PROVIDER *Provider; // Reference to provider who owns this socket 237 | SOCK_INFO *SockInfo; // Socket initiating this operation 238 | SOCKET CallerSocket; // Upper layer's socket handle 239 | SOCKET ProviderSocket; // Lower layer's socket handle 240 | HANDLE Iocp; 241 | int Error; // Error that operation completed with 242 | 243 | BOOL CloseThread; // Indicates whether we need to close thread we opened 244 | 245 | union 246 | { 247 | // Various arguments to the call being made 248 | ACCEPTEXARGS AcceptExArgs; 249 | TRANSMITFILEARGS TransmitFileArgs; 250 | CONNECTEXARGS ConnectExArgs; 251 | TRANSMITPACKETSARGS TransmitPacketsArgs; 252 | DISCONNECTEXARGS DisconnectExArgs; 253 | WSARECVMSGARGS RecvMsgArgs; 254 | RECVARGS RecvArgs; 255 | RECVFROMARGS RecvFromArgs; 256 | SENDARGS SendArgs; 257 | SENDTOARGS SendToArgs; 258 | IOCTLARGS IoctlArgs; 259 | WSASENDMSGARGS SendMsgArgs; 260 | }; 261 | 262 | LspOperation Operation; // Type of operation posted 263 | WSATHREADID CallerThreadId; // Which thread initiated operation 264 | LPWSAOVERLAPPED lpCallerOverlapped; // Upper layer's overlapped structure 265 | LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCallerCompletionRoutine; // APC to queue upon completion 266 | 267 | LIST_ENTRY Link; // Linked list entry 268 | 269 | } WSAOVERLAPPEDPLUS, * LPWSAOVERLAPPEDPLUS; 270 | 271 | //////////////////////////////////////////////////////////////////////////////// 272 | // 273 | // AsyncSelect.cpp prototypes 274 | // 275 | //////////////////////////////////////////////////////////////////////////////// 276 | 277 | // Retrieves the async worker window and creates it if it hasn't already been 278 | HWND 279 | GetWorkerWindow( 280 | ); 281 | 282 | // Issues the shutdown command to thread handling window messages 283 | int 284 | StopAsyncWindowManager( 285 | ); 286 | 287 | 288 | //////////////////////////////////////////////////////////////////////////////// 289 | // 290 | // Spi.cpp prototypes 291 | // 292 | //////////////////////////////////////////////////////////////////////////////// 293 | 294 | // 295 | // These are the Winsock functions an LSP must implement if it is non-IFS 296 | // 297 | 298 | SOCKET WSPAPI 299 | WSPAccept( 300 | SOCKET s, 301 | struct sockaddr FAR * addr, 302 | LPINT addrlen, 303 | LPCONDITIONPROC lpfnCondition, 304 | DWORD_PTR dwCallbackData, 305 | LPINT lpErrno 306 | ); 307 | 308 | int WSPAPI 309 | WSPAddressToString( 310 | LPSOCKADDR lpsaAddress, 311 | DWORD dwAddressLength, 312 | LPWSAPROTOCOL_INFOW lpProtocolInfo, 313 | LPWSTR lpszAddressString, 314 | LPDWORD lpdwAddressStringLength, 315 | LPINT lpErrno 316 | ); 317 | 318 | int WSPAPI 319 | WSPAsyncSelect( 320 | SOCKET s, 321 | HWND hWnd, 322 | unsigned int wMsg, 323 | long lEvent, 324 | LPINT lpErrno 325 | ); 326 | 327 | int WSPAPI 328 | WSPBind( 329 | SOCKET s, 330 | const struct sockaddr FAR * name, 331 | int namelen, 332 | LPINT lpErrno 333 | ); 334 | 335 | int WSPAPI 336 | WSPCancelBlockingCall( 337 | LPINT lpErrno 338 | ); 339 | 340 | int WSPAPI 341 | WSPCleanup( 342 | LPINT lpErrno 343 | ); 344 | 345 | int WSPAPI 346 | WSPCloseSocket( 347 | SOCKET s, 348 | LPINT lpErrno 349 | ); 350 | 351 | int WSPAPI 352 | WSPConnect( 353 | SOCKET s, 354 | const struct sockaddr FAR * name, 355 | int namelen, 356 | LPWSABUF lpCallerData, 357 | LPWSABUF lpCalleeData, 358 | LPQOS lpSQOS, 359 | LPQOS lpGQOS, 360 | LPINT lpErrno 361 | ); 362 | 363 | int WSPAPI 364 | WSPDuplicateSocket( 365 | SOCKET s, 366 | DWORD dwProcessId, 367 | LPWSAPROTOCOL_INFOW lpProtocolInfo, 368 | LPINT lpErrno 369 | ); 370 | 371 | int WSPAPI 372 | WSPEnumNetworkEvents( 373 | SOCKET s, 374 | WSAEVENT hEventObject, 375 | LPWSANETWORKEVENTS lpNetworkEvents, 376 | LPINT lpErrno 377 | ); 378 | 379 | int WSPAPI 380 | WSPEventSelect( 381 | SOCKET s, 382 | WSAEVENT hEventObject, 383 | long lNetworkEvents, 384 | LPINT lpErrno 385 | ); 386 | 387 | BOOL WSPAPI 388 | WSPGetOverlappedResult( 389 | SOCKET s, 390 | LPWSAOVERLAPPED lpOverlapped, 391 | LPDWORD lpcbTransfer, 392 | BOOL fWait, 393 | LPDWORD lpdwFlags, 394 | LPINT lpErrno 395 | ); 396 | 397 | int WSPAPI 398 | WSPGetPeerName( 399 | SOCKET s, 400 | struct sockaddr FAR * name, 401 | LPINT namelen, 402 | LPINT lpErrno 403 | ); 404 | 405 | int WSPAPI 406 | WSPGetSockName( 407 | SOCKET s, 408 | struct sockaddr FAR * name, 409 | LPINT namelen, 410 | LPINT lpErrno 411 | ); 412 | 413 | int WSPAPI 414 | WSPGetSockOpt( 415 | SOCKET s, 416 | int level, 417 | int optname, 418 | char FAR * optval, 419 | LPINT optlen, 420 | LPINT lpErrno 421 | ); 422 | 423 | BOOL WSPAPI 424 | WSPGetQOSByName( 425 | SOCKET s, 426 | LPWSABUF lpQOSName, 427 | LPQOS lpQOS, 428 | LPINT lpErrno 429 | ); 430 | 431 | int WSPAPI 432 | WSPIoctl( 433 | SOCKET s, 434 | DWORD dwIoControlCode, 435 | LPVOID lpvInBuffer, 436 | DWORD cbInBuffer, 437 | LPVOID lpvOutBuffer, 438 | DWORD cbOutBuffer, 439 | LPDWORD lpcbBytesReturned, 440 | LPWSAOVERLAPPED lpOverlapped, 441 | LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, 442 | LPWSATHREADID lpThreadId, 443 | LPINT lpErrno 444 | ); 445 | 446 | SOCKET WSPAPI 447 | WSPJoinLeaf( 448 | SOCKET s, 449 | const struct sockaddr FAR * name, 450 | int namelen, 451 | LPWSABUF lpCallerData, 452 | LPWSABUF lpCalleeData, 453 | LPQOS lpSQOS, 454 | LPQOS lpGQOS, 455 | DWORD dwFlags, 456 | LPINT lpErrno 457 | ); 458 | 459 | int WSPAPI 460 | WSPListen( 461 | SOCKET s, 462 | int backlog, 463 | LPINT lpErrno 464 | ); 465 | 466 | int WSPAPI 467 | WSPRecv( 468 | SOCKET s, 469 | LPWSABUF lpBuffers, 470 | DWORD dwBufferCount, 471 | LPDWORD lpNumberOfBytesRecvd, 472 | LPDWORD lpFlags, 473 | LPWSAOVERLAPPED lpOverlapped, 474 | LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, 475 | LPWSATHREADID lpThreadId, 476 | LPINT lpErrno 477 | ); 478 | 479 | int WSPAPI 480 | WSPRecvDisconnect( 481 | SOCKET s, 482 | LPWSABUF lpInboundDisconnectData, 483 | LPINT lpErrno 484 | ); 485 | 486 | int WSPAPI 487 | WSPRecvFrom( 488 | SOCKET s, 489 | LPWSABUF lpBuffers, 490 | DWORD dwBufferCount, 491 | LPDWORD lpNumberOfBytesRecvd, 492 | LPDWORD lpFlags, 493 | struct sockaddr FAR * lpFrom, 494 | LPINT lpFromLen, 495 | LPWSAOVERLAPPED lpOverlapped, 496 | LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, 497 | LPWSATHREADID lpThreadId, 498 | LPINT lpErrno 499 | ); 500 | 501 | int WSPAPI 502 | WSPSelect( 503 | int nfds, 504 | fd_set FAR * readfds, 505 | fd_set FAR * writefds, 506 | fd_set FAR * exceptfds, 507 | const struct timeval FAR * timeout, 508 | LPINT lpErrno 509 | ); 510 | 511 | int WSPAPI 512 | WSPSend( 513 | SOCKET s, 514 | LPWSABUF lpBuffers, 515 | DWORD dwBufferCount, 516 | LPDWORD lpNumberOfBytesSent, 517 | DWORD dwFlags, 518 | LPWSAOVERLAPPED lpOverlapped, 519 | LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, 520 | LPWSATHREADID lpThreadId, 521 | LPINT lpErrno 522 | ); 523 | 524 | int WSPAPI 525 | WSPSendDisconnect( 526 | SOCKET s, 527 | LPWSABUF lpOutboundDisconnectData, 528 | LPINT lpErrno 529 | ); 530 | 531 | int WSPAPI 532 | WSPSendTo( 533 | SOCKET s, 534 | LPWSABUF lpBuffers, 535 | DWORD dwBufferCount, 536 | LPDWORD lpNumberOfBytesSent, 537 | DWORD dwFlags, 538 | const struct sockaddr FAR * lpTo, 539 | int iToLen, 540 | LPWSAOVERLAPPED lpOverlapped, 541 | LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, 542 | LPWSATHREADID lpThreadId, 543 | LPINT lpErrno 544 | ); 545 | 546 | int WSPAPI 547 | WSPSetSockOpt( 548 | SOCKET s, 549 | int level, 550 | int optname, 551 | const char FAR * optval, 552 | int optlen, 553 | LPINT lpErrno 554 | ); 555 | 556 | int WSPAPI 557 | WSPShutdown ( 558 | SOCKET s, 559 | int how, 560 | LPINT lpErrno 561 | ); 562 | 563 | int WSPAPI 564 | WSPStringToAddress( 565 | LPWSTR AddressString, 566 | INT AddressFamily, 567 | LPWSAPROTOCOL_INFOW lpProtocolInfo, 568 | LPSOCKADDR lpAddress, 569 | LPINT lpAddressLength, 570 | LPINT lpErrno 571 | ); 572 | 573 | SOCKET WSPAPI 574 | WSPSocket( 575 | int af, 576 | int type, 577 | int protocol, 578 | __in LPWSAPROTOCOL_INFOW lpProtocolInfo, 579 | GROUP g, 580 | DWORD dwFlags, 581 | LPINT lpErrno 582 | ); 583 | 584 | // Copies the offset values from one overlapped structure to another 585 | void 586 | CopyOffset( 587 | WSAOVERLAPPED *ProviderOverlapped, 588 | WSAOVERLAPPED *UserOverlapped 589 | ); 590 | 591 | // Creates a new WSABUF array and copies the buffer and length values over 592 | WSABUF * 593 | CopyWSABuf( 594 | WSABUF *BufferArray, 595 | DWORD BufferCount, 596 | int *lpErrno 597 | ); 598 | 599 | // Frees a previously allocated WSABUF array 600 | void 601 | FreeWSABuf( 602 | WSABUF *BufferArray 603 | ); 604 | 605 | //////////////////////////////////////////////////////////////////////////////// 606 | // 607 | // Overlap.cpp prototypes 608 | // 609 | //////////////////////////////////////////////////////////////////////////////// 610 | 611 | // Initialize the overlapped system for handing asynchronous (overlapped) I/O 612 | int 613 | InitOverlappedManager( 614 | ); 615 | 616 | // Issues the shutdown command for all worker threads to exit 617 | int 618 | StopOverlappedManager( 619 | ); 620 | 621 | // Queue an overlapped operation for execution 622 | int 623 | QueueOverlappedOperation( 624 | WSAOVERLAPPEDPLUS *lpOverlapped, 625 | SOCK_INFO *Context 626 | ); 627 | 628 | // Allocate and initialize a WSAOVERLAPPEDPLUS structure which describes an overlapped operation 629 | WSAOVERLAPPEDPLUS * 630 | PrepareOverlappedOperation( 631 | SOCK_INFO *SocketContext, 632 | LspOperation operation, 633 | WSABUF *lpBuffers, 634 | DWORD dwBufferCount, 635 | LPWSAOVERLAPPED lpOverlapped, 636 | LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, 637 | LPWSATHREADID lpThreadId, 638 | int *lpErrno 639 | ); 640 | 641 | // This function handles the completion of an overlapped operation 642 | void CALLBACK 643 | IntermediateCompletionRoutine( 644 | DWORD dwError, 645 | DWORD cbTransferred, 646 | LPWSAOVERLAPPED lpOverlapped, 647 | DWORD dwFlags 648 | ); 649 | 650 | // If an overlapped operation fails inline, we must undo some state 651 | void 652 | UndoOverlappedOperation( 653 | SOCK_INFO *SocketContext, 654 | WSAOVERLAPPEDPLUS *ProviderOverlapped 655 | ); 656 | 657 | // Frees all cached WSAOVERLAPPEDPLUS structures when the LSP is unloaded 658 | void 659 | FreeOverlappedLookasideList( 660 | ); 661 | 662 | //////////////////////////////////////////////////////////////////////////////// 663 | // 664 | // Sockinfo.cpp prototypes 665 | // 666 | //////////////////////////////////////////////////////////////////////////////// 667 | 668 | SOCK_INFO * 669 | GetCallerSocket( 670 | PROVIDER *provider, 671 | SOCKET ProviderSocket 672 | ); 673 | 674 | // Allocates a SOCK_INFO structure, initializes it, and inserts into the provider list 675 | SOCK_INFO * 676 | CreateSockInfo( 677 | PROVIDER *Provider, 678 | SOCKET ProviderSocket, 679 | SOCK_INFO *Inherit, 680 | BOOL Insert, 681 | int *lpErrno 682 | ); 683 | 684 | // Looks up the socket context structure associated with the application socket 685 | SOCK_INFO * 686 | FindAndRefSocketContext( 687 | SOCKET s, 688 | int *err 689 | ); 690 | 691 | // Decrements the reference count on the given socket context object 692 | void 693 | DerefSocketContext( 694 | SOCK_INFO *context, 695 | int *err 696 | ); 697 | 698 | // Frees a previously allocated SOCK_INFO structure 699 | void 700 | FreeSockInfo( 701 | SOCK_INFO *info 702 | ); 703 | 704 | // Inserts the SOCK_INFO structure at the tail of the given provider's socket list 705 | void 706 | InsertSocketInfo( 707 | PROVIDER *provider, 708 | SOCK_INFO *sock 709 | ); 710 | 711 | // Removes the given SOCK_INFO structure from the provider's socket list 712 | void 713 | RemoveSocketInfo( 714 | PROVIDER *provider, 715 | SOCK_INFO *sock 716 | ); 717 | 718 | // Enters the SOCK_INFO structure's critical section preventing other threads from accessing it 719 | void 720 | AcquireSocketLock( 721 | SOCK_INFO *SockInfo 722 | ); 723 | 724 | // Releases the SOCK_INFO structure's critical section 725 | void 726 | ReleaseSocketLock( 727 | SOCK_INFO *SockInfo 728 | ); 729 | 730 | // Closes all the sockets and frees all resources associated with a provider 731 | void 732 | CloseAndFreeSocketInfo( 733 | PROVIDER *provider, 734 | BOOL processDetach 735 | ); 736 | 737 | 738 | //////////////////////////////////////////////////////////////////////////////// 739 | // 740 | // Extension.cpp prototypes 741 | // 742 | //////////////////////////////////////////////////////////////////////////////// 743 | 744 | BOOL PASCAL FAR 745 | ExtTransmitFile ( 746 | IN SOCKET hSocket, 747 | IN HANDLE hFile, 748 | IN DWORD nNumberOfBytesToWrite, 749 | IN DWORD nNumberOfBytesPerSend, 750 | IN LPOVERLAPPED lpOverlapped, 751 | IN LPTRANSMIT_FILE_BUFFERS lpTransmitBuffers, 752 | IN DWORD dwReserved 753 | ); 754 | 755 | BOOL PASCAL FAR 756 | ExtAcceptEx( 757 | IN SOCKET sListenSocket, 758 | IN SOCKET sAcceptSocket, 759 | IN PVOID lpOutputBuffer, 760 | IN DWORD dwReceiveDataLength, 761 | IN DWORD dwLocalAddressLength, 762 | IN DWORD dwRemoteAddressLength, 763 | OUT LPDWORD lpdwBytesReceived, 764 | IN LPOVERLAPPED lpOverlapped 765 | ); 766 | 767 | BOOL PASCAL FAR 768 | ExtConnectEx( 769 | IN SOCKET s, 770 | IN const struct sockaddr FAR *name, 771 | IN int namelen, 772 | IN PVOID lpSendBuffer OPTIONAL, 773 | IN DWORD dwSendDataLength, 774 | OUT LPDWORD lpdwBytesSent, 775 | IN LPOVERLAPPED lpOverlapped 776 | ); 777 | 778 | BOOL PASCAL FAR 779 | ExtTransmitPackets( 780 | SOCKET hSocket, 781 | LPTRANSMIT_PACKETS_ELEMENT lpPacketArray, 782 | DWORD nElementCount, 783 | DWORD nSendSize, 784 | LPOVERLAPPED lpOverlapped, 785 | DWORD dwFlags 786 | ); 787 | 788 | BOOL PASCAL FAR 789 | ExtDisconnectEx( 790 | IN SOCKET s, 791 | IN LPOVERLAPPED lpOverlapped, 792 | IN DWORD dwFlags, 793 | IN DWORD dwReserved 794 | ); 795 | 796 | INT PASCAL FAR 797 | ExtWSARecvMsg( 798 | IN SOCKET s, 799 | IN OUT LPWSAMSG lpMsg, 800 | OUT LPDWORD lpdwNumberOfBytesRecvd, 801 | IN LPWSAOVERLAPPED lpOverlapped, 802 | IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine 803 | ); 804 | 805 | INT PASCAL FAR 806 | ExtWSASendMsg( 807 | IN SOCKET s, 808 | IN WSASENDMSG *sendMsg, 809 | IN LPWSATHREADID lpThreadId, 810 | OUT LPINT lpErrno 811 | ); 812 | 813 | INT PASCAL FAR 814 | ExtWSAPoll( 815 | IN SOCKET s, 816 | IN WSAPOLLDATA *pollData, 817 | IN LPWSATHREADID lpThreadId, 818 | OUT LPINT lpErrno 819 | ); 820 | 821 | // Loads the given extension function from the lower provider 822 | BOOL 823 | LoadExtensionFunction( 824 | FARPROC **func, 825 | GUID ExtensionGuid, 826 | LPWSPIOCTL fnIoctl, 827 | SOCKET s 828 | ); 829 | 830 | //////////////////////////////////////////////////////////////////////////////// 831 | // 832 | // External variable definitions 833 | // 834 | //////////////////////////////////////////////////////////////////////////////// 835 | 836 | extern HINSTANCE gDllInstance; // Instance passed to DllMain 837 | extern CRITICAL_SECTION gCriticalSection, // Critical section for initialization and 838 | // socket list manipulation 839 | gOverlappedCS; // Used in overlapped IO handling 840 | extern INT gLayerCount; // Number of layered protocol entries for LSP 841 | extern PROVIDER *gBaseInfo; // Provider structures for each layered protocol 842 | extern HANDLE gAddContextEvent, // Event signaled whenver new socket context 843 | // is added to a PROVIDER 844 | gIocp; // Completion port handle 845 | extern WSPUPCALLTABLE gMainUpCallTable; // Upcall functions given to us by Winsock 846 | extern GUID gProviderGuid; // GUID of our dummy hidden entry 847 | 848 | #endif 849 | -------------------------------------------------------------------------------- /nonifslsp/lspguid.cpp: -------------------------------------------------------------------------------- 1 | // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 2 | // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 3 | // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 4 | // PARTICULAR PURPOSE. 5 | // 6 | // Copyright (C) 2004 Microsoft Corporation. All Rights Reserved. 7 | // 8 | // Module Name: lspguid.cpp 9 | // 10 | // Description: 11 | // 12 | // This module defines the GUID under which the LSP's hidden dummy 13 | // entry is to be installed under. This GUID must be hard coded in 14 | // this file so that the DLL instance can find itself in the Winsock 15 | // catalog. Once it finds the dummy hidden entry, it can then find 16 | // the layered protocol entries belonging to the LSP (since these 17 | // entries will reference the catalog ID of the hidden dummy entry). 18 | // 19 | // It is possible to create multiple LSPs by simply copying this project 20 | // to another directory, changing the GUID in this file, and changing 21 | // the DLL name. The LSP installer (instlsp.exe) can then install each 22 | // LSP with the -d flag which is the full path to each LSP to install. 23 | // 24 | // A new export has been added: GetLspGuid. This allows the LSP installer 25 | // to install an arbitrary LSP as long as it exports this function as the 26 | // installer needs to find the GUID to install the hidden dummy entry 27 | // with. The GUIDs for the layered protocol entries are generated on the 28 | // fly. 29 | // 30 | #include "lspdef.h" 31 | #include 32 | 33 | 34 | // 35 | // This is the hardcoded guid for our dummy (hidden) catalog entry 36 | // 37 | GUID gProviderGuid = { //c5fabbd0-9736-11d1-937f-00c04fad860d 38 | 0xc5fabbd0, 39 | 0x9736, 40 | 0x11d1, 41 | {0x93, 0x7f, 0x00, 0xc0, 0x4f, 0xad, 0x86, 0x0d} 42 | }; 43 | 44 | // 45 | // Function: GetLspGuid 46 | // 47 | // Description: 48 | // This function is exported by the DLL and it returns the GUID under 49 | // which the LSP (hidden) entry is to be installed. Note that this export 50 | // is not required to write an LSP but it is here to make the installer code 51 | // easier since the LSP DLL and the installer at least need to know the GUID 52 | // of the hidden dummy entry of the LSP. Using this export allows the installer 53 | // to query each LSP instance of its GUID so that it may install it. 54 | // 55 | void 56 | WSPAPI 57 | GetLspGuid( 58 | LPGUID lpGuid 59 | ) 60 | { 61 | memcpy( lpGuid, &gProviderGuid, sizeof( GUID ) ); 62 | } 63 | -------------------------------------------------------------------------------- /nonifslsp/nonifslsp.def: -------------------------------------------------------------------------------- 1 | LIBRARY nonifslsp 2 | EXPORTS 3 | WSPStartup 4 | GetLspGuid 5 | -------------------------------------------------------------------------------- /nonifslsp/sockinfo.cpp: -------------------------------------------------------------------------------- 1 | // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 2 | // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 3 | // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 4 | // PARTICULAR PURPOSE. 5 | // 6 | // Copyright (C) 2004 Microsoft Corporation. All Rights Reserved. 7 | // 8 | // Module Name: sockinfo.cpp 9 | // 10 | // Description: 11 | // 12 | // This sample illustrates how to develop a layered service provider that is 13 | // capable of counting all bytes transmitted through a TCP/IP socket. 14 | // 15 | // This file contains routines associated with the SOCK_INFO structure. This 16 | // structure maintains the mapping between the upper layer's socket and the 17 | // corresponding lower layer's socket. It also keeps track of the current 18 | // state and what operations are pending on the socket. The routines in this 19 | // file are for allocating, linked list management, etc. 20 | // 21 | 22 | #include "lspdef.h" 23 | 24 | // Lookup a socket context structure given the lower provider's socket 25 | SOCK_INFO * 26 | FindSockInfoFromProviderSocket( 27 | PROVIDER *provider, 28 | SOCKET socket 29 | ); 30 | 31 | // 32 | // Function: FindAndRefSocketContext 33 | // 34 | // Description: 35 | // This routine grabs the LSP critical seciton to lookup the socket context 36 | // and increase its ref count. Any operation on the socket context holds 37 | // the critical section so that it cannot be freed while its state changes. 38 | // 39 | SOCK_INFO * 40 | FindAndRefSocketContext( 41 | SOCKET s, 42 | int *lpErrno 43 | ) 44 | { 45 | SOCK_INFO *SocketContext = NULL; 46 | int ret; 47 | 48 | EnterCriticalSection(&gCriticalSection); 49 | 50 | ASSERT( gMainUpCallTable.lpWPUQuerySocketHandleContext ); 51 | 52 | ret = gMainUpCallTable.lpWPUQuerySocketHandleContext( 53 | s, 54 | (PDWORD_PTR) &SocketContext, 55 | lpErrno 56 | ); 57 | if ( SOCKET_ERROR == ret ) 58 | { 59 | dbgprint("FindAndRefSocketContext: WPUQuerySocketHandleContext failed: %d", *lpErrno); 60 | *lpErrno = WSAENOTSOCK; 61 | } 62 | else 63 | { 64 | InterlockedIncrement(&SocketContext->RefCount); 65 | } 66 | 67 | LeaveCriticalSection(&gCriticalSection); 68 | 69 | return SocketContext; 70 | } 71 | 72 | // 73 | // Function: DerefSocketContext 74 | // 75 | // Description: 76 | // This routine holds the LSP critical section and decrements the ref count 77 | // by one. It also checks if the socket has been closed while holding the 78 | // ref count. This can happen if two threads are accessing a socket simultaneously 79 | // and one calls closesocket. We don't want to remove the context from under 80 | // the second thread so it is marked as closing instead. 81 | // 82 | void 83 | DerefSocketContext( 84 | SOCK_INFO *context, 85 | int *lpErrno 86 | ) 87 | { 88 | LONG newval; 89 | int ret = NO_ERROR; 90 | 91 | EnterCriticalSection(&gCriticalSection); 92 | 93 | // Decrement the ref count and see if someone closed this socket (from another thread) 94 | newval = InterlockedDecrement(&context->RefCount); 95 | if ( ( 0 == newval ) && 96 | ( 0 == context->dwOutstandingAsync ) && 97 | ( TRUE == context->bClosing ) 98 | ) 99 | { 100 | ASSERT( gMainUpCallTable.lpWPUCloseSocketHandle ); 101 | 102 | // Socket has been closed so close the handle and free associated resources 103 | ret = gMainUpCallTable.lpWPUCloseSocketHandle(context->LayeredSocket, lpErrno); 104 | if ( SOCKET_ERROR == ret ) 105 | { 106 | dbgprint("DerefSocketContext: WPUCloseSocketHandle() failed: %d", *lpErrno); 107 | } 108 | 109 | context->LayeredSocket = INVALID_SOCKET; 110 | 111 | RemoveSocketInfo(context->Provider, context); 112 | 113 | dbgprint("Closing socket %d Bytes Sent [%lu] Bytes Recv [%lu]", 114 | context->LayeredSocket, context->BytesSent, context->BytesRecv); 115 | 116 | FreeSockInfo( context ); 117 | context = NULL; 118 | } 119 | 120 | LeaveCriticalSection( &gCriticalSection ); 121 | } 122 | 123 | // 124 | // Function: AcquireSocketLock 125 | // 126 | // Description: 127 | // This routine acquires the critical section which is a member of the 128 | // socket's context structure. This is held when modifying the socket 129 | // context outside of looking up the context (which is performed by 130 | // FindAndRefSocketContext). 131 | // 132 | void 133 | AcquireSocketLock( 134 | SOCK_INFO *SockInfo 135 | ) 136 | { 137 | EnterCriticalSection( &SockInfo->SockCritSec ); 138 | } 139 | 140 | // 141 | // Function: ReleaseSocketLock 142 | // 143 | // Description: 144 | // This routine releases the socket context critical section. 145 | // 146 | void 147 | ReleaseSocketLock( 148 | SOCK_INFO *SockInfo 149 | ) 150 | { 151 | LeaveCriticalSection( &SockInfo->SockCritSec ); 152 | } 153 | 154 | // 155 | // Function: CreateSockInfo 156 | // 157 | // Description: 158 | // Allocates a new socket info context structure and initializes the fields 159 | // except for the LayeredSocket field. The context must be allocated first, 160 | // then the layered socket is created (with the SOCK_INFO structure as the 161 | // context information), and then the LayeredSocket field is set. If 162 | // the Inherit context is provided, information is copied to the new socket 163 | // context structure (such as with WSPAccept). If the Insert flag is TRUE 164 | // then the context is automatically inserted into the list of sockets 165 | // for the given provider. If not then the caller must insert the context 166 | // (WSPAccept does this to ensure all fields of the context are valid 167 | // including LayeredSocket before insertion so that the async thread 168 | // handler will work properly). 169 | // 170 | SOCK_INFO * 171 | CreateSockInfo( 172 | PROVIDER *Provider, 173 | SOCKET ProviderSocket, 174 | SOCK_INFO *Inherit, 175 | BOOL Insert, 176 | int *lpErrno 177 | ) 178 | { 179 | SOCK_INFO *NewInfo = NULL; 180 | 181 | NewInfo = (SOCK_INFO *) LspAlloc( 182 | sizeof( SOCK_INFO ), 183 | lpErrno 184 | ); 185 | if ( NULL == NewInfo ) 186 | { 187 | dbgprint("HeapAlloc() failed: %d", GetLastError()); 188 | *lpErrno = WSAENOBUFS; 189 | goto cleanup; 190 | } 191 | 192 | // 193 | // Initialize the fields to default values 194 | // 195 | NewInfo->ProviderSocket = ProviderSocket; 196 | NewInfo->bClosing = FALSE; 197 | NewInfo->dwOutstandingAsync = 0; 198 | NewInfo->BytesRecv = 0; 199 | NewInfo->BytesSent = 0; 200 | NewInfo->Provider = Provider; 201 | NewInfo->hWnd = (Inherit ? Inherit->hWnd : 0); 202 | NewInfo->uMsg = (Inherit ? Inherit->uMsg : 0); 203 | 204 | __try 205 | { 206 | InitializeCriticalSection( &NewInfo->SockCritSec ); 207 | } 208 | __except( EXCEPTION_EXECUTE_HANDLER ) 209 | { 210 | *lpErrno = WSAENOBUFS; 211 | goto cleanup; 212 | } 213 | 214 | if ( TRUE == Insert ) 215 | InsertSocketInfo(Provider, NewInfo); 216 | 217 | return NewInfo; 218 | 219 | cleanup: 220 | 221 | if ( NULL != NewInfo ) 222 | LspFree( NewInfo ); 223 | 224 | return NULL; 225 | } 226 | 227 | // 228 | // Function: FreeSockInfo 229 | // 230 | // Description: 231 | // This routine frees the socket context structure. 232 | // 233 | void 234 | FreeSockInfo( 235 | SOCK_INFO *info 236 | ) 237 | { 238 | DeleteCriticalSection( &info->SockCritSec ); 239 | LspFree( info ); 240 | 241 | return; 242 | } 243 | 244 | // 245 | // Function: InsertSocketInfo 246 | // 247 | // Description: 248 | // We keep track of all the sockets created for a particulare provider. 249 | // This routine inserts a newly created socket (and its SOCK_INFO) into 250 | // the list. 251 | // 252 | void 253 | InsertSocketInfo( 254 | PROVIDER *provider, 255 | SOCK_INFO *sock 256 | ) 257 | { 258 | if ( ( NULL == provider ) || ( NULL == sock ) ) 259 | { 260 | dbgprint("InsertSocketInfo: PROVIDER or SOCK_INFO == NULL!"); 261 | goto cleanup; 262 | } 263 | 264 | EnterCriticalSection( &provider->ProviderCritSec ); 265 | 266 | InsertTailList( &provider->SocketList, &sock->Link ); 267 | 268 | LeaveCriticalSection( &provider->ProviderCritSec ); 269 | 270 | SetEvent( gAddContextEvent ); 271 | 272 | cleanup: 273 | 274 | return; 275 | } 276 | 277 | // 278 | // Function: RemoveSocketInfo 279 | // 280 | // Description: 281 | // This function removes a given SOCK_INFO structure from the referenced 282 | // provider. It doesn't free the structure, it just removes it from the 283 | // list. 284 | // 285 | void 286 | RemoveSocketInfo( 287 | PROVIDER *provider, 288 | SOCK_INFO *si 289 | ) 290 | { 291 | EnterCriticalSection( &provider->ProviderCritSec ); 292 | 293 | RemoveEntryList( &si->Link ); 294 | 295 | LeaveCriticalSection( &provider->ProviderCritSec ); 296 | 297 | return; 298 | } 299 | 300 | // 301 | // Function: CloseAndFreeSocketInfo 302 | // 303 | // Description: 304 | // Closes all sockets belonging to the specified provider and frees 305 | // the context information. If the lower provider socket is still 306 | // valid, set an abortive linger, and close the socket. 307 | // 308 | void 309 | CloseAndFreeSocketInfo( 310 | PROVIDER *provider, 311 | BOOL processDetach 312 | ) 313 | { 314 | LIST_ENTRY *entry = NULL; 315 | SOCK_INFO *si = NULL; 316 | struct linger linger; 317 | int Error, 318 | ret; 319 | 320 | ASSERT( provider ); 321 | 322 | linger.l_onoff = 1; 323 | linger.l_linger = 0; 324 | 325 | // Walk the list of sockets 326 | while ( !IsListEmpty( &provider->SocketList ) ) 327 | { 328 | entry = RemoveHeadList( &provider->SocketList ); 329 | 330 | ASSERT( entry ); 331 | 332 | si = CONTAINING_RECORD( entry, SOCK_INFO, Link ); 333 | 334 | if ( ( !processDetach ) || 335 | ( provider->NextProvider.ProtocolChain.ChainLen == BASE_PROTOCOL ) ) 336 | { 337 | 338 | ASSERT( provider->NextProcTable.lpWSPSetSockOpt ); 339 | 340 | // Set the abortive linger 341 | ret = provider->NextProcTable.lpWSPSetSockOpt( 342 | si->ProviderSocket, 343 | SOL_SOCKET, 344 | SO_LINGER, 345 | (char *) &linger, 346 | sizeof(linger), 347 | &Error 348 | ); 349 | if ( SOCKET_ERROR != ret ) 350 | { 351 | ASSERT( provider->NextProcTable.lpWSPCloseSocket ); 352 | 353 | // Close the lower provider socket 354 | ret = provider->NextProcTable.lpWSPCloseSocket( 355 | si->ProviderSocket, 356 | &Error 357 | ); 358 | if ( SOCKET_ERROR == ret ) 359 | { 360 | dbgprint("WSPCloseSocket() on handle %d failed: %d", si->ProviderSocket, Error); 361 | } 362 | #ifdef DEBUG 363 | else 364 | { 365 | dbgprint("Successfully closed socket %d", si->ProviderSocket); 366 | } 367 | #endif 368 | } 369 | #ifdef DEBUG 370 | else 371 | { 372 | dbgprint("WSPSetSockOpt(SO_LINGER) failed: %d", Error); 373 | } 374 | #endif 375 | } 376 | 377 | ASSERT( gMainUpCallTable.lpWPUCloseSocketHandle ); 378 | 379 | // Close the layered handle 380 | gMainUpCallTable.lpWPUCloseSocketHandle( 381 | si->LayeredSocket, 382 | &Error 383 | ); 384 | 385 | // Free the context structure 386 | FreeSockInfo( si ); 387 | } 388 | 389 | return; 390 | } 391 | 392 | // 393 | // Function: FindSockInfoFromProviderSocket 394 | // 395 | // Description: 396 | // This routine searches the list of socket context structures in a given 397 | // provider that matches the passed in provider (lower layer) socket. If found 398 | // the SOCK_INFO structure is returned; otherwise, NULL is returned. 399 | // 400 | SOCK_INFO * 401 | FindSockInfoFromProviderSocket( 402 | PROVIDER *provider, 403 | SOCKET socket 404 | ) 405 | { 406 | LIST_ENTRY *lptr = NULL; 407 | SOCK_INFO *si = NULL; 408 | 409 | ASSERT( provider ); 410 | 411 | if ( IsListEmpty( &provider->SocketList ) ) 412 | { 413 | dbgprint( "FindSockInfoFromProviderSocket: Empty SOCK_INFO list!" ); 414 | goto cleanup; 415 | } 416 | 417 | for(lptr = provider->SocketList.Flink ; lptr != &provider->SocketList ; lptr = lptr->Flink ) 418 | { 419 | si = CONTAINING_RECORD( lptr, SOCK_INFO, Link ); 420 | 421 | if ( socket == si->ProviderSocket ) 422 | break; 423 | 424 | si = NULL; 425 | } 426 | 427 | cleanup: 428 | 429 | return si; 430 | } 431 | 432 | // 433 | // Function: GetCallerSocket 434 | // 435 | // Description: 436 | // This function returns the SOCK_INFO structure for the given 437 | // provider socket. If provider is NULL then we'll search all 438 | // providers for the socket info. This routine is only used 439 | // in handling asynchronous window messages (WSAAsyncSelect) 440 | // since the window handler receives only the provider's socket 441 | // and we need to find the associated context structure. 442 | // 443 | SOCK_INFO * 444 | GetCallerSocket( 445 | PROVIDER *provider, 446 | SOCKET ProviderSock 447 | ) 448 | { 449 | SOCK_INFO *si = NULL; 450 | 451 | EnterCriticalSection( &gCriticalSection ); 452 | 453 | if ( NULL != provider ) 454 | { 455 | // If we know the provider just search its list of sockets 456 | si = FindSockInfoFromProviderSocket( provider, ProviderSock ); 457 | } 458 | else 459 | { 460 | // Don't know the provider so we must search all of them 461 | for(INT i=0; i < gLayerCount ;i++) 462 | { 463 | si = FindSockInfoFromProviderSocket( &gBaseInfo[ i ], ProviderSock ); 464 | if ( NULL != si ) 465 | break; 466 | } 467 | } 468 | 469 | LeaveCriticalSection( &gCriticalSection ); 470 | 471 | return si; 472 | } 473 | -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | INTRODUCTION 4 | 5 | This code sample illustrates a Winsock 2 layered service provider (LSP). 6 | An LSP is a method of inserting a layer between the Winsock 2 API and 7 | applications. This is achieved by creating a DLL which implements the 8 | entire set of Winsock provider functions. These functions begin with 9 | the three letters WSP. You can consult the Platform SDK documentation 10 | for the specifics on these functions. 11 | 12 | 13 | LAYERED SERVICE PROVIDERS 14 | 15 | There are two types of LSPs. The first type is known as a base provider. 16 | A base provider exposes access to a protocol (such as TCP/IP). Not only 17 | does it require a user mode DLL which implements the WSP functions but 18 | it also requires a kernel mode component which communicates with the 19 | underlying protocol driver (usually via the TDI interface - consult 20 | the DDK for TDI information). 21 | 22 | The other type of LSP is the type we mentioned in the first paragraph. 23 | It is a layer that lies above a base provider which is what this sample 24 | is. You can install this LSP above any installed base provider. Microsoft 25 | operating systems ship with a variety of base providers such as 26 | 'MSAFD Tcpip [TCP/IP]' (the TCP/IP provider). You can even install this 27 | LSP over other installed LSPs. 28 | 29 | 30 | INSTALLING THE LSP 31 | 32 | When you build the sample from the Samples\NetDS\WinSock\LSP folder, 33 | three files are generated. Instlsp.exe, ifslsp.dll and nonifslsp.dll. 34 | The first file is the installation program for installing the LSP into 35 | the Winsock catalog. The ifslsp.dll is an IFS LSP (LSP that creates sockets 36 | as installable file system (IFS) handles). The nonifslsp.dll is a NON-IFS LSP. 37 | The DLLs should be copied to %SYSTEMROOT%\System32 before installation. 38 | 39 | You need to determine which providers you want to install the LSP over 40 | before beginning. To get a list of the installed providers, execute 41 | the following command: 42 | 43 | C:\>instlsp.exe -p 44 | 1001 - MSAFD ATM AAL5 45 | 1002 - MSAFD Tcpip [TCP/IP] 46 | 1003 - MSAFD Tcpip [UDP/IP] 47 | 1004 - MSAFD Tcpip [RAW/IP] 48 | 1005 - RSVP UDP Service Provider 49 | 1006 - RSVP TCP Service Provider 50 | 1007 - MSAFD NetBIOS [\Device\NetBT_Tcpip_{74427F6E-EAED-4823-A03A-3759EBBB760B}] SEQPACKET 0 51 | 1008 - MSAFD NetBIOS [\Device\NetBT_Tcpip_{74427F6E-EAED-4823-A03A-3759EBBB760B}] DATAGRAM 0 52 | 1009 - MSAFD NetBIOS [\Device\NetBT_Tcpip_{E62BE309-3888-44C2-9A27-D981A3EB7EF5}] SEQPACKET 1 53 | 1010 - MSAFD NetBIOS [\Device\NetBT_Tcpip_{E62BE309-3888-44C2-9A27-D981A3EB7EF5}] DATAGRAM 1 54 | 1011 - MSAFD NetBIOS [\Device\NetBT_Tcpip_{A4BCF3EF-6D3E-46D0-93EF-6EBAF4E7F4FD}] SEQPACKET 2 55 | 1012 - MSAFD NetBIOS [\Device\NetBT_Tcpip_{A4BCF3EF-6D3E-46D0-93EF-6EBAF4E7F4FD}] DATAGRAM 2 56 | 1013 - MSAFD NetBIOS [\Device\NetBT_Tcpip_{4B4CCD46-9338-45DE-954C-3A379C17574A}] SEQPACKET 3 57 | 1014 - MSAFD NetBIOS [\Device\NetBT_Tcpip_{4B4CCD46-9338-45DE-954C-3A379C17574A}] DATAGRAM 3 58 | 1015 - MSAFD NetBIOS [\Device\NetBT_Tcpip_{F16E07AD-74F0-44E9-9731-DB72B9C4DD25}] SEQPACKET 4 59 | 1016 - MSAFD NetBIOS [\Device\NetBT_Tcpip_{F16E07AD-74F0-44E9-9731-DB72B9C4DD25}] DATAGRAM 4 60 | 1017 - MSAFD NetBIOS [\Device\NetBT_Tcpip_{14A9C4D0-76AC-4E14-BC60-C8DE25746F94}] SEQPACKET 5 61 | 1018 - MSAFD NetBIOS [\Device\NetBT_Tcpip_{14A9C4D0-76AC-4E14-BC60-C8DE25746F94}] DATAGRAM 5 62 | 63 | This prints the current Winsock catalog. The first number is the catalog 64 | ID followed by the string name of the corresponding Winsock provider. 65 | This particular machine is Windows 2000 with TCP/IP, TCP/IP QOS, NetBIOS, 66 | and ATM providers. You will need the catalog IDs of the layers you wish 67 | to install the LSP over. Note that if you should install the LSP over 68 | all the providers for a given protocol family. That is if you want to 69 | install over the TCP provider you should also install over the UDP 70 | and RAW providers (and probably the QOS providers as well). This is 71 | because there are certain applications (like Internet Explorer) which 72 | call the function select with SOCKET handles from different providers 73 | (UDP and TCP) which will fail if you're layered over only one of the 74 | these two providers. 75 | 76 | Once you've determined which providers you want to install over, you need 77 | to perform the installation of the LSP into the Winsock catalog with the 78 | -i option. You'll also need to specify a '-o ID' for each catalog entry 79 | you want to layer over as well as the qualified path to the LSP DLL with '-d '. 80 | For example, to layer over all the TCP/IP providers (except QOS) you would 81 | execute the following command: 82 | 83 | C:\>instlsp.exe -i -o 1002 -o 1003 -o 1004 -n "Foobar" -d c:\windows\system32\nonifslsp.dll 84 | LSP name is 'Foobar' 85 | Installing layer: Foobar over [MSAFD Tcpip [TCP/IP]] 86 | Installing layer: Foobar over [MSAFD Tcpip [UDP/IP]] 87 | Installing layer: Foobar over [MSAFD Tcpip [RAW/IP]] 88 | 89 | The '-n Name' option specifies the name of our LSP. You can verify the LSP 90 | installation by calling 'instlsp.exe -p'. 91 | 92 | C:\>instlsp -p 93 | 1042 - Foobar over [MSAFD Tcpip [TCP/IP]] 94 | 1043 - Foobar over [MSAFD Tcpip [UDP/IP]] 95 | 1044 - Foobar over [MSAFD Tcpip [RAW/IP]] 96 | 1001 - MSAFD ATM AAL5 97 | 1002 - MSAFD Tcpip [TCP/IP] 98 | 1003 - MSAFD Tcpip [UDP/IP] 99 | 1004 - MSAFD Tcpip [RAW/IP] 100 | 1005 - RSVP UDP Service Provider 101 | 1006 - RSVP TCP Service Provider 102 | 1007 - MSAFD NetBIOS [\Device\NetBT_Tcpip_{74427F6E-EAED-4823-A03A-3759EBBB760B}] SEQPACKET 0 103 | 1008 - MSAFD NetBIOS [\Device\NetBT_Tcpip_{74427F6E-EAED-4823-A03A-3759EBBB760B}] DATAGRAM 0 104 | 1009 - MSAFD NetBIOS [\Device\NetBT_Tcpip_{E62BE309-3888-44C2-9A27-D981A3EB7EF5}] SEQPACKET 1 105 | 1010 - MSAFD NetBIOS [\Device\NetBT_Tcpip_{E62BE309-3888-44C2-9A27-D981A3EB7EF5}] DATAGRAM 1 106 | 1011 - MSAFD NetBIOS [\Device\NetBT_Tcpip_{A4BCF3EF-6D3E-46D0-93EF-6EBAF4E7F4FD}] SEQPACKET 2 107 | 1012 - MSAFD NetBIOS [\Device\NetBT_Tcpip_{A4BCF3EF-6D3E-46D0-93EF-6EBAF4E7F4FD}] DATAGRAM 2 108 | 1013 - MSAFD NetBIOS [\Device\NetBT_Tcpip_{4B4CCD46-9338-45DE-954C-3A379C17574A}] SEQPACKET 3 109 | 1014 - MSAFD NetBIOS [\Device\NetBT_Tcpip_{4B4CCD46-9338-45DE-954C-3A379C17574A}] DATAGRAM 3 110 | 1015 - MSAFD NetBIOS [\Device\NetBT_Tcpip_{F16E07AD-74F0-44E9-9731-DB72B9C4DD25}] SEQPACKET 4 111 | 1016 - MSAFD NetBIOS [\Device\NetBT_Tcpip_{F16E07AD-74F0-44E9-9731-DB72B9C4DD25}] DATAGRAM 4 112 | 1017 - MSAFD NetBIOS [\Device\NetBT_Tcpip_{14A9C4D0-76AC-4E14-BC60-C8DE25746F94}] SEQPACKET 5 113 | 1018 - MSAFD NetBIOS [\Device\NetBT_Tcpip_{14A9C4D0-76AC-4E14-BC60-C8DE25746F94}] DATAGRAM 5 114 | 1041 - Foobar 115 | 116 | You'll notice that for each provider that we're layering over there is a 117 | new provider for our LSP (in this example, those entries with IDs 1042, 118 | 1042, and 1042). Additionally there is an extra entry entitled just "Foobar". 119 | This is the hidden (or dummy) entry for our LSP. It is required because 120 | before we can insert our LSP into another protocol's chain we must have 121 | a catalog ID and you don't get a catalog ID until you install a provider. 122 | So you install a dummy provider first to obtain a valid catalog ID which you 123 | then use in the protocol chains for the actual layered providers you install. 124 | 125 | As a shortcut, if you wish to install the LSP over every currently installed 126 | provider, specify -a instead of the individual '-o ID' flag, as in: 127 | 128 | C:\>instlsp -i -a -n "Foobar" -d c:\windows\system32\nonifslsp.dll 129 | 130 | INSTALLING THE IFS PROVIDER 131 | 132 | To install LSP as an IFS provider, run the installer and specify the '-h' switch (should be first 133 | parameter to instlsp.exe) as well as the qualified path to ifslsp.dll, as in: 134 | 135 | c:\>instlsp -h -i -o 1002 -o 1003 -o 1004 -n "IFSLSP" -d c:\windows\system32\ifslsp.dll 136 | 137 | INSTALLING AN LSP ON VISTA+ 138 | 139 | Since installing an LSP requires Administrator privileges and Vista introduces 140 | the notion of User Account Protection (UAP), installing an LSP on Vista 141 | requires a little extra work. A manifest (instlsp.exe.manifest) has been added 142 | to the installer code which directs Windows to prompt the non elevated user 143 | whether the application should be allowed to execute. If invoked from an 144 | elevated process, no prompt is given. 145 | 146 | For more information on UAP see: 147 | http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnlong/html/AccProtVista.asp 148 | 149 | Additionally, a new LSP install API has been added to Vista - WSCInstallProviderAndChains. 150 | This function performs all the necessary steps to install an LSP in one call. It also 151 | determines which entries need to be installed over based upon the providers supplied. 152 | That is if you tell instlsp.exe to install only over the TCP/IPv4 entry, it will also 153 | install over UDP/IPv4 and RAW/IPv4 since without those entries, IE (and other apps) 154 | would not operate correctly. 155 | 156 | INSTALLING AN LSP ON A 64-BIT OS 157 | 158 | When installing an LSP on a 64-bit OS, both a 64-bit and 32-bit LSP DLL are needed in 159 | order for 64-bit and 32-bit applications to access the LSPs functionality. Normally the 160 | 64-bit DLL is located in %SYSTEMROOT%\system32 and the 32-bit DLL is in %SYSTEMROOT%\SysWow64. 161 | The OS then automagically substitutes the correct location when applications load the DLL. 162 | However, if your application prefers to install its DLL under its own directory (which 163 | it should), there is not automagic redirection to the 32-bit DLL. Instead when installing 164 | your LSP, use the -d32 flag to specify the full path and filename to the 32-bit DLL. If this parameter is not specified, it is assumed that you are installing to the %SYSTEMROO%\System32 165 | directory. 166 | 167 | REMOVING THE LSP 168 | 169 | Removing the sample LSP is the simplest step. Just make the following call: 170 | 171 | C:\>instlsp.exe -r 1041 172 | 173 | This will remove the dummy entry as well as each layered entry. Note that 174 | with this sample, you cannot install the LSP more than once (that is you 175 | can't install the LSP over the IP providers and then try to install it 176 | over the newly created LSP entries). This is because the LSP sample uses 177 | a GUID to uniquely identify itself. If you attempt to install it twice, 178 | Winsock 2 catches the fact that a provider already exists with the given 179 | GUID and the installation will fail. You can however create a second 180 | instance of the DLL by changing the GUID and a few other resources. See 181 | lspguid.cpp and/or instlsp.cpp for more information. 182 | 183 | In the event that the Winsock catalog becomes so screwed up, you can 184 | remove all layered entries with the following call: 185 | 186 | C:\>instlsp.exe -f 187 | 188 | WINDOWS 9x AND WINDOWS ME INFORMATION 189 | 190 | For security reasons, the LSP's DLL location is fully pathed to 191 | %SYSTEMROOT%\system32 where it is installed. Additionally, the installer 192 | loads ws2_32.dll to determine whether WSCUpdateProvider is available. Both 193 | calls will fully path the DLL location which breaks under Windows 9x and 194 | ME. Please look at lspguid.cpp for information on compiling the sample for 195 | use under non NT based versions of Windows. 196 | 197 | FURTHER INFORMATION 198 | 199 | For additional information on layered service providers consult the Platform 200 | SDK documentation or the book "Network Programming for Microsoft Windows, 201 | Second Edition" by Anthony Jones and Jim Ohlund (ISBN 0735615799). 202 | --------------------------------------------------------------------------------