├── LICENSE ├── MakeFile ├── README.md ├── Sources ├── common.c ├── common.h ├── hash.c ├── hash.h ├── netmon.c ├── netmon.rc └── netmon_global.h /LICENSE: -------------------------------------------------------------------------------- 1 | Gangoo License 2 | Version 1.0, January 2024 3 | 4 | Terms and Conditions for use, reproduction, and distribution 5 | 1. Definitions 6 | “License” shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. 7 | 8 | “Licensor” shall mean the copyright owner or entity authorized by the copyright owner that is granting the License for uncommercial use. 9 | 10 | “Source” form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. 11 | 12 | "Commercial use” means use of the Licensed Material for purposes of generating income, or of advertising or publicity pertaining to the Licensed Material. 13 | 14 | "Commercial version source" The Source version for commercial use. 15 | 16 | "Commercial licensor" shall mean the entity authorized by the copyright owner that is granting the License of the Source/Commercial version source for Commercial Use. 17 | 18 | “Legal Entity” shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, “control” means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. 19 | 20 | “You” (or “Your”) shall mean an individual or Legal Entity exercising permissions granted by this License. 21 | 22 | “Object” form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. 23 | 24 | “Work” shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). 25 | 26 | “Derivative Works” shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. 27 | 28 | “Contribution” shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor/Commercial Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, “submitted” means any form of electronic, verbal, or written communication sent to the Licensor/Commercial Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor/Commercial Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as “Not a Contribution.” 29 | 30 | “Contributor” shall mean Licensor/Commercial Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor/Commercial Licensor and subsequently incorporated within the Work. 31 | 32 | 2. Commercial license 33 | For commercial use, please contact us: gangootech@hotmail.com 34 | 35 | 3. Grant of Copyright License 36 | Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 37 | 38 | 4. Grant of Patent License 39 | Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 40 | 41 | 5. Redistribution 42 | You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: 43 | 44 | (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and 45 | (b) You must cause any modified files to carry prominent notices stating that You changed the files; and 46 | (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and 47 | (d) If the Work includes a “NOTICE” text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. 48 | You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 49 | 50 | 6. Submission of Contributions 51 | Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor/Commercial Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor/Commercial Licensor regarding such Contributions. 52 | 53 | 7. Trademarks 54 | This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor/Commercial Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 55 | 56 | 8. Disclaimer of Warranty 57 | Unless required by applicable law or agreed to in writing, Licensor/Commercial Licensor provides the Work (and each Contributor provides its Contributions) on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 58 | 59 | 9. Limitation of Liability 60 | In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 61 | In the event of a breach of this agreement, the copyright holder reserves the right to terminate the user's rights to use the Software and reserves the right to take legal action. 62 | Use of the Software constitutes acceptance of all terms and conditions of this license agreement. 63 | 64 | 10. Accepting Warranty or Additional Liability 65 | While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. 66 | 67 | END OF TERMS AND CONDITIONS 68 | 69 | Unless required by applicable law or agreed to in writing, software 70 | distributed under the License is distributed on an "AS IS" BASIS, 71 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 72 | See the License for the specific language governing permissions and 73 | limitations under the License. -------------------------------------------------------------------------------- /MakeFile: -------------------------------------------------------------------------------- 1 | !IF 0 2 | 3 | Copyright (C) Microsoft Corporation, 1998 - 1998 4 | 5 | Module Name: 6 | 7 | makefile. 8 | 9 | !ENDIF 10 | 11 | # 12 | # DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source 13 | # file to this component. This file merely indirects to the real make file 14 | # that is shared by all the components of Windows NT 15 | # 16 | 17 | # 18 | # if building in a DDK environment 19 | # 20 | !IF defined(DDK_TARGET_OS) 21 | 22 | # 23 | # ensure that said build environment is at least Windows XP 24 | # 0x500 == Windows 2000 25 | # 0x501 == Windows XP 26 | # 0x502 == Windows .NET 27 | # 28 | ! IF defined(_NT_TARGET_VERSION) && $(_NT_TARGET_VERSION)>=0x501 29 | ! INCLUDE $(NTMAKEENV)\makefile.def 30 | ! ELSE 31 | ! message BUILDMSG: Warning : The sample "$(MAKEDIR)" is not valid for the current OS target. 32 | ! ENDIF 33 | 34 | !ELSE 35 | 36 | # 37 | # not a DDK environment, probably RAZZLE, so build 38 | # 39 | ! INCLUDE $(NTMAKEENV)\makefile.def 40 | 41 | !ENDIF 42 | 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # netmon 2 | network filter driver that control network sending speed, based on windows tdi framework. 3 | 4 | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- 5 | For the license of the Source (including but not limited to software source code, documentation source, and configuration files), please refer to the LICENSE file. 6 | Note: For commercial use you need to inquiry the commercial license, please refer to the detail in the LICENSE file. 7 | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- 8 | 9 | Prerequisites: 10 | 1. Visual Studio 2008 (or 2010,2015) 11 | 2. Windows driver development kit (WDK). 12 | 13 | The build steps: 14 | 1. Open visual studio 2008 (or 2010,2015). 15 | 2. Open netmon.sln. 16 | 3. Build this solution. 17 | 18 | Contact: 19 | Email: ganguotech@hotmail.com 20 | WeiXin: 651362705 21 | QQ group: 601169305 22 | QQ: 2146651351 23 | 24 | Donation: 25 | Alipay: shi.jijie@hotmail.com 26 | -------------------------------------------------------------------------------- /Sources: -------------------------------------------------------------------------------- 1 | TARGETNAME=netmon 2 | TARGETPATH=.\bin 3 | TARGETTYPE=DRIVER 4 | 5 | TARGETLIBS=$(DDK_LIB_PATH)\tdi.lib $(DDK_LIB_PATH)\nt.lib $(DDK_LIB_PATH)\ntdll.lib $(DDK_LIB_PATH)\kernel32.lib $(DDK_LIB_PATH)\wdm.lib 6 | 7 | INCLUDES=$(INCLUDES) 8 | 9 | SOURCES=netmon.c \ 10 | hash.c \ 11 | common.c \ 12 | netmon.rc -------------------------------------------------------------------------------- /common.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2024 JiJie.Shi. 3 | * 4 | * This file is part of netmon. 5 | * Licensed under the Gangoo License, Version 1.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | 15 | #include "common.h" 16 | 17 | PVOID AllocZeroPoolWithTag( POOL_TYPE Type, size_t Size ) 18 | { 19 | PVOID pPool; 20 | 21 | pPool = ExAllocatePoolWithTag( Type, Size, TDI_FILTER_POOL_TAG ); 22 | 23 | if( pPool ) 24 | RtlZeroMemory( pPool, Size ); 25 | 26 | return pPool; 27 | } 28 | -------------------------------------------------------------------------------- /common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2024 JiJie.Shi. 3 | * 4 | * This file is part of netmon. 5 | * Licensed under the Gangoo License, Version 1.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | 15 | #ifndef __COMMON_H__ 16 | #define __COMMON_H__ 17 | 18 | #include 19 | 20 | #define TDI_FILTER_POOL_TAG 0x74303633 21 | 22 | PVOID AllocZeroPoolWithTag( POOL_TYPE Type, size_t Size ); 23 | 24 | __inline VOID INTERLOCKED_COMPARE_EXCHANGE64( LARGE_INTEGER *pOriginalValue, LARGE_INTEGER NewValue ) 25 | { 26 | LARGE_INTEGER OriginalValue; 27 | 28 | ASSERT( NULL != pOriginalValue ); 29 | 30 | __asm 31 | { 32 | ATOM_CMPXCHG: 33 | mov esi, dword ptr [ pOriginalValue ]; 34 | mov ebx, dword ptr [ esi ]; 35 | mov ecx, dword ptr [ esi + 4 ]; 36 | 37 | mov dword ptr [ OriginalValue ], ebx; 38 | mov dword ptr [ OriginalValue + 4 ], ecx; 39 | 40 | mov eax, ebx; 41 | mov edx, ecx; 42 | 43 | mov ebx, dword ptr [ NewValue ]; 44 | mov ecx, dword ptr [ NewValue + 4 ]; 45 | 46 | mov edi, esi; 47 | 48 | lock cmpxchg8b [ edi ]; 49 | 50 | cmp eax, dword ptr [ OriginalValue ]; 51 | jnz ATOM_CMPXCHG; 52 | 53 | cmp edx, dword ptr [ OriginalValue + 4 ]; 54 | jnz ATOM_CMPXCHG; 55 | } 56 | return; 57 | } 58 | 59 | __inline VOID INTERLOCKED_HALF_COMPARE_EXCHANGE_ADD64( LARGE_INTEGER *pOriginalValue, LARGE_INTEGER AddValue ) 60 | { 61 | LARGE_INTEGER OriginalValue; 62 | 63 | ASSERT( NULL != pOriginalValue ); 64 | 65 | __asm 66 | { 67 | ATOM_CMPXCHG: 68 | mov esi, dword ptr [ pOriginalValue ]; 69 | mov ebx, dword ptr [ esi ]; 70 | mov ecx, dword ptr [ esi + 4 ]; 71 | 72 | mov dword ptr [ OriginalValue ], ebx; 73 | mov dword ptr [ OriginalValue + 4 ], ecx; 74 | 75 | mov eax, ebx; 76 | mov edx, ecx; 77 | 78 | add ebx, dword ptr [ AddValue ]; 79 | adc ecx, dword ptr [ AddValue + 4 ]; 80 | 81 | mov edi, esi; 82 | 83 | lock cmpxchg8b [ edi ]; 84 | 85 | cmp edx, dword ptr [ OriginalValue + 4 ]; 86 | jnz ATOM_CMPXCHG; 87 | } 88 | return; 89 | } 90 | 91 | __inline VOID INTERLOCKED_COMPARE_EXCHANGE_ADD64( LARGE_INTEGER *pOriginalValue, LARGE_INTEGER AddValue ) 92 | { 93 | LARGE_INTEGER OriginalValue; 94 | 95 | ASSERT( NULL != pOriginalValue ); 96 | 97 | __asm 98 | { 99 | ATOM_CMPXCHG: 100 | mov esi, dword ptr [ pOriginalValue ]; 101 | mov ebx, dword ptr [ esi ]; 102 | mov ecx, dword ptr [ esi + 4 ]; 103 | 104 | mov dword ptr [ OriginalValue ], ebx; 105 | mov dword ptr [ OriginalValue + 4 ], ecx; 106 | 107 | mov eax, ebx; 108 | mov edx, ecx; 109 | 110 | add ebx, dword ptr [ AddValue ]; 111 | adc ecx, dword ptr [ AddValue + 4 ]; 112 | 113 | mov edi, esi; 114 | 115 | lock cmpxchg8b [ edi ]; 116 | 117 | cmp eax, dword ptr [ OriginalValue ]; 118 | jnz ATOM_CMPXCHG; 119 | 120 | cmp edx, dword ptr [ OriginalValue + 4 ]; 121 | jnz ATOM_CMPXCHG; 122 | } 123 | return; 124 | } 125 | 126 | #endif -------------------------------------------------------------------------------- /hash.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2024 JiJie.Shi. 3 | * 4 | * This file is part of netmon. 5 | * Licensed under the Gangoo License, Version 1.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | 15 | #include 16 | #include "common.h" 17 | #include 18 | #include "netmon_global.h" 19 | #include "hash.h" 20 | 21 | dword modulo_hash( hash_key key, dword table_size ) 22 | { 23 | ASSERT( 0 < table_size ); 24 | 25 | return key.low_part % table_size; 26 | } 27 | 28 | int hash_item_is_empty( hash_item *item ) 29 | { 30 | return ( 0 == item->key.high_part && 0 == item->key.low_part ); 31 | } 32 | 33 | #define compare_key( key1, key2 ) ( key1.high_part == key2.high_part && key1.low_part == key2.low_part ) 34 | 35 | int find_item_in_list( hash_item *list, hash_key key, hash_item **prev_item, hash_item **item ) 36 | { 37 | hash_item *__prev_item; 38 | hash_item *locate_item; 39 | 40 | ASSERT( NULL != item ); 41 | 42 | __prev_item = NULL; 43 | locate_item = list; 44 | 45 | for( ; ; ) 46 | { 47 | if( NULL == locate_item ) 48 | { 49 | break; 50 | } 51 | 52 | if( compare_key( locate_item->key, key ) ) 53 | { 54 | if( NULL != prev_item ) 55 | *prev_item = __prev_item; 56 | 57 | if( NULL != item ) 58 | *item = locate_item; 59 | 60 | return 0; 61 | } 62 | 63 | __prev_item = locate_item; 64 | locate_item = locate_item->next_link; 65 | } 66 | 67 | if( NULL != prev_item ) 68 | *prev_item = NULL; 69 | 70 | if( NULL != item ) 71 | *item = NULL; 72 | return -1; 73 | } 74 | 75 | int locate_hash_item( hash_table *table, hash_key key, hash_item **item ) 76 | { 77 | dword index; 78 | hash_item *finded_item; 79 | 80 | ASSERT( NULL != table ); 81 | ASSERT( NULL != item ); 82 | 83 | index = modulo_hash( key, table->size ); 84 | 85 | finded_item = &table->items[ index ]; 86 | 87 | if( FALSE == hash_item_is_empty( finded_item ) ) 88 | { 89 | *item = NULL; 90 | return -1; 91 | } 92 | 93 | if( TRUE == compare_key( finded_item->key, key ) ) 94 | { 95 | *item = finded_item; 96 | return 0; 97 | } 98 | 99 | if( NULL == finded_item->next_link ) 100 | { 101 | *item = NULL; 102 | return -1; 103 | } 104 | 105 | return find_item_in_list( finded_item->next_link, key, NULL, item ); 106 | } 107 | 108 | int add_hash_item( hash_table *table, hash_key key, hash_value val ) 109 | { 110 | int ret; 111 | dword index; 112 | hash_item *item; 113 | hash_item *new_item; 114 | 115 | ASSERT( NULL != table ); 116 | 117 | index = modulo_hash( key, table->size ); 118 | 119 | item = &table->items[ index ]; 120 | 121 | if( hash_item_is_empty( item ) ) 122 | { 123 | item->key = key; 124 | item->value = val; 125 | item->next_item = table->first_hash_item; 126 | item->next_link = NULL; 127 | table->first_hash_item = item; 128 | table->item_count += 1; 129 | DebugPrintEx( IRP_CANCEL_INFO, "hash table item count is %d key is 0x%0.8x\n", 130 | table->item_count, 131 | key.low_part ); 132 | return 0; 133 | } 134 | else 135 | { 136 | if( TRUE == compare_key( item->key, key ) ) 137 | { 138 | return HASH_KEY_EXISTED; 139 | } 140 | } 141 | 142 | if( NULL != item->next_link ) 143 | { 144 | ret = find_item_in_list( item->next_link, key, NULL, NULL ); 145 | if( 0 == ret ) 146 | { 147 | return HASH_KEY_EXISTED; 148 | } 149 | } 150 | 151 | new_item = ( hash_item* )AllocZeroPoolWithTag( NonPagedPool, sizeof( hash_item ) ); 152 | if( NULL == new_item ) 153 | { 154 | return STATUS_INSUFFICIENT_RESOURCES; 155 | } 156 | 157 | new_item->key = key; 158 | new_item->value = val; 159 | new_item->next_item = item->next_item; 160 | new_item->next_link = item->next_link; 161 | item->next_link = new_item; 162 | table->item_count += 1; 163 | DebugPrintEx( IRP_CANCEL_INFO, "hash table item count is %d key is 0x%0.8x\n", 164 | table->item_count, 165 | key.low_part ); 166 | 167 | return 0; 168 | } 169 | 170 | hash_item *find_prev_item( hash_table *table, hash_item *item ) 171 | { 172 | hash_item *finded_item; 173 | 174 | ASSERT( NULL != table ); 175 | ASSERT( NULL != item ); 176 | ASSERT( NULL != table->header ); 177 | 178 | finded_item = table->header; 179 | for( ; ; ) 180 | { 181 | if( finded_item == NULL ) 182 | { 183 | ASSERT( FALSE ); 184 | return NULL; 185 | } 186 | 187 | if( finded_item->next_item == item ) 188 | { 189 | return finded_item; 190 | } 191 | 192 | finded_item = finded_item->next_item; 193 | } 194 | return NULL; 195 | } 196 | 197 | int del_hash_item( hash_table *table, hash_key key, hash_value *value ) 198 | { 199 | int ret; 200 | dword index; 201 | hash_item *item; 202 | hash_item *finded_item; 203 | hash_item *prev_item; 204 | 205 | ASSERT( NULL != table ); 206 | 207 | index = modulo_hash( key, table->size ); 208 | 209 | item = &table->items[ index ]; 210 | 211 | if( NULL != value ) 212 | { 213 | *value = NULL; 214 | } 215 | 216 | if( compare_key( item->key, key ) ) 217 | { 218 | prev_item = find_prev_item( table, item ); 219 | 220 | if( NULL == prev_item ) 221 | { 222 | ASSERT( FALSE ); 223 | return -1; 224 | } 225 | 226 | prev_item->next_item = item->next_item; 227 | 228 | table->item_count -= 1; 229 | DebugPrintEx( IRP_CANCEL_INFO, "hash table item count is %d key is 0x%0.8x\n", 230 | table->item_count, 231 | key.low_part ); 232 | item->key.high_part = 0; 233 | item->key.low_part = 0; 234 | item->next_item = NULL; 235 | if( NULL != value ) 236 | { 237 | *value = item->value; 238 | } 239 | item->value = 0; 240 | 241 | return 0; 242 | } 243 | 244 | if( NULL == item->next_link ) 245 | { 246 | return -1; 247 | } 248 | 249 | ret = find_item_in_list( item->next_link, key, &prev_item, &finded_item ); 250 | if( 0 > ret ) 251 | { 252 | return ret; 253 | } 254 | 255 | if( NULL != prev_item ) 256 | { 257 | prev_item->next_link = finded_item->next_link; 258 | } 259 | 260 | table->item_count -= 1; 261 | DebugPrintEx( IRP_CANCEL_INFO, "hash table item count is %d key is 0x%0.8x\n", 262 | table->item_count, 263 | key.low_part ); 264 | 265 | if( NULL != value ) 266 | { 267 | *value = finded_item->value; 268 | } 269 | ExFreePoolWithTag( finded_item, 0 ); 270 | 271 | return 0; 272 | } 273 | 274 | int get_hash_value( hash_table *table, hash_key key, hash_value *value ) 275 | { 276 | int ret; 277 | hash_item *item; 278 | 279 | ret = locate_hash_item( table, key, &item ); 280 | 281 | if( 0 > ret ) 282 | { 283 | *value = NULL; 284 | return ret; 285 | } 286 | 287 | *value = item->value; 288 | 289 | return 0; 290 | } 291 | 292 | int init_hash_table( hash_table *table, dword size ) 293 | { 294 | #define ADD_HEADER_SIZE( size ) ( size + 1 ) 295 | hash_item *__header; 296 | ASSERT( NULL != table ); 297 | 298 | __header = ( hash_item* )AllocZeroPoolWithTag( NonPagedPool, sizeof( hash_item ) * ADD_HEADER_SIZE( size ) ); 299 | 300 | if( NULL == __header ) 301 | { 302 | table->header = NULL; 303 | table->items = NULL; 304 | table->size = 0; 305 | return STATUS_INSUFFICIENT_RESOURCES; 306 | } 307 | 308 | memset( __header, 0, sizeof( hash_item ) * ADD_HEADER_SIZE( size ) ); 309 | 310 | table->header = __header; 311 | table->items = &__header[ 1 ]; 312 | table->size = size; 313 | table->item_count = 0; 314 | return 0; 315 | } 316 | 317 | hash_item* get_next_hash_item( hash_item *item ) 318 | { 319 | ASSERT( NULL != item ); 320 | if( NULL != item->next_link ) 321 | { 322 | return item->next_link; 323 | } 324 | 325 | return item->next_item; 326 | } 327 | 328 | void destroy_hash_table( hash_table *table, destroy_hash_value des_func, dword param ) 329 | { 330 | hash_item *item_list; 331 | hash_item *item; 332 | //hash_item *next_item; 333 | hash_item *next_list; 334 | 335 | ASSERT( NULL != table ); 336 | 337 | item = table->header->next_item; 338 | 339 | for( ; ; ) 340 | { 341 | if( NULL == item ) 342 | break; 343 | 344 | if( FALSE == hash_item_is_empty( item ) ) 345 | { 346 | if( NULL != des_func ) 347 | { 348 | des_func( item->value, param ); 349 | } 350 | } 351 | 352 | item_list = item->next_link; 353 | 354 | for( ; ; ) 355 | { 356 | if( NULL == item_list ) 357 | { 358 | break; 359 | } 360 | 361 | next_list = item_list->next_link; 362 | 363 | if( NULL != des_func ) 364 | { 365 | des_func( item_list->value, param ); 366 | } 367 | 368 | ExFreePoolWithTag( item_list, 0 ); 369 | item_list = next_list; 370 | } 371 | 372 | item = item->next_item; 373 | } 374 | 375 | ExFreePoolWithTag( table->header, 0 ); 376 | } 377 | 378 | 379 | uint64 make_hash_key( dword higher, dword lower ) 380 | { 381 | hash_key key; 382 | key.high_part = higher; 383 | key.low_part = lower; 384 | return key.quad_part; 385 | } 386 | 387 | void* get_next_item_value( void *pos_record, hash_table *table, hash_value *value ) 388 | { 389 | hash_item *item; 390 | 391 | ASSERT( NULL != table ); 392 | 393 | if( NULL == pos_record ) 394 | { 395 | item = table->first_hash_item; 396 | } 397 | else 398 | { 399 | item = ( hash_item* )pos_record; 400 | item = get_next_hash_item( item ); 401 | } 402 | 403 | if( NULL == item ) 404 | { 405 | *value = HASH_NULL_VALUE; 406 | return NULL; 407 | } 408 | 409 | *value = item->value; 410 | return ( void* )item; 411 | } 412 | 413 | int hash_is_empty( hash_table *table ) 414 | { 415 | if( NULL == table->header->next_item ) 416 | { 417 | return 0; 418 | } 419 | 420 | return -1; 421 | } -------------------------------------------------------------------------------- /hash.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2024 JiJie.Shi. 3 | * 4 | * This file is part of netmon. 5 | * Licensed under the Gangoo License, Version 1.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | 15 | #ifndef __BALANCE_PARALLEL_HASH_H__ 16 | #define __BALANCE_PARALLEL_HASH_H__ 17 | 18 | typedef unsigned __int64 uint64; 19 | typedef unsigned long dword; 20 | #define HASH_KEY_EXISTED -11 21 | typedef struct __long_int 22 | { 23 | union 24 | { 25 | struct 26 | { 27 | dword low_part; 28 | dword high_part; 29 | }; 30 | 31 | uint64 quad_part; 32 | }; 33 | } long_int; 34 | 35 | typedef long_int hash_key; 36 | typedef void *hash_value; 37 | #define HASH_NULL_VALUE NULL 38 | typedef struct __hash_item 39 | { 40 | hash_key key; 41 | hash_value value; 42 | 43 | struct __hash_item *next_item; 44 | struct __hash_item *next_link; 45 | 46 | } hash_item; 47 | 48 | typedef struct __hash_table 49 | { 50 | #define first_hash_item header->next_item 51 | hash_item *header; 52 | hash_item *items; 53 | dword size; 54 | dword item_count; 55 | } hash_table; 56 | 57 | typedef int ( *hash_val_comp )( hash_val, hash_val ); 58 | typedef void ( *destroy_hash_value )( hash_value *value, dword param ); 59 | 60 | #define hash_table_inited( table ) ( NULL != ( table )->header ) 61 | #define compare_key( key1, key2 ) ( key1.high_part == key2.high_part && key1.low_part == key2.low_part ) 62 | 63 | dword modulo_hash( hash_key key, dword table_size ); 64 | int hash_item_is_empty( hash_item *item ); 65 | int find_item_in_list( hash_item *list, hash_key key, hash_item **prev_item, hash_item **item ); 66 | int locate_hash_item( hash_table *table, hash_key key, hash_item **item ); 67 | int add_hash_item( hash_table *table, hash_key key, hash_value val ); 68 | hash_item *find_prev_item( hash_table *table, hash_item *item ); 69 | int del_hash_item( hash_table *table, hash_key key, hash_value *value ); 70 | int get_hash_value( hash_table *table, hash_key key, hash_value *value ); 71 | int init_hash_table( hash_table *table, dword size ); 72 | hash_item* get_next_hash_item( hash_item *item ); 73 | void destroy_hash_table( hash_table *table, destroy_hash_value des_func, dword param ); 74 | uint64 make_hash_key( dword higher, dword lower ); 75 | void* get_next_item_value( void *pos_record, hash_table *table, hash_value *value ); 76 | int hash_is_empty( hash_table *table ); 77 | 78 | #endif //__BALANCE_PARALLEL_HASH_H__ -------------------------------------------------------------------------------- /netmon.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2024 JiJie.Shi. 3 | * 4 | * This file is part of netmon. 5 | * Licensed under the Gangoo License, Version 1.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | 15 | #include 16 | #include "common.h" 17 | #include 18 | #include "hash.h" 19 | #include "netmon_global.h" 20 | 21 | extern volatile KSYSTEM_TIME KeTickCount; 22 | extern POBJECT_TYPE *IoFileObjectType; 23 | 24 | DWORD TDI_FILTER_DRIVER_VERSION[] = { 1, 0, 0, 0006 }; 25 | 26 | #define UDP_DEVICE_NAME L"\\Device\\Udp" 27 | #define TCP_DEVICE_NAME L"\\Device\\Tcp" 28 | 29 | #define TDI_FILTER_DEVICE_DOS_NAME L"\\DosDevices\\BCTdiFilter" 30 | #define TDI_FILTER_DEVICE_NAME L"\\Device\\BCTdiFilter" 31 | 32 | #define DOS_DEVICE_NAME_PREFIX L"\\??\\" 33 | 34 | #define TICK_COUNT_RECORD_INIT_VAL 0xBB40E64E 35 | #define TICK_COUNT_RECORD_NOT_INIT_VAL 0x44BF19B1 36 | 37 | #define DEL_EVENT_WRAP 1 38 | #define GET_EVENT_WRAP 2 39 | 40 | #define MASTER_IRP_HASH_TABLE_SIZE 500 41 | 42 | #ifdef ALLOC_PRAGMA 43 | #pragma alloc_text (INIT, DriverEntry) 44 | #endif 45 | 46 | PKTHREAD ThreadUpdateConfig = NULL; 47 | PKTHREAD ThreadProcessIrp = NULL; 48 | 49 | PDEVICE_OBJECT g_FilterDeviceForDeviceTcp = NULL; 50 | PDEVICE_OBJECT g_FilterDeviceForDeviceUdp = NULL; 51 | PDEVICE_OBJECT g_DevTdiFilter = NULL; 52 | 53 | BOOL g_bThreadsRunning = FALSE; 54 | BOOL g_bBeginStartThreads = FALSE; 55 | 56 | DWORD g_dwTickCountFactor = TICK_COUNT_RECORD_INIT_VAL; 57 | DWORD g_dwTickCountFactorNot = TICK_COUNT_RECORD_NOT_INIT_VAL; 58 | 59 | \ 60 | hash_table g_MasterIrpHash; 61 | 62 | BOOL g_bFiltering = TRUE; 63 | 64 | BOOL g_bThreadUpdateConfigStop = FALSE; 65 | BOOL g_bThreadIrpProcessStop = FALSE; 66 | 67 | LARGE_INTEGER Interval; 68 | 69 | LARGE_INTEGER g_SendingDelayTime = { 0 }; 70 | LARGE_INTEGER g_TimerElapse = { 0 }; 71 | LARGE_INTEGER g_ThreadWaitConfigProcTime = { 0 }; 72 | LARGE_INTEGER g_WaitNewIistItemTime = { 0 }; 73 | 74 | LARGE_INTEGER g_AllSendedDataSize; 75 | LARGE_INTEGER g_AllRecvedDataSize; 76 | 77 | KSPIN_LOCK g_SpLockProcessNetWorkTrafficInfo; 78 | KSPIN_LOCK g_SpLockTdiEventHandlerInfo; 79 | 80 | KEVENT g_EventProcessInformationAdded; 81 | KEVENT g_EventIrpListAdded; 82 | KEVENT g_EventCompletion; 83 | 84 | ERESOURCE g_SyncResource; 85 | 86 | NPAGED_LOOKASIDE_LIST g_CompletionWrapList; 87 | 88 | LIST_ENTRY g_TdiEventHandlerInfoList; 89 | LIST_ENTRY g_ProcessIoInfoList; 90 | LIST_ENTRY g_ProcessInformationList; 91 | 92 | BOOL IsDriverDevice( PDEVICE_OBJECT pDeviceObject ); 93 | 94 | NTSTATUS TdiFilterChainedRecvHandler( 95 | IN PVOID TdiEventContext, 96 | IN CONNECTION_CONTEXT ConnectionContext, 97 | IN ULONG ReceiveFlags, 98 | IN ULONG ReceiveLength, 99 | IN ULONG StartingOffset, 100 | IN PMDL Tsdu, 101 | IN PVOID TsduDescriptor 102 | ); 103 | 104 | NTSTATUS TdiFilterRecvDatagramEventHandler( 105 | IN PVOID TdiEventContext, 106 | IN LONG SourceAddressLength, 107 | IN PVOID SourceAddress, 108 | IN LONG OptionsLength, 109 | IN PVOID Options, 110 | IN ULONG ReceiveDatagramFlags, 111 | IN ULONG BytesIndicated, 112 | IN ULONG BytesAvailable, 113 | OUT ULONG *BytesTaken, 114 | IN PVOID Tsdu, 115 | OUT PIRP *IoRequestPacket 116 | ); 117 | 118 | DWORD dwBPFlag = 0; 119 | DWORD dwPrintFlags = IRP_CANCEL_INFO |DRIVER_ENTRY_INFO | DRIVER_UNLOAD_INFO; 120 | 121 | BOOL g_StopWaitCompletion = FALSE; 122 | INT32 g_CompletionIrpCount = 0; 123 | PKTHREAD g_ThreadWaitCompletion = NULL; 124 | PIRP DequeueIrp( PLIST_ENTRY pListHead, PKSPIN_LOCK SpLock ); 125 | VOID TdiFilterCancel( 126 | IN PDEVICE_OBJECT DeviceObject, 127 | IN PIRP Irp 128 | ); 129 | VOID ThreadWaitCompletion( PVOID pParam ); 130 | NTSTATUS RestoreEventHandler( PTDI_EVENT_HANDLER_WRAP pEventHandlerWrap ); 131 | DWORD ReleaseAllEventHandlerWrap(); 132 | VOID ReleaseAllProcessNetWorkTrafficInfo(); 133 | NTSTATUS TdiFilterCompletion( PDEVICE_OBJECT pDeviceObject, PIRP pIrp, LPVOID pContext ); 134 | NTSTATUS TdiFilterSyncSendProcess( PROCESS_NETWORK_TRAFFIC *pProcessNetWorkTrafficInfo, 135 | PDEVICE_OBJECT pDeviceObject, 136 | PIRP pIrp ); 137 | VOID ThreadSendingSpeedControl( PVOID pParam ); 138 | VOID TimerDpcProcess( PKDPC pDpc, PVOID pEProcess, PVOID SystemArgument1 , PVOID SystemArgument2 ); 139 | VOID DeleteProcessIoInfo( DWORD dwParentId, DWORD dwProcessId, BOOL bCreate ); 140 | NTSTATUS GetAllProcessesIoInformation( LPVOID *pOutput, DWORD dwInputBuffLength, DWORD *pAllInfoLength ); 141 | NTSTATUS GetAllProcessesInformation( PPROCESS_INFORMATION_RECORD pAllProcessInfomation, DWORD dwBufferLength, DWORD *pAllInfoLength ); 142 | NTSTATUS ReleaseAllProcessesInformation(); 143 | VOID DeleteEventWrap( PTDI_EVENT_HANDLER_LIST pTdiEventHandlerList ); 144 | VOID UpdateEventHandlerWrap( PPROCESS_NETWORK_TRAFFIC pProcessNetWorkTrafficInfo, 145 | PEPROCESS pEProcess, 146 | PDEVICE_OBJECT pDeviceObject, 147 | PFILE_OBJECT pFileObject, 148 | DWORD dwEventType, 149 | PVOID pEventHandler, 150 | PVOID pEventContext, 151 | PTDI_EVENT_HANDLER_LIST *ppEventHandlerWrap, 152 | DWORD dwFlags ); 153 | VOID ThreadUpdateProcessIoState( PVOID pParam ); 154 | 155 | NTSTATUS TdiFilterRecvEventHandler( IN PVOID TdiEventContext, 156 | IN CONNECTION_CONTEXT ConnectionContext, 157 | IN ULONG ReceiveFlags, 158 | IN ULONG BytesIndicated, 159 | IN ULONG BytesAvailable, 160 | OUT ULONG *BytesTaken, 161 | IN PVOID Tsdu, 162 | OUT PIRP *IoRequestPacket 163 | ); 164 | VOID TdiFilterUnload( PDRIVER_OBJECT pDriverObject ); 165 | NTSTATUS TdiFilterCleanUp(PDEVICE_OBJECT DeviceObject, PIRP pIrp ); 166 | NTSTATUS TdiFilterDefaultIrpProcess( PDEVICE_OBJECT pDeviceObject, PIRP pIrp); 167 | NTSTATUS StartWorkThreadManageProcessInfo( 168 | PROCESS_INFORMATION_RECORD *pProcessInformationFind, 169 | DWORD dwInputBufferLength 170 | ); 171 | NTSTATUS TdiFilterInternalIoControl( PDEVICE_OBJECT pDeviceObject, PIRP pIrp ); 172 | NTSTATUS TdiFilterIoControl( PDEVICE_OBJECT pDeviceObject, PIRP pIrp ); 173 | NTSTATUS DriverEntry( PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath ); 174 | NTSTATUS AttachToTdiDevice( PDRIVER_OBJECT DriverObject, PUNICODE_STRING TargetDeviceName, PDEVICE_OBJECT *DeviceObject ); 175 | PPROCESS_NETWORK_TRAFFIC GetProcessNetWorkTrafficInfoFromEProcess( PEPROCESS pEProcess ); 176 | PPROCESS_NETWORK_TRAFFIC ReferenceProcessNetWorkTrafficInfo( PEPROCESS pEProcess ); 177 | DWORD ReleaseProcessNetWorkTrafficInfo( PROCESS_NETWORK_TRAFFIC *pProcessIoInformaiton ); 178 | NTSTATUS EnterUserProcessReadImagePath( PEPROCESS pEProcess, PUNICODE_STRING pImageFilePath ); 179 | NTSTATUS GetFileHandle( PHANDLE pFileHandle, PUNICODE_STRING FileName ); 180 | NTSTATUS QueryFileAndDirInfo( HANDLE hFile, 181 | LPCWSTR pwszFilePath, 182 | LPCWSTR pwszFileName, 183 | PFILE_BOTH_DIRECTORY_INFORMATION FileInformation, 184 | ULONG FileInformationLength ); 185 | LPWSTR FindWideCharInWideString(LPCWSTR pszwString, DWORD dwLength, WCHAR wFindChar); 186 | NTSTATUS ShortPathNameToEntirePathName( PUNICODE_STRING ShortPathName, PUNICODE_STRING FullPathName ); 187 | NTSTATUS GetProcessImagePath( DWORD dwProcessId, PUNICODE_STRING ProcessImageFilePath, DWORD dwBufferLen ); 188 | NTSTATUS RegisterProcessCreateNotify(); 189 | NTSTATUS DeregisterProcessCreateNotify(); 190 | 191 | ULONG DebugPrintEx( DWORD dwFlags, CHAR *Format, ... ) 192 | { 193 | ULONG uRet; 194 | va_list va; 195 | 196 | if( !( dwPrintFlags & dwFlags ) ) 197 | { 198 | return 0; 199 | } 200 | 201 | va_start( va, Format ); 202 | 203 | uRet = vDbgPrintEx( 0xFFFFFFFF, 0, Format, va ); 204 | 205 | va_end( va ); 206 | 207 | return uRet; 208 | } 209 | 210 | NTSTATUS CreateWorkThread( PKSTART_ROUTINE StartRoutine, PVOID StartContext, PKTHREAD *kThread ) 211 | { 212 | NTSTATUS ntStatus; 213 | HANDLE hThread; 214 | 215 | ASSERT( NULL != kThread ); 216 | 217 | *kThread = NULL; 218 | hThread = NULL; 219 | 220 | ntStatus = PsCreateSystemThread( &hThread, 221 | THREAD_ALL_ACCESS, 222 | NULL, 223 | NULL, 224 | NULL, 225 | StartRoutine, 226 | NULL 227 | ); 228 | 229 | if( !NT_SUCCESS( ntStatus ) ) 230 | { 231 | goto RETURN_; 232 | } 233 | 234 | ntStatus = ObReferenceObjectByHandle( 235 | hThread, 236 | THREAD_ALL_ACCESS, 237 | NULL, 238 | KernelMode, 239 | ( PVOID* )kThread, 240 | NULL 241 | ); 242 | 243 | if( !NT_SUCCESS( ntStatus ) ) 244 | { 245 | goto RETURN_; 246 | } 247 | 248 | RETURN_: 249 | if( NULL != hThread ) 250 | { 251 | ZwClose( hThread ); 252 | } 253 | 254 | return ntStatus; 255 | } 256 | 257 | NTSTATUS DriverEntry( PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath ) 258 | { 259 | NTSTATUS ntStatus; 260 | INT32 i; 261 | 262 | UNICODE_STRING TcpDeviceName; 263 | UNICODE_STRING UdpDeviceName; 264 | 265 | UNICODE_STRING TdiFilterDeviceName; 266 | UNICODE_STRING TdiFilterDeviceDosName; 267 | 268 | DebugPrintEx( DRIVER_ENTRY_INFO, "netmon enter DriverEntry\n" ); 269 | 270 | RtlInitUnicodeString( ( PUNICODE_STRING )&TdiFilterDeviceName, 271 | TDI_FILTER_DEVICE_NAME ); 272 | 273 | RtlInitUnicodeString( ( PUNICODE_STRING )&TdiFilterDeviceDosName, 274 | TDI_FILTER_DEVICE_DOS_NAME ); 275 | 276 | DebugPrintEx( DRIVER_ENTRY_INFO, "netmon DriverEntry begin IoCreateDevice TdiFilterDeviceName\n" ); 277 | ntStatus = IoCreateDevice( 278 | DriverObject, 279 | 0, 280 | &TdiFilterDeviceName, 281 | FILE_DEVICE_UNKNOWN, 282 | 0, 283 | FALSE, 284 | &g_DevTdiFilter 285 | ); 286 | 287 | DebugPrintEx( DRIVER_ENTRY_INFO, "netmon DriverEntry end IoCreateDevice TdiFilterDeviceName\n" ); 288 | 289 | if ( !NT_SUCCESS( ntStatus ) ) 290 | { 291 | return ntStatus; 292 | } 293 | 294 | DebugPrintEx( DRIVER_ENTRY_INFO, "netmon DriverEntry begin IoCreateSymbolicLink TdiFilterDeviceDosName\n" ); 295 | 296 | ntStatus = IoCreateSymbolicLink( &TdiFilterDeviceDosName, 297 | &TdiFilterDeviceName ); 298 | 299 | if( !NT_SUCCESS( ntStatus ) ) 300 | { 301 | goto Error; 302 | } 303 | 304 | KeInitializeSpinLock( &g_SpLockProcessNetWorkTrafficInfo ); 305 | KeInitializeSpinLock( &g_SpLockTdiEventHandlerInfo ); 306 | 307 | InitializeListHead( &g_ProcessIoInfoList ); 308 | InitializeListHead( &g_TdiEventHandlerInfoList ); 309 | InitializeListHead( &g_ProcessInformationList ); 310 | 311 | ExInitializeResourceLite(&g_SyncResource); 312 | 313 | KeInitializeEvent( &g_EventProcessInformationAdded, SynchronizationEvent, 0 ); 314 | KeInitializeEvent( &g_EventIrpListAdded, SynchronizationEvent, 0 ); 315 | KeInitializeEvent( &g_EventCompletion, SynchronizationEvent, 0 ); 316 | 317 | g_TimerElapse.QuadPart = TDI_FILTER_TIMER_ELAPSE_TIME; 318 | 319 | g_SendingDelayTime.QuadPart = -10000; 320 | 321 | g_WaitNewIistItemTime.QuadPart = TDI_FILTER_TIMER_ELAPSE_TIME; 322 | 323 | g_ThreadWaitConfigProcTime.LowPart = WAIT_CONFIGURED_PROC_TIME; 324 | g_ThreadWaitConfigProcTime.HighPart = 0xFFFFFFFF; 325 | 326 | ExInitializeNPagedLookasideList( 327 | &g_CompletionWrapList, 328 | NULL, 329 | NULL, 330 | 0, 331 | sizeof( TDI_COMPLETION_WRAP ), 332 | TDI_FILTER_LOOKASIDE_POOL_TAG, 333 | 0 334 | ); 335 | 336 | for( i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i ++ ) 337 | { 338 | DriverObject->MajorFunction[ i ] = TdiFilterDefaultIrpProcess; 339 | } 340 | 341 | DriverObject->MajorFunction[ IRP_MJ_DEVICE_CONTROL ] = TdiFilterIoControl; 342 | DriverObject->MajorFunction[ IRP_MJ_INTERNAL_DEVICE_CONTROL ] = TdiFilterInternalIoControl; 343 | DriverObject->MajorFunction[ IRP_MJ_CLEANUP ] = TdiFilterCleanUp; 344 | DriverObject->DriverUnload = TdiFilterUnload; 345 | 346 | RtlInitUnicodeString( &TcpDeviceName, TCP_DEVICE_NAME ); 347 | RtlInitUnicodeString( &UdpDeviceName, UDP_DEVICE_NAME ); 348 | 349 | if( !NT_SUCCESS( AttachToTdiDevice( DriverObject, &TcpDeviceName, &g_FilterDeviceForDeviceTcp ) ) || 350 | !NT_SUCCESS( AttachToTdiDevice( DriverObject, &UdpDeviceName, &g_FilterDeviceForDeviceUdp ) ) ) 351 | { 352 | ExDeleteNPagedLookasideList( &g_CompletionWrapList ); 353 | goto Error; 354 | 355 | } 356 | 357 | ntStatus = RegisterProcessCreateNotify(); 358 | if( !NT_SUCCESS( ntStatus ) ) 359 | { 360 | ExDeleteNPagedLookasideList( &g_CompletionWrapList ); 361 | goto Error; 362 | } 363 | 364 | ntStatus = CreateWorkThread( ThreadWaitCompletion, NULL, &g_ThreadWaitCompletion ); 365 | if( !NT_SUCCESS( ntStatus ) ) 366 | { 367 | ExDeleteNPagedLookasideList( &g_CompletionWrapList ); 368 | goto Error; 369 | } 370 | 371 | DebugPrintEx( DRIVER_ENTRY_INFO, "netmon DriverEntry end CreateWorkThread ThreadWaitCompletion\n" ); 372 | 373 | ntStatus = init_hash_table( &g_MasterIrpHash, MASTER_IRP_HASH_TABLE_SIZE ); 374 | if( 0 > ntStatus ) 375 | { 376 | goto Error; 377 | } 378 | 379 | return ntStatus; 380 | 381 | Error: 382 | if ( NULL != g_FilterDeviceForDeviceTcp ) 383 | { 384 | PDEVICE_OBJECT DeviceObject; 385 | DeviceObject = *( PDEVICE_OBJECT * )g_FilterDeviceForDeviceTcp->DeviceExtension; 386 | IoDetachDevice( DeviceObject ); 387 | IoDeleteDevice( g_FilterDeviceForDeviceTcp ); 388 | g_FilterDeviceForDeviceTcp = NULL; 389 | } 390 | 391 | if ( NULL != g_FilterDeviceForDeviceUdp ) 392 | { 393 | PDEVICE_OBJECT DeviceObject; 394 | DeviceObject = *( PDEVICE_OBJECT * )g_FilterDeviceForDeviceUdp->DeviceExtension; 395 | IoDetachDevice( DeviceObject ); 396 | IoDeleteDevice( g_FilterDeviceForDeviceUdp ); 397 | g_FilterDeviceForDeviceUdp = NULL; 398 | } 399 | 400 | if( NULL != g_DevTdiFilter ) 401 | { 402 | IoDeleteDevice( g_DevTdiFilter ); 403 | g_DevTdiFilter = NULL; 404 | } 405 | 406 | IoDeleteSymbolicLink( &TdiFilterDeviceDosName ); 407 | return ntStatus; 408 | } 409 | 410 | DWORD ReleaseAllEventHandlerWrap() 411 | { 412 | NTSTATUS ntStatus; 413 | DWORD dwErrorCount; 414 | KIRQL OldIrql; 415 | PLIST_ENTRY pListEntry; 416 | PLIST_ENTRY pListEntryPrev; 417 | PTDI_EVENT_HANDLER_LIST pTdiEventHandlerList; 418 | PTDI_EVENT_HANDLER_WRAP pTdiEventHandlerWrap; 419 | 420 | KeAcquireSpinLock( &g_SpLockTdiEventHandlerInfo, &OldIrql ); 421 | 422 | pListEntry = g_TdiEventHandlerInfoList.Flink; 423 | 424 | dwErrorCount = 0; 425 | 426 | for( ; ; ) 427 | { 428 | if( pListEntry == &g_TdiEventHandlerInfoList ) 429 | { 430 | break; 431 | } 432 | 433 | pListEntryPrev = pListEntry->Flink; 434 | 435 | pTdiEventHandlerList = ( PTDI_EVENT_HANDLER_LIST )pListEntry; 436 | 437 | RemoveEntryList( pListEntry ); 438 | 439 | ntStatus = RestoreEventHandler( pTdiEventHandlerList->pTdiEventHandlerWrap ); 440 | if( !NT_SUCCESS( ntStatus ) ) 441 | { 442 | dwErrorCount ++; 443 | } 444 | 445 | ExFreePoolWithTag( pTdiEventHandlerList->pTdiEventHandlerWrap, 0 ); 446 | ExFreePoolWithTag( pTdiEventHandlerList, 0 ); 447 | 448 | pListEntry = pListEntryPrev; 449 | } 450 | 451 | KeReleaseSpinLock( &g_SpLockTdiEventHandlerInfo, OldIrql ); 452 | return dwErrorCount; 453 | } 454 | 455 | VOID TdiFilterUnload( PDRIVER_OBJECT pDriverObject ) 456 | { 457 | UNICODE_STRING TdiFilterDeviceDosName; 458 | 459 | PDEVICE_OBJECT DeviceObject; 460 | 461 | DebugPrintEx( DRIVER_UNLOAD_INFO, "netmon enter TdiFilterUnload\n" ); 462 | 463 | RtlInitUnicodeString( ( PUNICODE_STRING )&TdiFilterDeviceDosName, 464 | TDI_FILTER_DEVICE_DOS_NAME ); 465 | 466 | g_bFiltering = FALSE; 467 | 468 | DeregisterProcessCreateNotify(); 469 | 470 | ASSERT( NULL != g_FilterDeviceForDeviceTcp && 471 | NULL != g_FilterDeviceForDeviceUdp && 472 | NULL != g_DevTdiFilter ); 473 | 474 | if( NULL != g_FilterDeviceForDeviceTcp ) 475 | { 476 | DebugPrintEx( DRIVER_UNLOAD_INFO, "netmon release g_FilterDeviceForDeviceTcp begin\n" ); 477 | DeviceObject = *( PDEVICE_OBJECT * )g_FilterDeviceForDeviceTcp->DeviceExtension; 478 | IoDetachDevice( DeviceObject ); 479 | IoDeleteDevice( g_FilterDeviceForDeviceTcp ); 480 | DebugPrintEx( DRIVER_UNLOAD_INFO, "netmon release g_FilterDeviceForDeviceTcp end\n" ); 481 | } 482 | 483 | if( NULL != g_FilterDeviceForDeviceUdp ) 484 | { 485 | DebugPrintEx( DRIVER_UNLOAD_INFO, "netmon release g_FilterDeviceForDeviceUdp begin\n" ); 486 | DeviceObject = *( PDEVICE_OBJECT * )g_FilterDeviceForDeviceUdp->DeviceExtension; 487 | IoDetachDevice( DeviceObject ); 488 | IoDeleteDevice( g_FilterDeviceForDeviceUdp ); 489 | DebugPrintEx( DRIVER_UNLOAD_INFO, "netmon release g_FilterDeviceForDeviceUdp end\n" ); 490 | } 491 | 492 | if( NULL != g_DevTdiFilter ) 493 | { 494 | DebugPrintEx( DRIVER_UNLOAD_INFO, "netmon release g_DevTdiFilter begin\n" ); 495 | IoDeleteDevice( g_DevTdiFilter ); 496 | IoDeleteSymbolicLink( &TdiFilterDeviceDosName ); 497 | DebugPrintEx( DRIVER_UNLOAD_INFO, "netmon release g_DevTdiFilter end\n" ); 498 | } 499 | 500 | ASSERT( NULL != g_ThreadWaitCompletion ); 501 | 502 | DebugPrintEx( DRIVER_UNLOAD_INFO, "netmon ReleaseAllProcessesInformation begin\n" ); 503 | ReleaseAllProcessesInformation(); 504 | DebugPrintEx( DRIVER_UNLOAD_INFO, "netmon ReleaseAllProcessesInformation end\n" ); 505 | 506 | g_bThreadUpdateConfigStop = TRUE; 507 | g_bThreadIrpProcessStop = TRUE; 508 | 509 | if( NULL != ThreadUpdateConfig ) 510 | { 511 | DebugPrintEx( DRIVER_UNLOAD_INFO, "netmon release ThreadUpdateConfig begin\n" ); 512 | KeWaitForSingleObject( ThreadUpdateConfig, Executive, KernelMode, FALSE, NULL ); 513 | ObDereferenceObject( ThreadUpdateConfig ); 514 | DebugPrintEx( DRIVER_UNLOAD_INFO, "netmon release ThreadUpdateConfig end\n" ); 515 | } 516 | 517 | if( NULL != ThreadProcessIrp ) 518 | { 519 | DebugPrintEx( DRIVER_UNLOAD_INFO, "netmon release ThreadProcessIrp begin\n" ); 520 | KeWaitForSingleObject( ThreadProcessIrp, Executive, KernelMode, FALSE, NULL ); 521 | ObDereferenceObject( ThreadProcessIrp ); 522 | DebugPrintEx( DRIVER_UNLOAD_INFO, "netmon release ThreadProcessIrp end\n" ); 523 | } 524 | 525 | DebugPrintEx( DRIVER_UNLOAD_INFO, "netmon ReleaseAllEventHandlerWrap begin\n" ); 526 | ReleaseAllEventHandlerWrap(); 527 | DebugPrintEx( DRIVER_UNLOAD_INFO, "netmon ReleaseAllEventHandlerWrap end\n" ); 528 | 529 | DebugPrintEx( DRIVER_UNLOAD_INFO, "netmon ReleaseAllProcessNetWorkTrafficInfo begin\n" ); 530 | ReleaseAllProcessNetWorkTrafficInfo(); 531 | DebugPrintEx( DRIVER_UNLOAD_INFO, "netmon ReleaseAllProcessNetWorkTrafficInfo end\n" ); 532 | 533 | DebugPrintEx( DRIVER_UNLOAD_INFO, "netmon wait g_ThreadWaitCompletion begin\n" ); 534 | KeSetEvent( &g_EventCompletion, 0, FALSE ); 535 | KeWaitForSingleObject( g_ThreadWaitCompletion, Executive, KernelMode, FALSE, NULL ); 536 | DebugPrintEx( DRIVER_UNLOAD_INFO, "netmon wait g_ThreadWaitCompletion end\n" ); 537 | 538 | DebugPrintEx( DRIVER_UNLOAD_INFO, "netmon ExDeleteNPagedLookasideList begin\n" ); 539 | ExDeleteNPagedLookasideList( &g_CompletionWrapList ); 540 | DebugPrintEx( DRIVER_UNLOAD_INFO, "netmon ExDeleteNPagedLookasideList end\n" ); 541 | 542 | ExDeleteResourceLite( &g_SyncResource ); 543 | DebugPrintEx( DRIVER_UNLOAD_INFO, "netmon ExDeleteResourceLite end\n" ); 544 | 545 | return; 546 | } 547 | 548 | NTSTATUS TdiFilterCleanUp(PDEVICE_OBJECT DeviceObject, PIRP pIrp ) 549 | { 550 | NTSTATUS ntStatus; 551 | KIRQL OldIrql; 552 | LIST_ENTRY *pListEntry; 553 | PTDI_EVENT_HANDLER_LIST pTdiEventHandlerListFind; 554 | PTDI_EVENT_HANDLER_WRAP pTdiEventHandlerWrapFind; 555 | PFILE_OBJECT pFileObject; 556 | 557 | TDI_FILTER_DEVICE_EXTENSION *pDeviceExtension; 558 | PIO_STACK_LOCATION pIrpSp; 559 | 560 | DebugPrintEx( CLEANUP_INFO, "netmon Enter TdiFilterCleanUp\n" ); 561 | pDeviceExtension = ( TDI_FILTER_DEVICE_EXTENSION* )DeviceObject->DeviceExtension; 562 | pIrpSp = IoGetCurrentIrpStackLocation( pIrp ); 563 | pFileObject = pIrpSp->FileObject; 564 | 565 | if( FALSE == IsDriverDevice( DeviceObject ) ) 566 | { 567 | ntStatus = STATUS_INVALID_PARAMETER; 568 | goto COMPLETE_IRP; 569 | } 570 | 571 | if( DeviceObject == g_DevTdiFilter ) 572 | { 573 | ntStatus = STATUS_SUCCESS; 574 | goto COMPLETE_IRP; 575 | } 576 | 577 | DebugPrintEx( CLEANUP_INFO, "netmon TdiFilterCleanUp IoCallDriver\n" ); 578 | IoSkipCurrentIrpStackLocation( pIrp ); 579 | ntStatus = IoCallDriver( pDeviceExtension->pTdiDeviceObject, pIrp ); 580 | 581 | if( !NT_SUCCESS( ntStatus ) ) 582 | { 583 | DebugPrintEx( CLEANUP_INFO,"netmon TdiFilterCleanUp IoCallDriver return ERROR\n" ); 584 | return ntStatus; 585 | } 586 | 587 | KeAcquireSpinLock( &g_SpLockTdiEventHandlerInfo, &OldIrql ); 588 | 589 | FIND_LIST_AGAIN: 590 | pListEntry = g_TdiEventHandlerInfoList.Flink; 591 | 592 | for( ; ; ) 593 | { 594 | if( pListEntry == &g_TdiEventHandlerInfoList ) 595 | { 596 | break; 597 | } 598 | 599 | pTdiEventHandlerListFind = ( PTDI_EVENT_HANDLER_LIST )pListEntry; 600 | pTdiEventHandlerWrapFind = pTdiEventHandlerListFind->pTdiEventHandlerWrap; 601 | 602 | DebugPrintEx( CLEANUP_INFO,"Client address find: 0x%0.8x, input 0x%0.8x \n", 603 | pTdiEventHandlerWrapFind->pAssocAddr, 604 | pFileObject ); 605 | 606 | if( pTdiEventHandlerWrapFind->pAssocAddr == pFileObject ) 607 | { 608 | DebugPrintEx( CLEANUP_INFO,"Client address finded: 0x%0.8x \n", pTdiEventHandlerWrapFind->pAssocAddr ); 609 | 610 | RemoveEntryList( pListEntry ); 611 | 612 | ExFreePoolWithTag( pTdiEventHandlerWrapFind, 0 ); 613 | ExFreePoolWithTag( pTdiEventHandlerListFind, 0 ); 614 | goto FIND_LIST_AGAIN; 615 | } 616 | 617 | pListEntry = pListEntry->Flink; 618 | } 619 | 620 | KeReleaseSpinLock( &g_SpLockTdiEventHandlerInfo, OldIrql ); 621 | return ntStatus; 622 | 623 | COMPLETE_IRP: 624 | pIrp->IoStatus.Status = ntStatus; 625 | pIrp->IoStatus.Information = 0; 626 | 627 | IoCompleteRequest( pIrp, 0 ); 628 | 629 | return ntStatus; 630 | } 631 | 632 | NTSTATUS TdiFilterDefaultIrpProcess( PDEVICE_OBJECT pDeviceObject, PIRP pIrp ) 633 | { 634 | IO_STACK_LOCATION *pIrpSp; 635 | NTSTATUS ntStatus; 636 | TDI_FILTER_DEVICE_EXTENSION *pDeviceExtension; 637 | 638 | DebugPrintEx( PROCESS_COMMON_INFO, "netmon enter TdiFilterDefaultIrpProcess \n" ); 639 | pDeviceExtension = ( TDI_FILTER_DEVICE_EXTENSION* )pDeviceObject->DeviceExtension; 640 | 641 | pIrpSp = IoGetCurrentIrpStackLocation( pIrp ); 642 | 643 | if ( !IsDriverDevice( pDeviceObject, pIrp ) ) 644 | { 645 | ntStatus = STATUS_INVALID_PARAMETER; 646 | goto COMPLETE_IRP; 647 | } 648 | 649 | if ( pDeviceObject == g_DevTdiFilter ) 650 | { 651 | ntStatus = STATUS_SUCCESS; 652 | goto COMPLETE_IRP; 653 | } 654 | 655 | IoSkipCurrentIrpStackLocation( pIrp ); 656 | return IoCallDriver( pDeviceExtension->pTdiDeviceObject, pIrp ); 657 | 658 | COMPLETE_IRP: 659 | pIrp->IoStatus.Status = ntStatus; 660 | pIrp->IoStatus.Information = 0; 661 | IofCompleteRequest( pIrp, 0 ); 662 | return ntStatus; 663 | } 664 | 665 | NTSTATUS RestoreEventHandler( PTDI_EVENT_HANDLER_WRAP pEventHandlerWrap ) 666 | { 667 | NTSTATUS ntStatus; 668 | PIRP pIrp = NULL; 669 | PDEVICE_OBJECT pDeviceObject; 670 | 671 | ASSERT( NULL != pEventHandlerWrap ); 672 | 673 | ASSERT( FALSE != MmIsAddressValid( pEventHandlerWrap ) ); 674 | pDeviceObject = pEventHandlerWrap->pDeviceObject; 675 | 676 | ASSERT( FALSE != MmIsAddressValid( pDeviceObject ) ); 677 | 678 | if( NULL == pDeviceObject || 679 | FALSE == MmIsAddressValid( pEventHandlerWrap->pAssocAddr ) ) 680 | return STATUS_UNSUCCESSFUL; 681 | 682 | if( NULL == pEventHandlerWrap->pOrgEventHandler ) 683 | { 684 | return STATUS_SUCCESS; 685 | } 686 | 687 | pIrp = TdiBuildInternalDeviceControlIrp( TDI_SET_EVENT_HANDLER, pDeviceObject, 688 | pEventHandlerWrap->pAssocAddr, NULL, NULL ); 689 | 690 | if ( NULL == pIrp ) 691 | { 692 | ntStatus = STATUS_UNSUCCESSFUL; 693 | goto RETURN_; 694 | } 695 | 696 | TdiBuildSetEventHandler( pIrp, 697 | pDeviceObject, 698 | pEventHandlerWrap->pAssocAddr, 699 | NULL, 700 | NULL, 701 | pEventHandlerWrap->dwEventType, 702 | pEventHandlerWrap->pOrgEventHandler, 703 | pEventHandlerWrap->pOrgEventContext 704 | ); 705 | 706 | DebugPrintEx( RESTORE_EVENT_HANDLER_INFO, "net RestoreEventHandler restore event wrap 0x%0.8x, handler 0x%0.8x file object 0x%0.8x success \n", 707 | pEventHandlerWrap, 708 | pEventHandlerWrap->pOrgEventHandler, 709 | pEventHandlerWrap->pAssocAddr ); 710 | 711 | ntStatus = IoCallDriver( pDeviceObject, pIrp ); 712 | pIrp = NULL; 713 | 714 | if( NT_SUCCESS( ntStatus ) ) { 715 | DebugPrintEx( RESTORE_EVENT_HANDLER_INFO, "net RestoreEventHandler restore event wrap 0x%0.8x, handler 0x%0.8x success \n", 716 | pEventHandlerWrap, 717 | pEventHandlerWrap->pOrgEventHandler 718 | ); 719 | goto RETURN_; 720 | } 721 | 722 | // don't wait to complete 723 | RETURN_: 724 | if( NULL != pIrp ) 725 | { 726 | IoFreeIrp( pIrp ); 727 | } 728 | 729 | return ntStatus; 730 | } 731 | 732 | VOID DeleteEventWrap( PTDI_EVENT_HANDLER_LIST pTdiEventHandlerList ) 733 | { 734 | KIRQL OldIrql; 735 | 736 | KeAcquireSpinLock( &g_SpLockTdiEventHandlerInfo, &OldIrql ); 737 | 738 | DebugPrintEx( RECV_EVENT_HANDLER_INFO, "Delete event wrap list: 0x%0.8x \n", 739 | pTdiEventHandlerList ); 740 | 741 | RemoveEntryList( ( PLIST_ENTRY )pTdiEventHandlerList ); 742 | 743 | ExFreePoolWithTag( pTdiEventHandlerList->pTdiEventHandlerWrap, 0 ); 744 | ExFreePoolWithTag( pTdiEventHandlerList, 0 ); 745 | 746 | KeReleaseSpinLock( &g_SpLockTdiEventHandlerInfo, OldIrql ); 747 | return; 748 | } 749 | 750 | VOID UpdateEventHandlerWrap( PPROCESS_NETWORK_TRAFFIC pProcessNetWorkTrafficInfo, 751 | PEPROCESS pEProcess, 752 | PDEVICE_OBJECT pDeviceObject, 753 | PFILE_OBJECT pFileObject, 754 | DWORD dwEventType, 755 | PVOID pEventHandler, 756 | PVOID pEventContext, 757 | PTDI_EVENT_HANDLER_LIST *ppEventHandlerList, 758 | DWORD dwFlags ) 759 | { 760 | KIRQL OldIrql; 761 | PLIST_ENTRY pListEntry; 762 | PTDI_EVENT_HANDLER_LIST pTdiEventHandlerListFind; 763 | PTDI_EVENT_HANDLER_WRAP pTdiEventHandlerWrapFind; 764 | PTDI_EVENT_HANDLER_LIST pTdiEventHandlerListNew = NULL; 765 | PTDI_EVENT_HANDLER_WRAP pTdiEventHandlerWrapNew = NULL; 766 | 767 | ASSERT( NULL != ppEventHandlerList ); 768 | 769 | *ppEventHandlerList = NULL; 770 | 771 | KeAcquireSpinLock( &g_SpLockTdiEventHandlerInfo, &OldIrql ); 772 | 773 | pListEntry = g_TdiEventHandlerInfoList.Flink; 774 | 775 | for( ; ; ) 776 | { 777 | if( pListEntry == &g_TdiEventHandlerInfoList ) 778 | { 779 | break; 780 | } 781 | 782 | pTdiEventHandlerListFind = ( PTDI_EVENT_HANDLER_LIST )pListEntry; 783 | pTdiEventHandlerWrapFind = pTdiEventHandlerListFind->pTdiEventHandlerWrap; 784 | 785 | if( pTdiEventHandlerWrapFind->pAssocAddr == pFileObject && 786 | pTdiEventHandlerWrapFind->dwEventType == dwEventType ) 787 | { 788 | 789 | ASSERT( TRUE == MmIsAddressValid( pTdiEventHandlerWrapFind->pAssocAddr ) ); 790 | if( pProcessNetWorkTrafficInfo != NULL && 791 | pTdiEventHandlerWrapFind->pProcessNetWorkTrafficInfo != pProcessNetWorkTrafficInfo ) 792 | { 793 | DebugPrintEx( RECV_EVENT_HANDLER_INFO, "***Find event handler wrap, but process is not same***, finded 0x%0.8x, input 0x%0.8x \n", 794 | pTdiEventHandlerWrapFind->pProcessNetWorkTrafficInfo, 795 | pProcessNetWorkTrafficInfo ); 796 | } 797 | 798 | if( DEL_EVENT_WRAP == dwFlags ) 799 | { 800 | DebugPrintEx( RECV_EVENT_HANDLER_INFO, "Delete event wrap: 0x%0.8x, Process io information 0x%0.8x, Address 0x%0.8x, event type %d, event handler 0x%0.8x \n", 801 | pTdiEventHandlerWrapFind, 802 | pProcessNetWorkTrafficInfo, 803 | pFileObject, 804 | pTdiEventHandlerWrapFind->dwEventType, 805 | pTdiEventHandlerWrapFind->pOrgEventHandler 806 | ); 807 | RemoveEntryList( pListEntry ); 808 | ExFreePoolWithTag( pTdiEventHandlerWrapFind, 0 ); 809 | ExFreePoolWithTag( pTdiEventHandlerListFind, 0 ); 810 | } 811 | else 812 | { 813 | DebugPrintEx( RECV_EVENT_HANDLER_INFO, "Update event wrap: 0x%0.8x, Process io information 0x%0.8x, Address 0x%0.8x old event type %d, old event handler 0x%0.8x, new event type %d, new event handler 0x%0.8x \n", 814 | pTdiEventHandlerWrapFind, 815 | pProcessNetWorkTrafficInfo, 816 | pFileObject, 817 | pTdiEventHandlerWrapFind->dwEventType, 818 | pTdiEventHandlerWrapFind->pOrgEventHandler, 819 | dwEventType, 820 | pEventHandler ); 821 | 822 | pTdiEventHandlerWrapFind->pOrgEventHandler = pEventHandler; 823 | pTdiEventHandlerWrapFind->pOrgEventContext = pEventContext; 824 | 825 | *ppEventHandlerList = pTdiEventHandlerListFind; 826 | } 827 | 828 | KeReleaseSpinLock( &g_SpLockTdiEventHandlerInfo, OldIrql ); 829 | return; 830 | } 831 | 832 | pListEntry = pListEntry->Flink; 833 | } 834 | 835 | if( GET_EVENT_WRAP == dwFlags ) 836 | { 837 | pTdiEventHandlerWrapNew = ( PTDI_EVENT_HANDLER_WRAP )AllocZeroPoolWithTag( NonPagedPool, sizeof( TDI_EVENT_HANDLER_WRAP ) ); 838 | if( NULL == pTdiEventHandlerWrapNew ) 839 | { 840 | goto RELEASE_POOL_EXIT; 841 | } 842 | 843 | pTdiEventHandlerListNew = ( PTDI_EVENT_HANDLER_LIST )AllocZeroPoolWithTag( NonPagedPool, sizeof( TDI_EVENT_HANDLER_LIST ) ); 844 | if( NULL == pTdiEventHandlerListNew ) 845 | { 846 | goto RELEASE_POOL_EXIT; 847 | } 848 | 849 | pTdiEventHandlerWrapNew->dwEventContextMark = TDI_EVENT_CONTEXT_MARK; 850 | pTdiEventHandlerWrapNew->dwEventType = dwEventType; 851 | pTdiEventHandlerWrapNew->pOrgEventHandler = pEventHandler; 852 | pTdiEventHandlerWrapNew->pOrgEventContext = pEventContext; 853 | pTdiEventHandlerWrapNew->pEProcess = pEProcess; 854 | pTdiEventHandlerWrapNew->pProcessNetWorkTrafficInfo = pProcessNetWorkTrafficInfo; 855 | pTdiEventHandlerWrapNew->pAssocAddr = pFileObject; 856 | pTdiEventHandlerWrapNew->pDeviceObject = pDeviceObject; 857 | 858 | pTdiEventHandlerListNew->pTdiEventHandlerWrap = pTdiEventHandlerWrapNew; 859 | 860 | InsertTailList( &g_TdiEventHandlerInfoList, ( PLIST_ENTRY )pTdiEventHandlerListNew ); 861 | 862 | DebugPrintEx( RECV_EVENT_HANDLER_INFO, "Add new event wrap: 0x%0.8x, Process io information 0x%0.8x, Address 0x%0.8x event type %d, new event handler 0x%0.8x \n", 863 | pTdiEventHandlerWrapNew, 864 | pProcessNetWorkTrafficInfo, 865 | pFileObject, 866 | pTdiEventHandlerWrapNew->dwEventType, 867 | pTdiEventHandlerWrapNew->pOrgEventHandler 868 | ); 869 | 870 | *ppEventHandlerList = pTdiEventHandlerListNew; 871 | 872 | KeReleaseSpinLock( &g_SpLockTdiEventHandlerInfo, OldIrql ); 873 | return; 874 | 875 | RELEASE_POOL_EXIT: 876 | if( NULL != pTdiEventHandlerWrapNew ) 877 | { 878 | ExFreePoolWithTag( pTdiEventHandlerWrapNew, NonPagedPool ); 879 | } 880 | 881 | if( NULL != pTdiEventHandlerListNew ) 882 | { 883 | ExFreePoolWithTag( pTdiEventHandlerListNew, NonPagedPool ); 884 | } 885 | 886 | KeReleaseSpinLock( &g_SpLockTdiEventHandlerInfo, OldIrql ); 887 | return; 888 | } 889 | 890 | KeReleaseSpinLock( &g_SpLockTdiEventHandlerInfo, OldIrql ); 891 | return; 892 | } 893 | 894 | PIRP DequeueIrp( PLIST_ENTRY pListHead, PKSPIN_LOCK SpLock ) 895 | { 896 | KIRQL oldIrql; 897 | PIRP nextIrp = NULL; 898 | 899 | KeAcquireSpinLock( SpLock, &oldIrql ); 900 | 901 | while( !nextIrp && !IsListEmpty( pListHead ) ) 902 | { 903 | PDRIVER_CANCEL oldCancelRoutine; 904 | PLIST_ENTRY listEntry = RemoveHeadList( pListHead ); 905 | 906 | // Get the next IRP off the queue. 907 | nextIrp = CONTAINING_RECORD( listEntry, IRP, Tail.Overlay.ListEntry ); 908 | 909 | if( NULL == nextIrp->AssociatedIrp.MasterIrp ) 910 | { 911 | // Clear the IRP's cancel routine 912 | oldCancelRoutine = IoSetCancelRoutine(nextIrp, NULL); 913 | // IoCancelIrp() could have just been called on this IRP. 914 | // What we're interested in is not whether IoCancelIrp() was called (nextIrp->Cancel flag set), 915 | // but whether IoCancelIrp() called (or is about to call) our cancel routine. 916 | // To check that, check the result of the test-and-set macro IoSetCancelRoutine. 917 | if (oldCancelRoutine){ 918 | // Cancel routine not called for this IRP. Return this IRP. 919 | ASSERT(oldCancelRoutine == TdiFilterCancel ); 920 | } 921 | else { 922 | // This IRP was just canceled and the cancel routine was (or will be) called. 923 | // The cancel routine will complete this IRP as soon as we drop the spin lock, 924 | // so don't do anything with the IRP. 925 | // Also, the cancel routine will try to dequeue the IRP, 926 | // so make the IRP's listEntry point to itself. 927 | ASSERT(nextIrp->Cancel); 928 | InitializeListHead(&nextIrp->Tail.Overlay.ListEntry); 929 | nextIrp = NULL; 930 | } 931 | } 932 | } 933 | 934 | KeReleaseSpinLock(SpLock, oldIrql); 935 | 936 | return nextIrp; 937 | } 938 | 939 | VOID TdiFilterCancel( 940 | IN PDEVICE_OBJECT DeviceObject, 941 | IN PIRP Irp 942 | ) 943 | 944 | { 945 | NTSTATUS ntStatus; 946 | PLIST_ENTRY pListEntry = NULL; 947 | PIRP pAssocIrp = NULL; 948 | KIRQL OldIrql; 949 | KIRQL CancelIrql = Irp->CancelIrql; 950 | PPROCESS_NETWORK_TRAFFIC pProcessNetWorkTraffic = NULL; 951 | hash_key key; 952 | key.quad_part = make_hash_key( 0, ( DWORD )Irp ); 953 | 954 | DebugPrintEx( IRP_CANCEL_INFO, "netmon Enter TdiFilterCancel\n" ); 955 | IoReleaseCancelSpinLock( CancelIrql ); 956 | 957 | FIND_ASSOC_IRPS: 958 | 959 | KeAcquireSpinLock( &pProcessNetWorkTraffic->IrpListLock, &OldIrql ); 960 | 961 | DebugPrintEx( IRP_CANCEL_INFO, "netmon TdiFilterCancel get_hash_value\n" ); 962 | ntStatus = get_hash_value( &g_MasterIrpHash, key, &pProcessNetWorkTraffic ); 963 | DebugPrintEx( IRP_CANCEL_INFO, "netmon TdiFilterCancel get_hash_value return 0x%0.8x, pProcessNetWorkTraffic 0x%0.8x\n", 964 | ntStatus, 965 | pProcessNetWorkTraffic 966 | ); 967 | 968 | if( 0 > ntStatus ) 969 | { 970 | ASSERT( FALSE ); 971 | goto RETURN_; 972 | } 973 | 974 | ASSERT( TRUE == MmIsAddressValid( pProcessNetWorkTraffic ) ); 975 | 976 | pListEntry = pProcessNetWorkTraffic->IrpList.Flink; 977 | 978 | for ( ; ; ) 979 | { 980 | if( pListEntry == &pProcessNetWorkTraffic->IrpList ) 981 | { 982 | break; 983 | } 984 | 985 | pAssocIrp = CONTAINING_RECORD( pListEntry, IRP, Tail.Overlay.ListEntry ); 986 | DebugPrintEx( IRP_CANCEL_INFO, "netmon TdiFilterCancel find irp 0x%0.8x master irp 0x%0.8x cancel irp 0x%0.8x\n", 987 | pAssocIrp->AssociatedIrp.MasterIrp, 988 | Irp ); 989 | 990 | if ( Irp == pAssocIrp->AssociatedIrp.MasterIrp ) 991 | { 992 | DebugPrintEx( IRP_CANCEL_INFO, "netmon TdiFilterCancel finded \n" ); 993 | RemoveEntryList( &pAssocIrp->Tail.Overlay.ListEntry ); 994 | KeReleaseSpinLock( &pProcessNetWorkTraffic->IrpListLock, OldIrql ); 995 | 996 | pAssocIrp->IoStatus.Status = STATUS_CANCELLED; 997 | pAssocIrp->IoStatus.Information = 0; 998 | 999 | IoCompleteRequest( pAssocIrp, IO_NO_INCREMENT ); 1000 | goto FIND_ASSOC_IRPS; 1001 | } 1002 | pListEntry = pListEntry->Flink; 1003 | } 1004 | 1005 | RemoveEntryList( &Irp->Tail.Overlay.ListEntry ); 1006 | KeReleaseSpinLock( &pProcessNetWorkTraffic->IrpListLock, OldIrql ); 1007 | 1008 | Irp->IoStatus.Status = STATUS_CANCELLED; 1009 | Irp->IoStatus.Information = 0; 1010 | 1011 | IoCompleteRequest( Irp, IO_NO_INCREMENT ); 1012 | 1013 | DebugPrintEx( IRP_CANCEL_INFO, "netmon TdiFilterCancel delete hash item 0x%0.8x \n", 1014 | Irp ); 1015 | 1016 | ntStatus = del_hash_item( &g_MasterIrpHash, key, &pProcessNetWorkTraffic ); 1017 | 1018 | DebugPrintEx( IRP_CANCEL_INFO, "netmon TdiFilterCancel delete hash item 0x%0.8x, return 0x%0.8x \n", 1019 | Irp, 1020 | ntStatus ); 1021 | 1022 | return; 1023 | 1024 | RETURN_: 1025 | KeReleaseSpinLock( &pProcessNetWorkTraffic->IrpListLock, OldIrql ); 1026 | } 1027 | 1028 | NTSTATUS TdiFilterInternalIoControl( PDEVICE_OBJECT pDeviceObject, PIRP pIrp ) 1029 | { 1030 | NTSTATUS ntStatus; 1031 | PTDI_FILTER_DEVICE_EXTENSION pDeviceExtension; 1032 | PIO_STACK_LOCATION pIrpSp; 1033 | PFILE_OBJECT pFileObject; 1034 | TDI_REQUEST_KERNEL_RECEIVE *pTdiRecvParam; 1035 | PPROCESS_NETWORK_TRAFFIC pProcessNetWorkTrafficInfo; 1036 | IO_STACK_LOCATION *pIrpSpNext; 1037 | PTDI_COMPLETION_WRAP pCompletionWrap; 1038 | PTDI_REQUEST_KERNEL_SET_EVENT pTdiSetEvent; 1039 | PTDI_EVENT_HANDLER_LIST pTdiEventHandlerList; 1040 | PLIST_ENTRY pListEntry; 1041 | BYTE MinorFunction; 1042 | PEPROCESS pEProcess; 1043 | PETHREAD pThread; 1044 | CHAR bIsSend; 1045 | BYTE OldIrql; 1046 | hash_key key; 1047 | 1048 | if( FALSE == IsDriverDevice( pDeviceObject, pIrp ) ) 1049 | { 1050 | ASSERT( FALSE ); 1051 | DebugPrintEx( IO_INTERNAL_CONTROL_INFO, "netmon TdiFilterInternalIoControl: IsDriverDevice return FALSE\n" ); 1052 | ntStatus = STATUS_INVALID_PARAMETER; 1053 | goto COMPLETE_IRP; 1054 | } 1055 | 1056 | pIrpSp = IoGetCurrentIrpStackLocation( pIrp ); 1057 | pFileObject = pIrpSp->FileObject; 1058 | pDeviceExtension = ( PTDI_FILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension; 1059 | 1060 | if( FALSE == g_bFiltering ) 1061 | { 1062 | if( g_FilterDeviceForDeviceTcp == pDeviceObject || 1063 | g_FilterDeviceForDeviceUdp == pDeviceObject ) 1064 | { 1065 | DebugPrintEx( IO_INTERNAL_CONTROL_INFO, "netmon TdiFilterInternalIoControl: g_bFiltering == FALSE pDeviceObject == g_pFilterDevicexxx \n" ); 1066 | goto SKIP_CURRENT_STACK_LOCATION_CALL_PDO_DRIVER; 1067 | } 1068 | } 1069 | 1070 | if( g_DevTdiFilter == pDeviceObject ) 1071 | { 1072 | DebugPrintEx( IO_INTERNAL_CONTROL_INFO, "netmon TdiFilterInternalIoControl: g_DevTdiFilter == pDeviceObject" ); 1073 | ntStatus = STATUS_SUCCESS; 1074 | goto COMPLETE_IRP; 1075 | } 1076 | 1077 | pThread = pIrp->Tail.Overlay.Thread; 1078 | if( NULL == pThread ) 1079 | { 1080 | pEProcess = IoGetCurrentProcess(); 1081 | } 1082 | else 1083 | { 1084 | pEProcess = IoThreadToProcess( pThread ); 1085 | } 1086 | 1087 | DebugPrintEx( IO_INTERNAL_CONTROL_INFO, "netmon TdiFilterInternalIoControl: got the eprocess of the thread: 0x%0.8x \n", pEProcess ); 1088 | 1089 | ASSERT( NULL != pEProcess ); 1090 | 1091 | MinorFunction = pIrpSp->MinorFunction; 1092 | 1093 | if( TDI_SEND == MinorFunction || 1094 | TDI_SEND_DATAGRAM == MinorFunction ) 1095 | { 1096 | DebugPrintEx( IO_INTERNAL_CONTROL_INFO, " TDI_SEND SystemBuffer is 0x%0.8x, MdlAddress Is 0x%0.8x, UserBuffer is 0x%0.8x \n", 1097 | pIrp->AssociatedIrp.SystemBuffer, 1098 | pIrp->MdlAddress, 1099 | pIrp->UserBuffer ); 1100 | } 1101 | else 1102 | { 1103 | DebugPrintEx( IO_INTERNAL_CONTROL_INFO, " TDI_RECEIVE SystemBuffer is 0x%0.8x, MdlAddress Is 0x%0.8x, UserBuffer is 0x%0.8x \n", 1104 | pIrp->AssociatedIrp.SystemBuffer, 1105 | pIrp->MdlAddress, 1106 | pIrp->UserBuffer ); 1107 | } 1108 | 1109 | if( TDI_SEND == MinorFunction || 1110 | TDI_SEND_DATAGRAM == MinorFunction || 1111 | TDI_RECEIVE == MinorFunction || 1112 | TDI_RECEIVE_DATAGRAM == MinorFunction ) 1113 | { 1114 | DebugPrintEx( IO_INTERNAL_CONTROL_INFO, "netmon TdiFilterInternalIoControl: MinorFunction == TDI_SENDXXX, TDI_RECEIVEXXX \n" ); 1115 | 1116 | if( TDI_RECEIVE == MinorFunction && 1117 | TDI_RECEIVE_PEEK == ( ULONG )pIrpSp->Parameters.Others.Argument2 ) 1118 | { 1119 | DebugPrintEx( IO_INTERNAL_CONTROL_INFO, "netmon TdiFilterInternalIoControl: MinorFunction == TDI_RECEIVE recv flags == TDI_RECEIVE_PEEK \n" ); 1120 | goto SKIP_CURRENT_STACK_LOCATION_CALL_PDO_DRIVER; 1121 | } 1122 | 1123 | pProcessNetWorkTrafficInfo = GetProcessNetWorkTrafficInfoFromEProcess( pEProcess ); 1124 | if( NULL == pProcessNetWorkTrafficInfo ) 1125 | { 1126 | DebugPrintEx( IO_INTERNAL_CONTROL_INFO, "netmon TdiFilterInternalIoControl: GetProcessNetWorkTrafficInfoFromEProcess return NULL \n" ); 1127 | goto SKIP_CURRENT_STACK_LOCATION_CALL_PDO_DRIVER; 1128 | } 1129 | 1130 | if( FALSE != pProcessNetWorkTrafficInfo->bStopSend && 1131 | ( TDI_SEND == MinorFunction || 1132 | TDI_SEND_DATAGRAM == MinorFunction ) ) 1133 | { 1134 | DebugPrintEx( IO_INTERNAL_CONTROL_INFO, "netmon TdiFilterInternalIoControl: prohibit send! \n" ); 1135 | goto WHEN_ACCESS_DENIED; 1136 | } 1137 | 1138 | if( FALSE != pProcessNetWorkTrafficInfo->bStopRecv && 1139 | ( TDI_RECEIVE_DATAGRAM == MinorFunction || 1140 | TDI_RECEIVE == MinorFunction ) ) 1141 | { 1142 | DebugPrintEx( IO_INTERNAL_CONTROL_INFO, "netmon TdiFilterInternalIoControl: prohibit receive \n" ); 1143 | goto WHEN_ACCESS_DENIED; 1144 | } 1145 | 1146 | DebugPrintEx( IO_INTERNAL_CONTROL_INFO, "netmon TdiFilterInternalIoControl: check sendingspeed \n" ); 1147 | 1148 | if( TRUE == InterlockedExchangeAdd( &g_bThreadsRunning, 0 ) && 1149 | ( pProcessNetWorkTrafficInfo->SendingSpeed.LowPart != 0xFFFFFFFF && 1150 | pProcessNetWorkTrafficInfo->SendingSpeed.HighPart != 0x7FFFFFFF ) ) 1151 | { 1152 | if( NULL == pIrp->AssociatedIrp.SystemBuffer && 1153 | ( TDI_SEND == MinorFunction || 1154 | TDI_SEND_DATAGRAM == MinorFunction ) ) 1155 | { 1156 | if( TRUE == IoIsOperationSynchronous( pIrp ) ) 1157 | { 1158 | DebugPrintEx( IO_INTERNAL_CONTROL_INFO, "netmon TdiFilterInternalIoControl: IoIsOperationSynchronous return TRUE \n" ); 1159 | ntStatus = TdiFilterSyncSendProcess( pProcessNetWorkTrafficInfo, 1160 | pDeviceObject, 1161 | pIrp ); 1162 | 1163 | ReleaseProcessNetWorkTrafficInfo( pProcessNetWorkTrafficInfo ); 1164 | 1165 | return ntStatus; 1166 | } 1167 | else 1168 | { 1169 | KIRQL IrpSpIrql; 1170 | hash_key key; 1171 | PDRIVER_CANCEL OldCancelRoutine; 1172 | 1173 | DebugPrintEx( IO_INTERNAL_CONTROL_INFO, "netmon TdiFilterInternalIoControl: add irp to process irp list \n" ); 1174 | 1175 | IoMarkIrpPending( pIrp ); 1176 | key.quad_part = make_hash_key( 0, ( DWORD )pIrp ); 1177 | 1178 | KeAcquireSpinLock( &pProcessNetWorkTrafficInfo->IrpListLock, &IrpSpIrql ); 1179 | 1180 | DebugPrintEx( IRP_CANCEL_INFO, "netmon TdiFilterInternalIoControl add_hash_item 0x%0.8x \n", pIrp ); 1181 | ntStatus = add_hash_item( &g_MasterIrpHash, key, ( hash_value )pProcessNetWorkTrafficInfo ); 1182 | 1183 | DebugPrintEx( IRP_CANCEL_INFO, "netmon TdiFilterInternalIoControl add_hash_item return 0x%0.8x \n", ntStatus ); 1184 | 1185 | OldCancelRoutine = IoSetCancelRoutine( pIrp, TdiFilterCancel ); 1186 | ASSERT( NULL == OldCancelRoutine ); 1187 | 1188 | InsertTailList( &pProcessNetWorkTrafficInfo->IrpList, &pIrp->Tail.Overlay.ListEntry ); 1189 | 1190 | if( pIrp->Cancel ) 1191 | { 1192 | OldCancelRoutine = IoSetCancelRoutine( pIrp, NULL); 1193 | if( OldCancelRoutine ) 1194 | { 1195 | RemoveEntryList( &pIrp->Tail.Overlay.ListEntry ); 1196 | KeReleaseSpinLock( &pProcessNetWorkTrafficInfo->IrpListLock, IrpSpIrql ); 1197 | pIrp->IoStatus.Status = STATUS_CANCELLED; 1198 | pIrp->IoStatus.Information = 0; 1199 | IoCompleteRequest( pIrp, IO_NO_INCREMENT ); 1200 | return STATUS_PENDING; 1201 | } 1202 | } 1203 | 1204 | KeReleaseSpinLock( &pProcessNetWorkTrafficInfo->IrpListLock, IrpSpIrql ); 1205 | 1206 | DebugPrintEx( IO_INTERNAL_CONTROL_INFO, "netmon TdiFilterInternalIoControl: ExInterlockedInsertTailList insert irp to pProcessNetWorkTrafficInfo->IrpList \n" ); 1207 | ReleaseProcessNetWorkTrafficInfo( pProcessNetWorkTrafficInfo ); 1208 | 1209 | KeSetEvent( &g_EventIrpListAdded, 0, FALSE ); 1210 | return STATUS_PENDING; 1211 | } 1212 | } 1213 | } 1214 | 1215 | DebugPrintEx( IO_INTERNAL_CONTROL_INFO, "netmon TdiFilterInternalIoControl: wrap completion \n" ); 1216 | pCompletionWrap = ( PTDI_COMPLETION_WRAP )ExAllocateFromNPagedLookasideList( &g_CompletionWrapList ); 1217 | if( NULL == pCompletionWrap ) 1218 | { 1219 | DebugPrintEx( IO_INTERNAL_CONTROL_INFO, "netmon TdiFilterInternalIoControl: ExAllocateFromNPagedLookasideList return NULL \n" ); 1220 | ReleaseProcessNetWorkTrafficInfo( pProcessNetWorkTrafficInfo ); 1221 | goto SKIP_CURRENT_STACK_LOCATION_CALL_PDO_DRIVER; 1222 | } 1223 | 1224 | if( TDI_SEND == MinorFunction || 1225 | TDI_SEND_DATAGRAM == MinorFunction ) 1226 | { 1227 | bIsSend = TRUE; 1228 | } 1229 | else 1230 | { 1231 | bIsSend = FALSE; 1232 | } 1233 | 1234 | DebugPrintEx( IO_INTERNAL_CONTROL_INFO, "netmon TdiFilterInternalIoControl: set the irp completion wrap \n" ); 1235 | pCompletionWrap->bSendOpera = bIsSend; 1236 | pCompletionWrap->bWrap = FALSE; 1237 | pCompletionWrap->bAssocIrp = FALSE; 1238 | pCompletionWrap->bSync = TRUE; 1239 | pCompletionWrap->pEProcess = pEProcess; 1240 | pCompletionWrap->pProcessNetWorkTrafficInfo = pProcessNetWorkTrafficInfo; 1241 | 1242 | ReleaseProcessNetWorkTrafficInfo( pProcessNetWorkTrafficInfo ); 1243 | 1244 | if( pIrp->CurrentLocation <= 1 ) 1245 | { 1246 | ASSERT( FALSE ); 1247 | ExFreeToNPagedLookasideList( &g_CompletionWrapList, pCompletionWrap ); 1248 | goto SKIP_CURRENT_STACK_LOCATION_CALL_PDO_DRIVER; 1249 | } 1250 | 1251 | IoCopyCurrentIrpStackLocationToNext( pIrp ); 1252 | 1253 | IoSetCompletionRoutine( pIrp, 1254 | TdiFilterCompletion, 1255 | pCompletionWrap, 1256 | TRUE, 1257 | TRUE, 1258 | TRUE 1259 | ); 1260 | 1261 | g_CompletionIrpCount ++; 1262 | DebugPrintEx( IRP_COMPLETION_INFO, "netmon ThreadSendingSpeedControl completion count++ %d\n", g_CompletionIrpCount ); 1263 | 1264 | DebugPrintEx( IO_INTERNAL_CONTROL_INFO, "netmon TdiFilterInternalIoControl: call driver with completion wraped irp \n" ); 1265 | goto CALL_PDO_DRIVER; 1266 | 1267 | } 1268 | else if( TDI_SET_EVENT_HANDLER == MinorFunction ) 1269 | { 1270 | DebugPrintEx( IO_INTERNAL_CONTROL_INFO, "netmon TdiFilterInternalIoControl: TDI_SET_EVENT_HANDLER == MinorFunction \n" ); 1271 | 1272 | pTdiSetEvent = ( PTDI_REQUEST_KERNEL_SET_EVENT )&pIrpSp->Parameters; 1273 | 1274 | if( TDI_EVENT_RECEIVE == pTdiSetEvent->EventType || 1275 | TDI_EVENT_RECEIVE_EXPEDITED == pTdiSetEvent->EventType || 1276 | TDI_EVENT_CHAINED_RECEIVE == pTdiSetEvent->EventType || 1277 | TDI_EVENT_CHAINED_RECEIVE_EXPEDITED == pTdiSetEvent->EventType || 1278 | TDI_EVENT_RECEIVE_DATAGRAM == pTdiSetEvent->EventType ) 1279 | { 1280 | pTdiEventHandlerList = NULL; 1281 | pProcessNetWorkTrafficInfo = NULL; 1282 | 1283 | if( NULL == pTdiSetEvent->EventHandler ) 1284 | { 1285 | DWORD EventType; 1286 | DebugPrintEx( IO_INTERNAL_CONTROL_INFO, "netmon TdiFilterInternalIoControl: NULL == pTdiSetEvent->EventHandler \n" ); 1287 | 1288 | EventType = pTdiSetEvent->EventType; 1289 | 1290 | IoSkipCurrentIrpStackLocation( pIrp ); 1291 | ntStatus = IoCallDriver( pDeviceExtension->pTdiDeviceObject, pIrp ); 1292 | 1293 | if( !NT_SUCCESS( ntStatus ) ) 1294 | { 1295 | DebugPrintEx( IO_INTERNAL_CONTROL_INFO, "netmon TdiFilterInternalIoControl: IoCallDriver return error \n" ); 1296 | return ntStatus; 1297 | } 1298 | 1299 | UpdateEventHandlerWrap( NULL, 1300 | NULL, 1301 | NULL, 1302 | pFileObject, 1303 | EventType, 1304 | NULL, 1305 | NULL, 1306 | &pTdiEventHandlerList, 1307 | DEL_EVENT_WRAP ); 1308 | 1309 | DebugPrintEx( IO_INTERNAL_CONTROL_INFO, "netmon TdiFilterInternalIoControl: delete event wraped handler \n" ); 1310 | 1311 | return ntStatus; 1312 | } 1313 | 1314 | pProcessNetWorkTrafficInfo = GetProcessNetWorkTrafficInfoFromEProcess( pEProcess ); 1315 | if( NULL == pProcessNetWorkTrafficInfo ) 1316 | { 1317 | DebugPrintEx( IO_INTERNAL_CONTROL_INFO, "netmon TdiFilterInternalIoControl: GetProcessNetWorkTrafficInfoFromEProcess return NULL \n" ); 1318 | goto SKIP_CURRENT_STACK_LOCATION_CALL_PDO_DRIVER; 1319 | } 1320 | 1321 | UpdateEventHandlerWrap( pProcessNetWorkTrafficInfo, 1322 | pEProcess, 1323 | pDeviceExtension->pTdiDeviceObject, 1324 | pFileObject, 1325 | pTdiSetEvent->EventType, 1326 | pTdiSetEvent->EventHandler, 1327 | pTdiSetEvent->EventContext, 1328 | &pTdiEventHandlerList, 1329 | GET_EVENT_WRAP ); 1330 | 1331 | ReleaseProcessNetWorkTrafficInfo( pProcessNetWorkTrafficInfo ); 1332 | 1333 | if( NULL == pTdiEventHandlerList ) 1334 | { 1335 | goto SKIP_CURRENT_STACK_LOCATION_CALL_PDO_DRIVER; 1336 | } 1337 | 1338 | if( TDI_EVENT_RECEIVE == pTdiSetEvent->EventType || 1339 | TDI_EVENT_RECEIVE_EXPEDITED == pTdiSetEvent->EventType ) 1340 | { 1341 | pTdiSetEvent->EventHandler = TdiFilterRecvEventHandler; 1342 | } 1343 | else if( TDI_EVENT_CHAINED_RECEIVE == pTdiSetEvent->EventType || 1344 | TDI_EVENT_CHAINED_RECEIVE_EXPEDITED == pTdiSetEvent->EventType ) 1345 | { 1346 | pTdiSetEvent->EventHandler = TdiFilterChainedRecvHandler; 1347 | } 1348 | else 1349 | { 1350 | pTdiSetEvent->EventHandler = TdiFilterRecvDatagramEventHandler; 1351 | } 1352 | 1353 | ASSERT( NULL != pTdiEventHandlerList->pTdiEventHandlerWrap ); 1354 | pTdiSetEvent->EventContext = pTdiEventHandlerList->pTdiEventHandlerWrap; 1355 | 1356 | DebugPrintEx( IO_INTERNAL_CONTROL_INFO, "netmon TdiFilterInternalIoControl: IoCallDriver with event wraped irp \n" ); 1357 | 1358 | IoSkipCurrentIrpStackLocation( pIrp ); 1359 | ntStatus = IoCallDriver( pDeviceExtension->pTdiDeviceObject, pIrp ); 1360 | 1361 | if( !NT_SUCCESS( ntStatus ) ) 1362 | { 1363 | DeleteEventWrap( pTdiEventHandlerList ); 1364 | DebugPrintEx( IO_INTERNAL_CONTROL_INFO, "netmon TdiFilterInternalIoControl: IoCallDriver return error \n" ); 1365 | } 1366 | 1367 | return ntStatus; 1368 | } 1369 | else 1370 | { 1371 | DebugPrintEx( IO_INTERNAL_CONTROL_INFO, "netmon TdiFilterInternalIoControl: is other event handler call pdo drver \n" ); 1372 | goto SKIP_CURRENT_STACK_LOCATION_CALL_PDO_DRIVER; 1373 | } 1374 | } 1375 | else 1376 | { 1377 | DebugPrintEx( IO_INTERNAL_CONTROL_INFO, "netmon TdiFilterInternalIoControl: is other minor function call pdo drver \n" ); 1378 | goto SKIP_CURRENT_STACK_LOCATION_CALL_PDO_DRIVER; 1379 | } 1380 | 1381 | SKIP_CURRENT_STACK_LOCATION_CALL_PDO_DRIVER: 1382 | IoSkipCurrentIrpStackLocation( pIrp ); 1383 | 1384 | CALL_PDO_DRIVER: 1385 | DebugPrintEx( IO_INTERNAL_CONTROL_INFO, "netmon TdiFilterInternalIoControl: call pdo drver \n" ); 1386 | return IoCallDriver( pDeviceExtension->pTdiDeviceObject, pIrp ); 1387 | 1388 | COMPLETE_IRP: 1389 | pIrp->IoStatus.Status = ntStatus; 1390 | pIrp->IoStatus.Information = 0; 1391 | IoCompleteRequest( pIrp, 0 ); 1392 | return ntStatus; 1393 | 1394 | WHEN_ACCESS_DENIED: 1395 | DebugPrintEx( IO_INTERNAL_CONTROL_INFO, "netmon TdiFilterInternalIoControl Access denied\n" ); 1396 | ReleaseProcessNetWorkTrafficInfo( pProcessNetWorkTrafficInfo ); 1397 | ntStatus = STATUS_ACCESS_DENIED; 1398 | goto COMPLETE_IRP; 1399 | } 1400 | 1401 | NTSTATUS TdiFilterIoControl( PDEVICE_OBJECT pDeviceObject, PIRP pIrp ) 1402 | { 1403 | NTSTATUS ntStatus; 1404 | PTDI_FILTER_DEVICE_EXTENSION pDeviceExtension; 1405 | PIO_STACK_LOCATION pIrpSp; 1406 | DWORD dwOutputLength; 1407 | 1408 | pDeviceExtension = ( PTDI_FILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension; 1409 | pIrpSp = IoGetCurrentIrpStackLocation( pIrp ); 1410 | 1411 | 1412 | DebugPrintEx( IO_CONTROL_INFO, "netmon enter TdiFilterIoControl\n" ); 1413 | 1414 | if( FALSE == IsDriverDevice( pDeviceObject, pIrp ) ) 1415 | { 1416 | DebugPrintEx( IO_CONTROL_INFO, "netmon TdiFilterIoControl FALSE == IsDriverDevice\n" ); 1417 | ntStatus = STATUS_INVALID_PARAMETER; 1418 | goto COMPLETE_IRP; 1419 | } 1420 | 1421 | if( FALSE == g_bFiltering && 1422 | ( pDeviceObject == g_FilterDeviceForDeviceTcp || 1423 | pDeviceObject == g_FilterDeviceForDeviceUdp ) ) 1424 | { 1425 | DebugPrintEx( IO_CONTROL_INFO, "netmon TdiFilterIoControl FALSE == g_bFiltering\n" ); 1426 | 1427 | goto SKIP_CURRENT_STACK_LOCATION_CALL_DRIVER; 1428 | } 1429 | 1430 | if( g_DevTdiFilter != pDeviceObject ) 1431 | { 1432 | if( PASSIVE_LEVEL == KeGetCurrentIrql() ) 1433 | { 1434 | ntStatus = TdiMapUserRequest( pDeviceObject, 1435 | pIrp, 1436 | pIrpSp 1437 | ); 1438 | 1439 | if( NT_SUCCESS( ntStatus ) ) 1440 | { 1441 | DebugPrintEx( IO_CONTROL_INFO, "netmon TdiFilterIoControl TdiMapUserRequest return success: 0x%0.8x minor function is 0x%0.8x\n", ntStatus, pIrpSp->MinorFunction ); 1442 | return TdiFilterInternalIoControl( pDeviceObject, pIrp ); 1443 | } 1444 | } 1445 | 1446 | goto SKIP_CURRENT_STACK_LOCATION_CALL_DRIVER; 1447 | } 1448 | else 1449 | { 1450 | DebugPrintEx( IO_CONTROL_INFO, "netmon TdiFilterIoControl g_DevTdiFilter == pDeviceObject\n" ); 1451 | DebugPrintEx( IO_CONTROL_INFO, "netmon TdiFilterIoControl IoControlCode == %d \n", pIrpSp->Parameters.DeviceIoControl.IoControlCode ); 1452 | 1453 | 1454 | if( IOCTL_TDI_GET_TDI_FILTER_DRIVER_VERSION == pIrpSp->Parameters.DeviceIoControl.IoControlCode ) 1455 | { 1456 | DWORD *pId; 1457 | DebugPrintEx( IO_CONTROL_INFO, "netmon TdiFilterIoControl IoControlCode == IOCTL_TDI_GET_TDI_FILTER_DRIVER_ID\n" ); 1458 | if( NULL == pIrp->AssociatedIrp.SystemBuffer || 1459 | sizeof( TDI_FILTER_DRIVER_VERSION ) > pIrpSp->Parameters.DeviceIoControl.OutputBufferLength ) 1460 | { 1461 | ntStatus = STATUS_INVALID_PARAMETER; 1462 | dwOutputLength = 0; 1463 | goto COMPLETE_IRP; 1464 | } 1465 | 1466 | pId = ( DWORD* )pIrp->AssociatedIrp.SystemBuffer; 1467 | 1468 | RtlCopyMemory( pIrp->AssociatedIrp.SystemBuffer, TDI_FILTER_DRIVER_VERSION, sizeof( TDI_FILTER_DRIVER_VERSION ) ); 1469 | ntStatus = STATUS_SUCCESS; 1470 | dwOutputLength = sizeof( TDI_FILTER_DRIVER_VERSION ); 1471 | goto COMPLETE_IRP; 1472 | } 1473 | else if( IOCTL_TDI_CHECK_FILTERING_STATE == pIrpSp->Parameters.DeviceIoControl.IoControlCode ) 1474 | { 1475 | DebugPrintEx( IO_CONTROL_INFO, "netmon TdiFilterIoControl IoControlCode == IOCTL_TDI_CHECK_FILTERING_STATE \n" ); 1476 | if( NULL == pIrp->AssociatedIrp.SystemBuffer || 1477 | sizeof( BOOL ) > pIrpSp->Parameters.DeviceIoControl.OutputBufferLength ) 1478 | { 1479 | ntStatus = STATUS_INVALID_PARAMETER; 1480 | dwOutputLength = 0; 1481 | goto COMPLETE_IRP; 1482 | } 1483 | 1484 | *( BOOL* )pIrp->AssociatedIrp.SystemBuffer = g_bFiltering; 1485 | ntStatus = STATUS_SUCCESS; 1486 | dwOutputLength = sizeof( BOOL ); 1487 | goto COMPLETE_IRP; 1488 | } 1489 | else if( IOCTL_TDI_GET_ALL_PROCESS_IO_INFO == pIrpSp->Parameters.DeviceIoControl.IoControlCode ) 1490 | { 1491 | DebugPrintEx( IO_CONTROL_INFO, "netmon TdiFilterIoControl IoControlCode == IOCTL_TDI_GET_ALL_PROCESS_IO_INFO \n" ); 1492 | ntStatus = GetAllProcessesIoInformation( pIrp->AssociatedIrp.SystemBuffer, 1493 | pIrpSp->Parameters.DeviceIoControl.OutputBufferLength, 1494 | &dwOutputLength ); 1495 | 1496 | goto COMPLETE_IRP; 1497 | } 1498 | else if( IOCTL_TDI_OPEN_FILTERING == pIrpSp->Parameters.DeviceIoControl.IoControlCode ) 1499 | { 1500 | DebugPrintEx( IO_CONTROL_INFO, "netmon TdiFilterIoControl IoControlCode == IOCTL_TDI_OPEN_FILTERING \n" ); 1501 | g_bFiltering = TRUE; 1502 | ntStatus = STATUS_SUCCESS; 1503 | dwOutputLength = 0; 1504 | goto COMPLETE_IRP; 1505 | } 1506 | else if( IOCTL_TDI_CLOSE_FILTERING == pIrpSp->Parameters.DeviceIoControl.IoControlCode ) 1507 | { 1508 | DebugPrintEx( IO_CONTROL_INFO, "netmon TdiFilterIoControl IoControlCode == IOCTL_TDI_CLOSE_FILTERING \n" ); 1509 | g_bFiltering = FALSE; 1510 | ntStatus = STATUS_SUCCESS; 1511 | dwOutputLength = 0; 1512 | goto COMPLETE_IRP; 1513 | } 1514 | else if( IOCTL_TDI_GET_ALL_TRAFFIC == pIrpSp->Parameters.DeviceIoControl.IoControlCode ) 1515 | { 1516 | LARGE_INTEGER *pOutput; 1517 | DebugPrintEx( IO_CONTROL_INFO, "netmon TdiFilterIoControl IoControlCode == IOCTL_TDI_GET_ALL_TRAFFIC \n" ); 1518 | if( NULL == pIrp->AssociatedIrp.SystemBuffer || 1519 | sizeof( LARGE_INTEGER ) * 2 > pIrpSp->Parameters.DeviceIoControl.OutputBufferLength ) 1520 | { 1521 | ntStatus = STATUS_INVALID_PARAMETER; 1522 | dwOutputLength = 0; 1523 | goto COMPLETE_IRP; 1524 | } 1525 | 1526 | pOutput = ( LARGE_INTEGER* )pIrp->AssociatedIrp.SystemBuffer; 1527 | pOutput[ 0 ].LowPart = g_AllRecvedDataSize.LowPart; 1528 | pOutput[ 0 ].HighPart = g_AllRecvedDataSize.HighPart; 1529 | pOutput[ 1 ].LowPart = g_AllSendedDataSize.LowPart; 1530 | pOutput[ 1 ].HighPart = g_AllSendedDataSize.HighPart; 1531 | 1532 | ntStatus = STATUS_SUCCESS; 1533 | dwOutputLength = sizeof( LARGE_INTEGER ) * 2; 1534 | goto COMPLETE_IRP; 1535 | } 1536 | else if( IOCTL_TDI_START_UPDATE_PROCESS_IO_INFO == pIrpSp->Parameters.DeviceIoControl.IoControlCode ) 1537 | { 1538 | DebugPrintEx( IO_CONTROL_INFO, "netmon TdiFilterIoControl IoControlCode == IOCTL_TDI_START_UPDATE_PROCESS_IO_INFO \n" ); 1539 | ntStatus = StartWorkThreadManageProcessInfo( ( PPROCESS_INFORMATION_RECORD )pIrp->AssociatedIrp.SystemBuffer, pIrpSp->Parameters.DeviceIoControl.InputBufferLength ); 1540 | dwOutputLength = 0; 1541 | goto COMPLETE_IRP; 1542 | } 1543 | else if( IOCTL_TDI_GET_ALL_PROCESS_INFO == pIrpSp->Parameters.DeviceIoControl.IoControlCode ) 1544 | { 1545 | DebugPrintEx( IO_CONTROL_INFO, "netmon TdiFilterIoControl IoControlCode == IOCTL_TDI_GET_ALL_PROCESS_INFO\n" ); 1546 | ntStatus = GetAllProcessesInformation( pIrp->AssociatedIrp.SystemBuffer, pIrpSp->Parameters.DeviceIoControl.OutputBufferLength, &dwOutputLength ); 1547 | goto COMPLETE_IRP; 1548 | } 1549 | else if( IOCTL_TDI_RELEASE_ALL_PROCESS_INFO == pIrpSp->Parameters.DeviceIoControl.IoControlCode ) 1550 | { 1551 | DebugPrintEx( IO_CONTROL_INFO, "netmon TdiFilterIoControl IoControlCode == IOCTL_TDI_RELEASE_ALL_PROCESS_INFO\n" ); 1552 | ntStatus = ReleaseAllProcessesInformation(); 1553 | dwOutputLength = 0; 1554 | goto COMPLETE_IRP; 1555 | } 1556 | #ifdef _DEBUG 1557 | else if( IOCTL_TDI_SET_DEBUG_TRACE_FLAG == pIrpSp->Parameters.DeviceIoControl.IoControlCode ) 1558 | { 1559 | DebugPrintEx( IO_CONTROL_INFO, "netmon TdiFilterIoControl IoControlCode == IOCTL_TDI_SET_DEBUG_TRACE_FLAG \n" ); 1560 | if( NULL == pIrp->AssociatedIrp.SystemBuffer || 1561 | sizeof( DWORD ) > pIrpSp->Parameters.DeviceIoControl.InputBufferLength ) 1562 | { 1563 | ntStatus = STATUS_INVALID_PARAMETER; 1564 | dwOutputLength = 0; 1565 | goto COMPLETE_IRP; 1566 | } 1567 | 1568 | dwPrintFlags = *( DWORD* )pIrp->AssociatedIrp.SystemBuffer; 1569 | 1570 | DebugPrintEx( IO_CONTROL_INFO, "netmon TdiFilterIoControl New debug flags is 0x%0.8x \n", dwPrintFlags ); 1571 | 1572 | ntStatus = STATUS_SUCCESS; 1573 | dwOutputLength = sizeof( DWORD ); 1574 | goto COMPLETE_IRP; 1575 | } 1576 | else if( IOCTL_TDI_SET_BP_FLAG ) 1577 | { 1578 | DebugPrintEx( IO_CONTROL_INFO, "netmon TdiFilterIoControl IoControlCode == IOCTL_TDI_SET_DEBUG_TRACE_FLAG \n" ); 1579 | if( NULL == pIrp->AssociatedIrp.SystemBuffer || 1580 | sizeof( DWORD ) > pIrpSp->Parameters.DeviceIoControl.InputBufferLength ) 1581 | { 1582 | ntStatus = STATUS_INVALID_PARAMETER; 1583 | dwOutputLength = 0; 1584 | goto COMPLETE_IRP; 1585 | } 1586 | 1587 | dwBPFlag = *( DWORD* )pIrp->AssociatedIrp.SystemBuffer; 1588 | 1589 | DebugPrintEx( IO_CONTROL_INFO, "netmon TdiFilterIoControl New bp flags is 0x%0.8x \n", dwBPFlag ); 1590 | 1591 | ntStatus = STATUS_SUCCESS; 1592 | dwOutputLength = sizeof( DWORD ); 1593 | goto COMPLETE_IRP; 1594 | } 1595 | #endif 1596 | else 1597 | { 1598 | DebugPrintEx( IO_CONTROL_INFO, "netmon TdiFilterIoControl receive other io control code, IoControlCode == 0x%0.8x \n" ); 1599 | } 1600 | } 1601 | 1602 | ntStatus = STATUS_INVALID_PARAMETER; 1603 | dwOutputLength = 0; 1604 | 1605 | COMPLETE_IRP: 1606 | pIrp->IoStatus.Status = ntStatus; 1607 | pIrp->IoStatus.Information = dwOutputLength; 1608 | IoCompleteRequest( pIrp, 0 ); 1609 | return ntStatus; 1610 | 1611 | SKIP_CURRENT_STACK_LOCATION_CALL_DRIVER: 1612 | IoSkipCurrentIrpStackLocation( pIrp ); 1613 | return IoCallDriver( pDeviceExtension->pTdiDeviceObject, pIrp ); 1614 | } 1615 | 1616 | NTSTATUS TdiFilterRecvEventHandler( IN PVOID TdiEventContext, 1617 | IN CONNECTION_CONTEXT ConnectionContext, 1618 | IN ULONG ReceiveFlags, 1619 | IN ULONG BytesIndicated, 1620 | IN ULONG BytesAvailable, 1621 | OUT ULONG *BytesTaken, 1622 | IN PVOID Tsdu, 1623 | OUT PIRP *IoRequestPacket 1624 | ) 1625 | { 1626 | NTSTATUS ntStatus; 1627 | PIO_STACK_LOCATION pIrpSp; 1628 | PTDI_EVENT_HANDLER_WRAP pEventHandlerWrap; 1629 | PPROCESS_NETWORK_TRAFFIC pProcessNetWorkTrafficInfo; 1630 | PTDI_COMPLETION_WRAP pCompletionWrap; 1631 | LARGE_INTEGER RecvedDataSize; 1632 | 1633 | ASSERT( NULL != TdiEventContext ); 1634 | 1635 | DebugPrintEx( RECV_EVENT_HANDLER_INFO, "netmon Enter TdiFilterRecvEventHandler \n" ); 1636 | 1637 | pEventHandlerWrap = ( PTDI_EVENT_HANDLER_WRAP )TdiEventContext; 1638 | 1639 | ASSERT( NULL != pEventHandlerWrap && 1640 | NULL != pEventHandlerWrap->pOrgEventHandler ); 1641 | 1642 | if( FALSE == MmIsAddressValid( pEventHandlerWrap ) ) 1643 | { 1644 | DebugPrintEx( RECV_EVENT_HANDLER_INFO, "netmon TdiFilterRecvEventHandler pEventHandlerWrap is not valid reading address\n" ); 1645 | return STATUS_DATA_NOT_ACCEPTED; 1646 | } 1647 | 1648 | DebugPrintEx( RECV_EVENT_HANDLER_INFO, "netmon TdiFilterRecvEventHandler event wrap 0x%0.8x, original event handler 0x%0.8x \n", 1649 | pEventHandlerWrap, 1650 | pEventHandlerWrap->pOrgEventHandler ); 1651 | 1652 | if( FALSE == g_bFiltering ) 1653 | { 1654 | DebugPrintEx( RECV_EVENT_HANDLER_INFO, "netmon TdiFilterRecvEventHandler g_bFiltering is false\n" ); 1655 | goto CALL_ORIGINAL_EVENT_HANDLER; 1656 | } 1657 | 1658 | pProcessNetWorkTrafficInfo = ReferenceProcessNetWorkTrafficInfo( pEventHandlerWrap->pEProcess ); 1659 | if( NULL == pProcessNetWorkTrafficInfo ) 1660 | { 1661 | DebugPrintEx( RECV_EVENT_HANDLER_INFO, "netmon TdiFilterRecvEventHandler ReferenceProcessNetWorkTrafficInfo return NULL\n" ); 1662 | goto CALL_ORIGINAL_EVENT_HANDLER; 1663 | } 1664 | 1665 | if( FALSE != pProcessNetWorkTrafficInfo->bStopRecv ) 1666 | { 1667 | ntStatus = STATUS_DATA_NOT_ACCEPTED; 1668 | DebugPrintEx( RECV_EVENT_HANDLER_INFO, "netmon TdiFilterRecvEventHandler bStopRecv = TRUE\n" ); 1669 | 1670 | goto RELEASE_PROCESS_IO_INFO_RETURN; 1671 | } 1672 | 1673 | DebugPrintEx( RECV_EVENT_HANDLER_INFO, "netmon TdiFilterRecvEventHandler call org handler\n" ); 1674 | 1675 | ntStatus = ( ( ClientEventReceive )pEventHandlerWrap->pOrgEventHandler )( 1676 | pEventHandlerWrap->pOrgEventContext, 1677 | ConnectionContext, 1678 | ReceiveFlags, 1679 | BytesIndicated, 1680 | BytesAvailable, 1681 | BytesTaken, 1682 | Tsdu, 1683 | IoRequestPacket 1684 | ); 1685 | 1686 | if( NULL != BytesTaken && 1687 | 0 != *BytesTaken ) 1688 | { 1689 | RecvedDataSize.LowPart = *BytesTaken; 1690 | RecvedDataSize.HighPart = 0; 1691 | 1692 | INTERLOCKED_COMPARE_EXCHANGE_ADD64( &pProcessNetWorkTrafficInfo->AllSuccRecvedDataSize, RecvedDataSize ); 1693 | INTERLOCKED_HALF_COMPARE_EXCHANGE_ADD64( &g_AllRecvedDataSize, RecvedDataSize ); 1694 | } 1695 | 1696 | if( STATUS_MORE_PROCESSING_REQUIRED != ntStatus ) 1697 | { 1698 | goto RELEASE_PROCESS_IO_INFO_RETURN; 1699 | } 1700 | 1701 | if( NULL == *IoRequestPacket ) 1702 | { 1703 | goto RELEASE_PROCESS_IO_INFO_RETURN; 1704 | } 1705 | 1706 | pIrpSp = IoGetCurrentIrpStackLocation( *IoRequestPacket ); 1707 | 1708 | pCompletionWrap = ( PTDI_COMPLETION_WRAP )ExAllocateFromNPagedLookasideList( &g_CompletionWrapList ); 1709 | 1710 | if( NULL == pCompletionWrap ) 1711 | { 1712 | goto RELEASE_PROCESS_IO_INFO_RETURN; 1713 | } 1714 | 1715 | pCompletionWrap->bSendOpera = FALSE; 1716 | pCompletionWrap->bWrap = TRUE; 1717 | pCompletionWrap->bAssocIrp = FALSE; 1718 | pCompletionWrap->pCompletionRoutine = pIrpSp->CompletionRoutine; 1719 | pCompletionWrap->pContext = pIrpSp->Context; 1720 | pCompletionWrap->Control = pIrpSp->Control; 1721 | pCompletionWrap->pEProcess = pEventHandlerWrap->pEProcess; 1722 | pCompletionWrap->pProcessNetWorkTrafficInfo = pEventHandlerWrap->pProcessNetWorkTrafficInfo; 1723 | 1724 | pIrpSp->CompletionRoutine = TdiFilterCompletion; 1725 | pIrpSp->Context = pCompletionWrap; 1726 | pIrpSp->Control = SL_INVOKE_ON_CANCEL | 1727 | SL_INVOKE_ON_SUCCESS | 1728 | SL_INVOKE_ON_ERROR; 1729 | 1730 | g_CompletionIrpCount ++; 1731 | DebugPrintEx( IRP_COMPLETION_INFO, "netmon TdiFilterRecvEventHandler completion count++ %d\n", g_CompletionIrpCount ); 1732 | 1733 | //Note: the recv event handler will add the BytesTaken number bytes to the record, and will add the next serial irp of this recv request recved bytes to record. by the ocmpletion wrap. 1734 | 1735 | RELEASE_PROCESS_IO_INFO_RETURN: 1736 | ReleaseProcessNetWorkTrafficInfo( pProcessNetWorkTrafficInfo ); 1737 | return ntStatus; 1738 | 1739 | CALL_ORIGINAL_EVENT_HANDLER: 1740 | return ( ( ClientEventReceive )pEventHandlerWrap->pOrgEventHandler )( 1741 | pEventHandlerWrap->pOrgEventContext, 1742 | ConnectionContext, 1743 | ReceiveFlags, 1744 | BytesIndicated, 1745 | BytesAvailable, 1746 | BytesTaken, 1747 | Tsdu, 1748 | IoRequestPacket 1749 | ); 1750 | } 1751 | 1752 | NTSTATUS TdiFilterChainedRecvHandler( 1753 | IN PVOID TdiEventContext, 1754 | IN CONNECTION_CONTEXT ConnectionContext, 1755 | IN ULONG ReceiveFlags, 1756 | IN ULONG ReceiveLength, 1757 | IN ULONG StartingOffset, 1758 | IN PMDL Tsdu, 1759 | IN PVOID TsduDescriptor 1760 | ) 1761 | { 1762 | PTDI_EVENT_HANDLER_WRAP pTdiEventHandlerWrap; 1763 | NTSTATUS ntStatus; 1764 | ClientEventChainedReceive pfChainedReceiveEventHandler; 1765 | LPVOID pOriginalContext; 1766 | LARGE_INTEGER RecvedDataSize; 1767 | 1768 | PPROCESS_NETWORK_TRAFFIC pProcessNetWorkTrafficInfo; 1769 | PPROCESS_NETWORK_TRAFFIC pProcessNetWorkTrafficInfoHost; 1770 | 1771 | ASSERT( NULL != TdiEventContext ); 1772 | 1773 | pTdiEventHandlerWrap = ( PTDI_EVENT_HANDLER_WRAP )TdiEventContext; 1774 | 1775 | DebugPrintEx( RECV_EVENT_HANDLER_INFO, "netmon Enter TdiFilterChainedRecvHandler\n" ); 1776 | 1777 | if( FALSE == MmIsAddressValid( pTdiEventHandlerWrap ) ) 1778 | { 1779 | DebugPrintEx( RECV_EVENT_HANDLER_INFO, "netmon TdiFilterChainedRecvHandler MmIsAddressValid return FALSE\n" ); 1780 | return STATUS_DATA_NOT_ACCEPTED; 1781 | } 1782 | 1783 | if( pTdiEventHandlerWrap->dwEventContextMark != TDI_EVENT_CONTEXT_MARK ) 1784 | { 1785 | DebugPrintEx( RECV_EVENT_HANDLER_INFO, "netmon TdiFilterChainedRecvHandler Mark is not correct \n" ); 1786 | return STATUS_DATA_NOT_ACCEPTED; 1787 | } 1788 | 1789 | ASSERT( NULL != pTdiEventHandlerWrap->pOrgEventHandler ); 1790 | ASSERT( NULL != pTdiEventHandlerWrap->pOrgEventContext ); 1791 | ASSERT( NULL != pTdiEventHandlerWrap->pEProcess ); 1792 | 1793 | pfChainedReceiveEventHandler = ( ClientEventChainedReceive )pTdiEventHandlerWrap->pOrgEventHandler; 1794 | pOriginalContext = pTdiEventHandlerWrap->pOrgEventContext; 1795 | 1796 | DebugPrintEx( RECV_EVENT_HANDLER_INFO, "netmon TdiFilterChainedRecvHandler original event handler 0x%0.8x \n", 1797 | pTdiEventHandlerWrap->pOrgEventHandler ); 1798 | 1799 | if ( FALSE == g_bFiltering ) 1800 | { 1801 | DebugPrintEx( RECV_EVENT_HANDLER_INFO, "netmon TdiFilterChainedRecvHandler FALSE == g_bFiltering\n" ); 1802 | goto CALL_ORG_EVENT_HANDLER; 1803 | } 1804 | 1805 | pProcessNetWorkTrafficInfo = ReferenceProcessNetWorkTrafficInfo( pTdiEventHandlerWrap->pEProcess ); 1806 | if( NULL == pProcessNetWorkTrafficInfo ) 1807 | { 1808 | DebugPrintEx( RECV_EVENT_HANDLER_INFO, "netmon TdiFilterChainedRecvHandler NULL == pProcessNetWorkTrafficInfo\n" ); 1809 | goto CALL_ORG_EVENT_HANDLER; 1810 | } 1811 | 1812 | if( FALSE != pProcessNetWorkTrafficInfo->bStopRecv ) 1813 | { 1814 | DebugPrintEx( RECV_EVENT_HANDLER_INFO, "netmon TdiFilterChainedRecvHandler FALSE != pProcessNetWorkTrafficInfo->bStopRecv\n" ); 1815 | ReleaseProcessNetWorkTrafficInfo( pProcessNetWorkTrafficInfo ); 1816 | return STATUS_DATA_NOT_ACCEPTED; 1817 | } 1818 | 1819 | DebugPrintEx( RECV_EVENT_HANDLER_INFO, "netmon TdiFilterChainedRecvHandler call pfChainedReceiveEventHandler\n" ); 1820 | 1821 | ntStatus = pfChainedReceiveEventHandler( 1822 | pOriginalContext, 1823 | ConnectionContext, 1824 | ReceiveFlags, 1825 | ReceiveLength, 1826 | StartingOffset, 1827 | Tsdu, 1828 | TsduDescriptor 1829 | ); 1830 | 1831 | if( NT_SUCCESS( ntStatus ) ) 1832 | { 1833 | RecvedDataSize.LowPart = ReceiveLength; 1834 | RecvedDataSize.HighPart = 0; 1835 | 1836 | pProcessNetWorkTrafficInfoHost = pTdiEventHandlerWrap->pProcessNetWorkTrafficInfo; 1837 | INTERLOCKED_COMPARE_EXCHANGE_ADD64( &pProcessNetWorkTrafficInfoHost->AllSuccRecvedDataSize, RecvedDataSize ); 1838 | INTERLOCKED_HALF_COMPARE_EXCHANGE_ADD64( &g_AllRecvedDataSize, RecvedDataSize ); 1839 | } 1840 | 1841 | DebugPrintEx( RECV_EVENT_HANDLER_INFO, "netmon leave TdiFilterChainedRecvHandler\n" ); 1842 | 1843 | ReleaseProcessNetWorkTrafficInfo( pProcessNetWorkTrafficInfo ); 1844 | return ntStatus; 1845 | 1846 | CALL_ORG_EVENT_HANDLER: 1847 | DebugPrintEx( RECV_EVENT_HANDLER_INFO, "netmon leave TdiFilterChainedRecvHandler direct call pfChainedReceiveEventHandler\n" ); 1848 | return pfChainedReceiveEventHandler( 1849 | pOriginalContext, 1850 | ConnectionContext, 1851 | ReceiveFlags, 1852 | ReceiveLength, 1853 | StartingOffset, 1854 | Tsdu, 1855 | TsduDescriptor 1856 | ); 1857 | } 1858 | 1859 | NTSTATUS TdiFilterRecvDatagramEventHandler( 1860 | IN PVOID TdiEventContext, 1861 | IN LONG SourceAddressLength, 1862 | IN PVOID SourceAddress, 1863 | IN LONG OptionsLength, 1864 | IN PVOID Options, 1865 | IN ULONG ReceiveDatagramFlags, 1866 | IN ULONG BytesIndicated, 1867 | IN ULONG BytesAvailable, 1868 | OUT ULONG *BytesTaken, 1869 | IN PVOID Tsdu, 1870 | OUT PIRP *IoRequestPacket 1871 | ) 1872 | { 1873 | NTSTATUS ntStatus; 1874 | ClientEventReceiveDatagram pfOrgEventHandler; 1875 | TDI_EVENT_HANDLER_WRAP *pEventHandlerWrap; 1876 | PPROCESS_NETWORK_TRAFFIC pProcessNetWorkTrafficInfo; 1877 | LPVOID pOrgEventContext; 1878 | LARGE_INTEGER RecvedDataSize; 1879 | 1880 | DebugPrintEx( RECV_EVENT_HANDLER_INFO, "netmon Enter TdiFilterRecvDatagramEventHandler \n" ); 1881 | 1882 | pEventHandlerWrap = ( PTDI_EVENT_HANDLER_WRAP )TdiEventContext; 1883 | 1884 | if( FALSE == MmIsAddressValid( pEventHandlerWrap ) ) 1885 | { 1886 | DebugPrintEx( RECV_EVENT_HANDLER_INFO, "netmon TdiFilterRecvDatagramEventHandler MmIsAddressValid return FALSE\n" ); 1887 | goto RETRUN_ERROR; 1888 | } 1889 | 1890 | if( TDI_EVENT_CONTEXT_MARK != pEventHandlerWrap->dwEventContextMark ) 1891 | { 1892 | DebugPrintEx( RECV_EVENT_HANDLER_INFO, "netmon TdiFilterRecvDatagramEventHandler TDI_EVENT_CONTEXT_MARK error\n" ); 1893 | goto RETRUN_ERROR; 1894 | } 1895 | 1896 | ASSERT( NULL != pEventHandlerWrap->pOrgEventHandler ); 1897 | 1898 | pfOrgEventHandler = ( ClientEventReceiveDatagram )pEventHandlerWrap->pOrgEventHandler; 1899 | pOrgEventContext = pEventHandlerWrap->pOrgEventContext; 1900 | 1901 | DebugPrintEx( RECV_EVENT_HANDLER_INFO, "netmon TdiFilterRecvDatagramEventHandler original event handler 0x%0.8x \n", 1902 | pfOrgEventHandler ); 1903 | 1904 | if( FALSE == g_bFiltering ) 1905 | { 1906 | DebugPrintEx( RECV_EVENT_HANDLER_INFO, "netmon TdiFilterRecvDatagramEventHandler g_bFiltering = FALSE\n" ); 1907 | goto CALL_ORIGINAL_EVENT_HANDLER; 1908 | } 1909 | 1910 | pProcessNetWorkTrafficInfo = ReferenceProcessNetWorkTrafficInfo( pEventHandlerWrap->pEProcess ); 1911 | if( NULL == pProcessNetWorkTrafficInfo ) 1912 | { 1913 | DebugPrintEx( RECV_EVENT_HANDLER_INFO, "netmon TdiFilterRecvDatagramEventHandler pProcessNetWorkTrafficInfo = NULL\n" ); 1914 | goto CALL_ORIGINAL_EVENT_HANDLER; 1915 | } 1916 | 1917 | if( FALSE != pProcessNetWorkTrafficInfo->bStopRecv ) 1918 | { 1919 | DebugPrintEx( RECV_EVENT_HANDLER_INFO, "netmon TdiFilterRecvDatagramEventHandler bStopRecv = TRUE\n" ); 1920 | ReleaseProcessNetWorkTrafficInfo( pProcessNetWorkTrafficInfo ); 1921 | return STATUS_DATA_NOT_ACCEPTED; 1922 | } 1923 | 1924 | DebugPrintEx( RECV_EVENT_HANDLER_INFO, "netmon TdiFilterRecvDatagramEventHandler call pfOrgEventHandler\n" ); 1925 | ntStatus = pfOrgEventHandler( pOrgEventContext, 1926 | SourceAddressLength, 1927 | SourceAddress, 1928 | OptionsLength, 1929 | Options, 1930 | ReceiveDatagramFlags, 1931 | BytesIndicated, 1932 | BytesAvailable, 1933 | BytesTaken, 1934 | Tsdu, 1935 | IoRequestPacket 1936 | ); 1937 | 1938 | RecvedDataSize.LowPart = BytesAvailable; 1939 | RecvedDataSize.HighPart = 0; 1940 | 1941 | INTERLOCKED_COMPARE_EXCHANGE_ADD64( 1942 | &pProcessNetWorkTrafficInfo->AllSuccRecvedDataSize, 1943 | RecvedDataSize ); 1944 | 1945 | INTERLOCKED_HALF_COMPARE_EXCHANGE_ADD64( 1946 | &g_AllRecvedDataSize, 1947 | RecvedDataSize ); 1948 | ReleaseProcessNetWorkTrafficInfo( pProcessNetWorkTrafficInfo ); 1949 | DebugPrintEx( RECV_EVENT_HANDLER_INFO, "netmon Leave TdiFilterRecvDatagramEventHandler \n" ); 1950 | return ntStatus; 1951 | 1952 | CALL_ORIGINAL_EVENT_HANDLER: 1953 | DebugPrintEx( RECV_EVENT_HANDLER_INFO, "netmon TdiFilterRecvDatagramEventHandler direct call pfOrgEventHandler\n" ); 1954 | return pfOrgEventHandler( pOrgEventContext, 1955 | SourceAddressLength, 1956 | SourceAddress, 1957 | OptionsLength, 1958 | Options, 1959 | ReceiveDatagramFlags, 1960 | BytesIndicated, 1961 | BytesAvailable, 1962 | BytesTaken, 1963 | Tsdu, 1964 | IoRequestPacket 1965 | ); 1966 | RETRUN_ERROR: 1967 | DebugPrintEx( RECV_EVENT_HANDLER_INFO, "netmon Leave TdiFilterRecvDatagramEventHandler \n" ); 1968 | return STATUS_DATA_NOT_ACCEPTED; 1969 | } 1970 | 1971 | NTSTATUS TdiFilterCompletion( PDEVICE_OBJECT pDeviceObject, PIRP pIrp, LPVOID pContext ) 1972 | { 1973 | NTSTATUS ntStatus; 1974 | PTDI_COMPLETION_WRAP pCompletionWrap; 1975 | PPROCESS_NETWORK_TRAFFIC pProcessNetWorkTrafficInfo; 1976 | PPROCESS_NETWORK_TRAFFIC pProcessNetWorkTrafficInfoHost; 1977 | LARGE_INTEGER TransferredDataSize; 1978 | PIRP pMasterIrp; 1979 | PIO_STACK_LOCATION pIrpSp; 1980 | 1981 | g_CompletionIrpCount --; 1982 | DebugPrintEx( IRP_COMPLETION_INFO, "netmon Enter TdiFilterCompletion completion-- count %d\n", g_CompletionIrpCount ); 1983 | 1984 | if( FALSE == MmIsAddressValid( pContext ) ) 1985 | { 1986 | ASSERT( FALSE ); 1987 | goto RETURN_SUCCESS; 1988 | } 1989 | 1990 | if( NULL == pIrp || 1991 | NULL == pContext ) 1992 | { 1993 | ASSERT( FALSE ); 1994 | goto RETURN_SUCCESS; 1995 | } 1996 | 1997 | ntStatus = pIrp->IoStatus.Status; 1998 | 1999 | pCompletionWrap = ( PTDI_COMPLETION_WRAP )pContext; 2000 | 2001 | ASSERT( NULL != pCompletionWrap->pEProcess ); 2002 | 2003 | DebugPrintEx( IRP_COMPLETION_INFO, "netmon TdiFilterCompletion status == 0x%0.8x \n", pIrp->IoStatus.Status ); 2004 | 2005 | if( NT_SUCCESS( ntStatus ) ) 2006 | { 2007 | pProcessNetWorkTrafficInfo = ReferenceProcessNetWorkTrafficInfo( pCompletionWrap->pEProcess ); 2008 | if( NULL == pProcessNetWorkTrafficInfo ) 2009 | { 2010 | DebugPrintEx( IRP_COMPLETION_INFO, "netmon TdiFilterCompletion ReferenceProcessNetWorkTrafficInfo return NULL, complete this irp \n" ); 2011 | goto COMPLETE_IRP; 2012 | } //Check the process of completion context validity. 2013 | 2014 | TransferredDataSize.LowPart = pIrp->IoStatus.Information; 2015 | TransferredDataSize.HighPart = 0; 2016 | 2017 | pProcessNetWorkTrafficInfoHost = ( PPROCESS_NETWORK_TRAFFIC )pCompletionWrap->pProcessNetWorkTrafficInfo; 2018 | 2019 | ASSERT( NULL != pProcessNetWorkTrafficInfoHost ); 2020 | ASSERT( pProcessNetWorkTrafficInfoHost == pProcessNetWorkTrafficInfo ); 2021 | 2022 | DebugPrintEx( IRP_COMPLETION_INFO, "netmon TdiFilterCompletion ReferenceProcessNetWorkTrafficInfo, updating traffic record TransferredDataSize %u\n", 2023 | TransferredDataSize.LowPart ); 2024 | if( pCompletionWrap->bSendOpera ) 2025 | { 2026 | INTERLOCKED_COMPARE_EXCHANGE_ADD64( &pProcessNetWorkTrafficInfoHost->AllSuccSendedDataSize, 2027 | TransferredDataSize ); 2028 | 2029 | INTERLOCKED_COMPARE_EXCHANGE_ADD64( &g_AllSendedDataSize, 2030 | TransferredDataSize ); 2031 | } 2032 | else 2033 | { 2034 | INTERLOCKED_COMPARE_EXCHANGE_ADD64( &pProcessNetWorkTrafficInfoHost->AllSuccRecvedDataSize, 2035 | TransferredDataSize ); 2036 | 2037 | INTERLOCKED_COMPARE_EXCHANGE_ADD64( &g_AllRecvedDataSize, 2038 | TransferredDataSize ); 2039 | } 2040 | 2041 | ReleaseProcessNetWorkTrafficInfo( pProcessNetWorkTrafficInfo ); 2042 | } 2043 | 2044 | COMPLETE_IRP: 2045 | DebugPrintEx( IRP_COMPLETION_INFO, "netmon TdiFilterCompletion COMPLETE_IRP \n" ); 2046 | ASSERT( FALSE == ( pCompletionWrap->bWrap && pCompletionWrap->bAssocIrp ) ); 2047 | 2048 | if( FALSE == pCompletionWrap->bWrap || 2049 | NULL == pCompletionWrap->pCompletionRoutine ) 2050 | { 2051 | goto CHECK_PENDING_RETURN; 2052 | } 2053 | 2054 | if( NT_SUCCESS( ntStatus ) ) 2055 | { 2056 | if( SL_INVOKE_ON_SUCCESS & pCompletionWrap->Control ) 2057 | { 2058 | goto CALL_ORG_COMPLETION_FUNCTION; 2059 | } 2060 | } 2061 | else 2062 | { 2063 | if( SL_INVOKE_ON_ERROR & pCompletionWrap->Control ) 2064 | { 2065 | goto CALL_ORG_COMPLETION_FUNCTION; 2066 | } 2067 | } 2068 | 2069 | if( TRUE == pIrp->Cancel ) 2070 | { 2071 | if( SL_INVOKE_ON_CANCEL | pCompletionWrap->Control ) 2072 | { 2073 | goto CALL_ORG_COMPLETION_FUNCTION; 2074 | } 2075 | } 2076 | 2077 | goto COMPLETE_ASSOCIATED_IRP; 2078 | 2079 | CHECK_PENDING_RETURN: 2080 | DebugPrintEx( IRP_COMPLETION_INFO, "netmon TdiFilterCompletion CHECK_PENDING_RETURN \n" ); 2081 | if( FALSE == pIrp->PendingReturned ) 2082 | { 2083 | goto COMPLETE_ASSOCIATED_IRP; 2084 | } 2085 | 2086 | if( TRUE == pCompletionWrap->bAssocIrp ) //If this irp is the associated irp, it don't need to have the pending flag. 2087 | { 2088 | goto COMPLETE_ASSOCIATED_IRP; 2089 | } 2090 | 2091 | if( TRUE == pCompletionWrap->bWrap ) //If have wraped completion routine, then left this pending flag seting operation to it. 2092 | { 2093 | goto COMPLETE_ASSOCIATED_IRP; 2094 | } 2095 | 2096 | IoGetCurrentIrpStackLocation( pIrp )->Control |= SL_PENDING_RETURNED; 2097 | 2098 | goto COMPLETE_ASSOCIATED_IRP; 2099 | 2100 | CALL_ORG_COMPLETION_FUNCTION: 2101 | DebugPrintEx( IRP_COMPLETION_INFO, "netmon TdiFilterCompletion CALL_ORG_COMPLETION_FUNCTION \n" ); 2102 | ntStatus = pCompletionWrap->pCompletionRoutine( pDeviceObject, 2103 | pIrp, 2104 | pCompletionWrap->pContext ); 2105 | 2106 | COMPLETE_ASSOCIATED_IRP: 2107 | DebugPrintEx( IRP_COMPLETION_INFO, "netmon TdiFilterCompletion COMPLETE_ASSOCIATED_IRP \n" ); 2108 | if( FALSE == pCompletionWrap->bAssocIrp ) 2109 | { 2110 | goto FREE_COMPLETION_WRAP; 2111 | } 2112 | 2113 | if( NULL == pIrp->AssociatedIrp.MasterIrp ) 2114 | { 2115 | goto FREE_COMPLETION_WRAP; 2116 | } 2117 | 2118 | pMasterIrp = pIrp->AssociatedIrp.MasterIrp; 2119 | pMasterIrp->IoStatus.Information += pIrp->IoStatus.Information; 2120 | pMasterIrp->IoStatus.Status = pIrp->IoStatus.Status; 2121 | 2122 | DebugPrintEx( IRP_CANCEL_INFO, "netmon TdiFilterCompletion MasterIrp 0x%0.8x Associated irp count is 0x%0.8x\n", 2123 | pMasterIrp, 2124 | pMasterIrp->AssociatedIrp.IrpCount ); 2125 | if( 1 == pMasterIrp->AssociatedIrp.IrpCount ) 2126 | { 2127 | INT32 nRet; 2128 | hash_key key; 2129 | 2130 | key.quad_part = make_hash_key( 0, ( DWORD )pMasterIrp ); 2131 | 2132 | IoSetCancelRoutine( pMasterIrp, NULL ); 2133 | 2134 | DebugPrintEx( IRP_CANCEL_INFO, "netmon TdiFilterCompletion del_hash_item 0x%0.8x \n", pMasterIrp ); 2135 | nRet = del_hash_item( &g_MasterIrpHash, key, NULL ); 2136 | DebugPrintEx( IRP_CANCEL_INFO, "netmon TdiFilterCompletion del_hash_item 0x%0.8x return 0x%0.8x\n", pMasterIrp, nRet ); 2137 | } 2138 | 2139 | DebugPrintEx( IRP_COMPLETION_INFO, "netmon TdiFilterCompletion master irp 0x%0.8x, master irp cancel routine 0x%0.8x, return length %d, status 0x%0.8x \n", 2140 | pMasterIrp, 2141 | pMasterIrp->CancelRoutine, 2142 | pIrp->IoStatus.Information, 2143 | pIrp->IoStatus.Status 2144 | ); 2145 | 2146 | FREE_COMPLETION_WRAP: 2147 | DebugPrintEx( IRP_COMPLETION_INFO, "netmon TdiFilterCompletion FREE_COMPLETION_WRAP\n" ); 2148 | ExFreeToNPagedLookasideList( &g_CompletionWrapList, pCompletionWrap ); 2149 | 2150 | ASSERT( KeGetCurrentIrql() <= DISPATCH_LEVEL ); 2151 | KeSetEvent( &g_EventCompletion, 0, FALSE ); 2152 | return ntStatus; 2153 | 2154 | RETURN_SUCCESS: 2155 | return STATUS_SUCCESS; 2156 | } 2157 | 2158 | NTSTATUS TdiFilterSyncSendProcess( PPROCESS_NETWORK_TRAFFIC pProcessNetWorkTrafficInfo, 2159 | PDEVICE_OBJECT pDeviceObject, 2160 | PIRP pIrp ) 2161 | { 2162 | NTSTATUS ntStatus; 2163 | PIO_STACK_LOCATION pIrpSp; 2164 | PTDI_FILTER_DEVICE_EXTENSION pDeviceExtension; 2165 | LARGE_INTEGER SendedSizeOneSec; 2166 | LARGE_INTEGER SendRequireSize; 2167 | PPROCESS_INFORMATION_RECORD pProcessInformation; 2168 | PTDI_COMPLETION_WRAP pCompletionWrap; 2169 | PIO_STACK_LOCATION pIrpSpNext; 2170 | PIRP pAssocIrp; 2171 | PMDL pMdlAlloced; 2172 | PMDL pMdl; 2173 | PBYTE pMdlVA; 2174 | DWORD dwSendLength; 2175 | DWORD dwSendedLength; 2176 | 2177 | DebugPrintEx( SYNC_SEND_IRP_PROCESS_INFO, "netmon enter TdiFilterSyncSendProcess\n" ); 2178 | 2179 | ASSERT( NULL == pIrp->AssociatedIrp.SystemBuffer ); 2180 | 2181 | pDeviceExtension = ( PTDI_FILTER_DEVICE_EXTENSION )pDeviceObject->DeviceExtension; 2182 | pIrpSp = IoGetCurrentIrpStackLocation( pIrp ); 2183 | 2184 | ASSERT( TDI_SEND == pIrpSp->MinorFunction || 2185 | TDI_SEND_DATAGRAM == pIrpSp->MinorFunction ); 2186 | 2187 | dwSendLength = ( DWORD )pIrpSp->Parameters.Others.Argument1; 2188 | 2189 | if( pProcessNetWorkTrafficInfo->SendingSpeed.QuadPart >= dwSendLength ) 2190 | { 2191 | if( pIrp->CurrentLocation <= 1 ) 2192 | { 2193 | ASSERT( FALSE ); 2194 | goto SKIP_CURRENT_STACK_LOCATION_CALL_PDO_DRIVER; 2195 | } 2196 | 2197 | for( ; ; ) 2198 | { 2199 | SendedSizeOneSec.QuadPart = pProcessNetWorkTrafficInfo->SendedSizeOneSec.QuadPart; 2200 | SendedSizeOneSec.QuadPart += dwSendLength; 2201 | 2202 | if( SendedSizeOneSec.QuadPart > 2203 | pProcessNetWorkTrafficInfo->SendingSpeed.QuadPart ) 2204 | { 2205 | if( pProcessNetWorkTrafficInfo->SendingSpeed.QuadPart >= dwSendLength ) 2206 | { 2207 | KeDelayExecutionThread( KernelMode, FALSE, &g_SendingDelayTime ); 2208 | continue; 2209 | } 2210 | else 2211 | { 2212 | break; 2213 | } 2214 | } 2215 | else 2216 | { 2217 | break; 2218 | } 2219 | } 2220 | 2221 | pCompletionWrap = ( PTDI_COMPLETION_WRAP )ExAllocateFromNPagedLookasideList( &g_CompletionWrapList ); 2222 | if( NULL == pCompletionWrap ) 2223 | { 2224 | goto SKIP_CURRENT_STACK_LOCATION_CALL_PDO_DRIVER; 2225 | } 2226 | 2227 | pProcessNetWorkTrafficInfo->SendedSizeOneSec.QuadPart += dwSendLength; 2228 | pCompletionWrap->bSendOpera = TRUE; 2229 | pCompletionWrap->bWrap = FALSE; 2230 | pCompletionWrap->bAssocIrp = FALSE; 2231 | pCompletionWrap->bSync = TRUE; 2232 | 2233 | pCompletionWrap->pEProcess = pProcessNetWorkTrafficInfo->pEProcess; 2234 | pCompletionWrap->pProcessNetWorkTrafficInfo = pProcessNetWorkTrafficInfo; //must got the process inforamtion reference. 2235 | 2236 | IoCopyCurrentIrpStackLocationToNext( pIrp ); 2237 | 2238 | IoSetCompletionRoutine( pIrp, 2239 | TdiFilterCompletion, 2240 | pCompletionWrap, 2241 | TRUE, 2242 | TRUE, 2243 | TRUE 2244 | ); 2245 | 2246 | g_CompletionIrpCount ++; 2247 | DebugPrintEx( IRP_COMPLETION_INFO, "netmon TdiFilterSyncSendProcess completion count++ %d\n", g_CompletionIrpCount ); 2248 | ntStatus = IoCallDriver( pDeviceExtension->pTdiDeviceObject, pIrp ); 2249 | 2250 | return ntStatus; 2251 | } 2252 | else 2253 | { 2254 | dwSendedLength = 0; 2255 | pMdl = pIrp->MdlAddress; 2256 | 2257 | if( NULL == pMdl ) 2258 | { 2259 | ASSERT( FALSE ); 2260 | goto SKIP_CURRENT_STACK_LOCATION_CALL_PDO_DRIVER; 2261 | } 2262 | 2263 | if( dwSendLength != MmGetMdlByteCount( pMdl ) ) 2264 | { 2265 | ASSERT( FALSE ); 2266 | goto SKIP_CURRENT_STACK_LOCATION_CALL_PDO_DRIVER; 2267 | } 2268 | 2269 | pMdlVA = MmGetMdlVirtualAddress( pMdl ); 2270 | 2271 | if( NULL == pMdlVA ) 2272 | { 2273 | ASSERT( pMdlVA ); 2274 | goto SKIP_CURRENT_STACK_LOCATION_CALL_PDO_DRIVER; 2275 | } 2276 | 2277 | ntStatus = STATUS_UNSUCCESSFUL; 2278 | 2279 | for( ; ; ) 2280 | { 2281 | if( dwSendedLength >= dwSendLength ) 2282 | { 2283 | return ntStatus; 2284 | } 2285 | 2286 | SendRequireSize.QuadPart = dwSendLength - dwSendedLength; 2287 | 2288 | if( pProcessNetWorkTrafficInfo->SendingSpeed.QuadPart < SendRequireSize.QuadPart ) 2289 | { 2290 | SendRequireSize.QuadPart = pProcessNetWorkTrafficInfo->SendingSpeed.QuadPart; 2291 | } 2292 | 2293 | pAssocIrp = IoMakeAssociatedIrp( pIrp, pDeviceExtension->pTdiDeviceObject->StackSize ); 2294 | if( NULL == pAssocIrp ) 2295 | { 2296 | goto SKIP_CURRENT_STACK_LOCATION_CALL_PDO_DRIVER; 2297 | } 2298 | 2299 | pMdlAlloced = IoAllocateMdl( 2300 | pMdlVA, 2301 | dwSendLength, 2302 | FALSE, 2303 | 0, 2304 | pAssocIrp 2305 | ); 2306 | 2307 | if( NULL == pMdlAlloced ) 2308 | { 2309 | IoFreeIrp( pAssocIrp ); 2310 | goto SKIP_CURRENT_STACK_LOCATION_CALL_PDO_DRIVER; 2311 | } 2312 | 2313 | InterlockedExchangeAdd( &pIrp->AssociatedIrp.IrpCount, 1 ); 2314 | 2315 | IoBuildPartialMdl( pIrp->MdlAddress, 2316 | pMdlAlloced, 2317 | pMdlVA + dwSendedLength, 2318 | SendRequireSize.LowPart ); 2319 | 2320 | dwSendedLength += SendRequireSize.LowPart; 2321 | 2322 | pIrpSpNext = IoGetNextIrpStackLocation( pAssocIrp ); 2323 | 2324 | pIrpSpNext->MajorFunction = pIrpSp->MajorFunction; 2325 | pIrpSpNext->MinorFunction = pIrpSp->MinorFunction; 2326 | pIrpSpNext->DeviceObject = pDeviceExtension->pTdiDeviceObject; 2327 | pIrpSpNext->FileObject = pIrpSp->FileObject; 2328 | 2329 | pIrpSpNext->Parameters.Others.Argument1 = ( PVOID )SendRequireSize.LowPart; 2330 | pIrpSpNext->Parameters.Others.Argument2 = pIrpSp->Parameters.Others.Argument2; 2331 | 2332 | pAssocIrp->MdlAddress = pMdlAlloced; 2333 | 2334 | for( ; ; ) 2335 | { 2336 | if( pProcessNetWorkTrafficInfo->SendedSizeOneSec.QuadPart + SendRequireSize.QuadPart > 2337 | pProcessNetWorkTrafficInfo->SendingSpeed.QuadPart ) 2338 | { 2339 | if( SendRequireSize.QuadPart <= pProcessNetWorkTrafficInfo->SendingSpeed.QuadPart ) 2340 | { 2341 | KeDelayExecutionThread( KernelMode, FALSE, &g_SendingDelayTime ); 2342 | continue; 2343 | } 2344 | else 2345 | { 2346 | break; 2347 | } 2348 | } 2349 | else 2350 | { 2351 | break; 2352 | } 2353 | } 2354 | 2355 | pCompletionWrap = ( PTDI_COMPLETION_WRAP )ExAllocateFromNPagedLookasideList( &g_CompletionWrapList ); 2356 | if( NULL == pCompletionWrap ) 2357 | { 2358 | goto SKIP_CURRENT_STACK_LOCATION_CALL_PDO_DRIVER; 2359 | } 2360 | 2361 | pProcessNetWorkTrafficInfo->SendedSizeOneSec.QuadPart += SendRequireSize.LowPart; 2362 | pCompletionWrap->bSendOpera = TRUE; 2363 | pCompletionWrap->bWrap = FALSE; //If synchronized operation, it must not have the completion routine. 2364 | pCompletionWrap->bAssocIrp = FALSE; 2365 | pCompletionWrap->bSync = TRUE; 2366 | 2367 | pCompletionWrap->pEProcess = pProcessNetWorkTrafficInfo->pEProcess; 2368 | pCompletionWrap->pProcessNetWorkTrafficInfo = pProcessNetWorkTrafficInfo; 2369 | 2370 | IoSetCompletionRoutine( pAssocIrp, 2371 | TdiFilterCompletion, 2372 | pCompletionWrap, 2373 | TRUE, 2374 | TRUE, 2375 | TRUE 2376 | ); 2377 | 2378 | g_CompletionIrpCount ++; 2379 | DebugPrintEx( IRP_COMPLETION_INFO, "netmon TdiFilterSyncSendProcess completion count++ %d\n", g_CompletionIrpCount ); 2380 | ntStatus = IoCallDriver( pIrpSpNext->DeviceObject, pAssocIrp ); 2381 | ASSERT( KeGetCurrentIrql() <= DISPATCH_LEVEL ); 2382 | } 2383 | } 2384 | 2385 | SKIP_CURRENT_STACK_LOCATION_CALL_PDO_DRIVER: 2386 | IoSkipCurrentIrpStackLocation( pIrp ); 2387 | return IoCallDriver( pDeviceExtension->pTdiDeviceObject, pIrp ); 2388 | } 2389 | 2390 | VOID ThreadWaitCompletion( PVOID pParam ) 2391 | { 2392 | for( ; ; ) 2393 | { 2394 | KeWaitForSingleObject( &g_EventCompletion, Executive, KernelMode, FALSE, NULL ); 2395 | 2396 | if( 0 == InterlockedExchangeAdd( &g_CompletionIrpCount, 0 ) ) 2397 | { 2398 | break; 2399 | } 2400 | } 2401 | } 2402 | 2403 | VOID ThreadSendingSpeedControl( PVOID pParam ) 2404 | { 2405 | NTSTATUS ntStatus; 2406 | BYTE OldIrql; 2407 | BOOL bWaitEvent; 2408 | DWORD dwConfiguredProcessIoInfoCount; 2409 | LIST_ENTRY AllProcessIoList; 2410 | LIST_ENTRY *pListEntry; 2411 | PPROCESS_NETWORK_TRAFFIC pProcessNetWorkTrafficInfo; 2412 | PIRP pIrp; 2413 | PIRP pIrpListed; 2414 | PLIST_ENTRY pIrpListEntry; 2415 | DWORD dwIrpCount; 2416 | PIO_STACK_LOCATION pIrpSp; 2417 | PIO_STACK_LOCATION pIrpSpNext; 2418 | PTDI_REQUEST_KERNEL_SEND pTdiSendParam; 2419 | PTDI_REQUEST_KERNEL_SENDDG pTdiSendDGParam; 2420 | PTDI_FILTER_DEVICE_EXTENSION pDeviceExtension; 2421 | DWORD dwTransferLength; 2422 | DWORD dwThreadWaitTime; 2423 | LARGE_INTEGER TransferredSize; 2424 | BOOL bIrpContextNotAlloced; 2425 | DWORD dwTransferred; 2426 | PMDL pMdl; 2427 | PMDL pAllocMdl; 2428 | PMDL pMdlNext; 2429 | PBYTE pIrpMdlVA; 2430 | BOOL bAssocIrpMakeDone; 2431 | PTDI_COMPLETION_WRAP pCompletionWrap; 2432 | DWORD dwIrpQueryLength; 2433 | PIRP pAssocIrp; 2434 | PIO_STACK_LOCATION pAssocIrpSp; 2435 | PIO_STACK_LOCATION pAssocIrpSpNext; 2436 | DWORD dwSendingSpeedHigh; 2437 | hash_key key; 2438 | INT32 nRet; 2439 | 2440 | bWaitEvent = TRUE; 2441 | dwConfiguredProcessIoInfoCount = 0; 2442 | 2443 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, "netmon Enter ThreadSendingSpeedControl\n" ); 2444 | 2445 | for( ; ; ) 2446 | { 2447 | if( TRUE == g_bThreadIrpProcessStop ) 2448 | { 2449 | InitializeListHead( &AllProcessIoList ); 2450 | KeAcquireSpinLock( &g_SpLockProcessNetWorkTrafficInfo, &OldIrql ); 2451 | 2452 | pListEntry = g_ProcessIoInfoList.Flink; 2453 | 2454 | for( ; ; ) 2455 | { 2456 | if( pListEntry == &g_ProcessIoInfoList ) 2457 | { 2458 | break; 2459 | } 2460 | 2461 | pProcessNetWorkTrafficInfo = ( PPROCESS_NETWORK_TRAFFIC )pListEntry; 2462 | 2463 | InterlockedExchangeAdd( 2464 | &pProcessNetWorkTrafficInfo->dwRefCount, 2465 | 1 ); 2466 | 2467 | InsertTailList( &AllProcessIoList, &pProcessNetWorkTrafficInfo->ListEntry ); 2468 | 2469 | pListEntry = pListEntry->Flink; 2470 | } 2471 | 2472 | KeReleaseSpinLock( &g_SpLockProcessNetWorkTrafficInfo, OldIrql ); 2473 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, "netmon ThreadSendingSpeedControl KeReleaseSpinLock g_SpLockProcessNetWorkTrafficInfo \n" ); 2474 | 2475 | if( IsListEmpty( &AllProcessIoList ) ) 2476 | { 2477 | break; 2478 | } 2479 | 2480 | for( ; ; ) 2481 | { 2482 | pListEntry = AllProcessIoList.Flink; 2483 | 2484 | if( pListEntry == &AllProcessIoList ) 2485 | { 2486 | break; 2487 | } 2488 | 2489 | RemoveEntryList( pListEntry ); 2490 | 2491 | pProcessNetWorkTrafficInfo = ( PPROCESS_NETWORK_TRAFFIC )CONTAINING_RECORD( pListEntry, PROCESS_NETWORK_TRAFFIC, ListEntry ); 2492 | 2493 | pIrp = DequeueIrp( &pProcessNetWorkTrafficInfo->IrpList, &pProcessNetWorkTrafficInfo->IrpListLock ); 2494 | 2495 | if( NULL == pIrp ) //If value is null, then reach the tail of the irp list. 2496 | { 2497 | continue; 2498 | } 2499 | 2500 | pIrpSp = IoGetCurrentIrpStackLocation( pIrp ); 2501 | pDeviceExtension = ( PTDI_FILTER_DEVICE_EXTENSION )pIrpSp->DeviceObject->DeviceExtension; 2502 | 2503 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, " ThreadSendingSpeedControl minor function is %d \n", pIrpSp->MinorFunction ); 2504 | 2505 | if( NULL == pIrp->AssociatedIrp.MasterIrp ) 2506 | { 2507 | IoSetCancelRoutine( pIrp, NULL ); 2508 | 2509 | key.quad_part = make_hash_key( 0, ( DWORD )pIrp ); 2510 | DebugPrintEx( IRP_CANCEL_INFO, "netmon TdiFilterCompletion del_hash_item 0x%0.8x \n", pIrp ); 2511 | 2512 | nRet = del_hash_item( &g_MasterIrpHash, key, NULL ); 2513 | DebugPrintEx( IRP_CANCEL_INFO, "netmon TdiFilterCompletion del_hash_item 0x%0.8x return 0x%0.8x\n", pIrp, nRet ); 2514 | } 2515 | IoSkipCurrentIrpStackLocation( pIrp ); 2516 | IoCallDriver( pDeviceExtension->pTdiDeviceObject, pIrp ); 2517 | ReleaseProcessNetWorkTrafficInfo( pProcessNetWorkTrafficInfo ); 2518 | } 2519 | 2520 | break; 2521 | } 2522 | 2523 | if( TRUE == bWaitEvent ) 2524 | { 2525 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, "netmon ThreadSendingSpeedControl wait new irp\n" ); 2526 | ASSERT( KeGetCurrentIrql() <= DISPATCH_LEVEL ); 2527 | KeWaitForSingleObject( &g_EventIrpListAdded, Executive, KernelMode, FALSE, &g_WaitNewIistItemTime ); 2528 | } 2529 | 2530 | if( 0 == dwConfiguredProcessIoInfoCount ) 2531 | { 2532 | KeDelayExecutionThread( KernelMode, FALSE, &g_ThreadWaitConfigProcTime ); 2533 | } 2534 | 2535 | bWaitEvent = TRUE; 2536 | dwConfiguredProcessIoInfoCount = 0; 2537 | 2538 | InitializeListHead( &AllProcessIoList ); 2539 | 2540 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, "netmon ThreadSendingSpeedControl KeAcquireSpinLock g_SpLockProcessNetWorkTrafficInfo \n" ); 2541 | KeAcquireSpinLock( &g_SpLockProcessNetWorkTrafficInfo, &OldIrql ); 2542 | 2543 | pListEntry = g_ProcessIoInfoList.Flink; 2544 | 2545 | for( ; ; ) 2546 | { 2547 | if( pListEntry == &g_ProcessIoInfoList ) 2548 | { 2549 | break; 2550 | } 2551 | 2552 | pProcessNetWorkTrafficInfo = ( PPROCESS_NETWORK_TRAFFIC )pListEntry; 2553 | if( pProcessNetWorkTrafficInfo->SendingSpeed.LowPart != 0xFFFFFFFF || 2554 | pProcessNetWorkTrafficInfo->SendingSpeed.HighPart != 0x7FFFFFFF ) 2555 | { 2556 | dwConfiguredProcessIoInfoCount ++; //Record the count of the send speed configured process. 2557 | } 2558 | 2559 | InterlockedExchangeAdd( 2560 | &pProcessNetWorkTrafficInfo->dwRefCount, 2561 | 1 ); 2562 | 2563 | InsertTailList( &AllProcessIoList, &pProcessNetWorkTrafficInfo->ListEntry ); 2564 | 2565 | pListEntry = pListEntry->Flink; 2566 | } 2567 | 2568 | KeReleaseSpinLock( &g_SpLockProcessNetWorkTrafficInfo, OldIrql ); 2569 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, "netmon ThreadSendingSpeedControl KeReleaseSpinLock g_SpLockProcessNetWorkTrafficInfo \n" ); 2570 | 2571 | if( IsListEmpty( &AllProcessIoList ) ) 2572 | { 2573 | continue; 2574 | } 2575 | 2576 | for( ; ; ) 2577 | { 2578 | PDEVICE_OBJECT pPdoDevice; 2579 | pListEntry = AllProcessIoList.Flink; 2580 | 2581 | ASSERT( TRUE == MmIsAddressValid( pListEntry ) ); 2582 | if( pListEntry == &AllProcessIoList ) 2583 | { 2584 | break; 2585 | } 2586 | 2587 | RemoveEntryList( pListEntry ); 2588 | 2589 | pProcessNetWorkTrafficInfo = ( PPROCESS_NETWORK_TRAFFIC )CONTAINING_RECORD( pListEntry, PROCESS_NETWORK_TRAFFIC, ListEntry ); 2590 | 2591 | pIrp = DequeueIrp( &pProcessNetWorkTrafficInfo->IrpList, &pProcessNetWorkTrafficInfo->IrpListLock ); 2592 | 2593 | if( NULL == pIrp ) //If value is null, then reach the tail of the irp list. 2594 | { 2595 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, "netmon ThreadSendingSpeedControl process: %d irp list is empty. \n", pProcessNetWorkTrafficInfo->dwProcessId ); 2596 | goto RELEASE_PROCESS_IO_INFO_GET_NEXT; 2597 | } 2598 | 2599 | bWaitEvent = FALSE; 2600 | dwIrpCount = pIrp->AssociatedIrp.IrpCount; 2601 | 2602 | KeDelayExecutionThread( KernelMode, FALSE, &g_SendingDelayTime ); 2603 | KeDelayExecutionThread( KernelMode, FALSE, &g_SendingDelayTime ); 2604 | KeDelayExecutionThread( KernelMode, FALSE, &g_SendingDelayTime ); 2605 | KeDelayExecutionThread( KernelMode, FALSE, &g_SendingDelayTime ); 2606 | KeDelayExecutionThread( KernelMode, FALSE, &g_SendingDelayTime ); 2607 | 2608 | if( 0 == dwIrpCount ) 2609 | { 2610 | pIrpSp = IoGetCurrentIrpStackLocation( pIrp ); 2611 | pDeviceExtension = ( PTDI_FILTER_DEVICE_EXTENSION )pIrpSp->DeviceObject->DeviceExtension; 2612 | pPdoDevice = pDeviceExtension->pTdiDeviceObject; 2613 | } 2614 | else 2615 | { 2616 | pIrpSp = IoGetNextIrpStackLocation( pIrp ); 2617 | pPdoDevice = pIrpSp->DeviceObject; 2618 | pDeviceExtension = NULL; 2619 | } 2620 | 2621 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, "netmon ThreadSendingSpeedControl irp count is %d\n, pdo device is 0x%0.8x\n, Marjor func 0x%0.8x\n, Minor func 0x%0.8x\n, param1 0x%0.8x, param2 0x%0.8x \n", 2622 | dwIrpCount, 2623 | pPdoDevice, 2624 | pIrpSp->MajorFunction, 2625 | pIrpSp->MinorFunction, 2626 | pIrpSp->Parameters.Others.Argument1, 2627 | pIrpSp->Parameters.Others.Argument2 2628 | ); 2629 | 2630 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, "ThreadSendingSpeedControl minor function is %d \n", pIrpSp->MinorFunction ); 2631 | 2632 | ASSERT( TDI_SEND == pIrpSp->MinorFunction || 2633 | TDI_SEND_DATAGRAM == pIrpSp->MinorFunction ); 2634 | 2635 | if( TDI_SEND == pIrpSp->MinorFunction ) 2636 | { 2637 | pTdiSendParam = ( PTDI_REQUEST_KERNEL_SEND )&pIrpSp->Parameters; 2638 | dwTransferLength = pTdiSendParam->SendLength; 2639 | } 2640 | else 2641 | { 2642 | pTdiSendDGParam = ( PTDI_REQUEST_KERNEL_SENDDG )&pIrpSp->Parameters; 2643 | dwTransferLength = pTdiSendDGParam->SendLength; 2644 | } 2645 | 2646 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, "pIrp->AssociatedIrp.SystemBuffer = 0x%0.8x, MinorFunction = %d \n", pIrp->AssociatedIrp.SystemBuffer, IoGetCurrentIrpStackLocation( pIrp )->MinorFunction ); 2647 | 2648 | //Control speeding speed by depart sending length and make these to associated irps, so this original irp become the master irp. 2649 | if( dwTransferLength > pProcessNetWorkTrafficInfo->SendingSpeed.QuadPart ) 2650 | { 2651 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, "netmon ThreadSendingSpeedControl process: %d packet send length %d is greater than send speed limit %d \n", 2652 | pProcessNetWorkTrafficInfo->dwProcessId, 2653 | dwTransferLength, 2654 | pProcessNetWorkTrafficInfo->SendingSpeed.LowPart ); 2655 | 2656 | if( 0 == dwIrpCount ) 2657 | { 2658 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, "netmon ThreadSendingSpeedControl irp is master irp \n" ); 2659 | 2660 | pMdl = pIrp->MdlAddress; 2661 | if( NULL == pMdl ) 2662 | { 2663 | ASSERT( FALSE ); 2664 | goto SKIP_CURRENT_STACK_LOCATION_RELEASE_PROCESS_NETWORK_TRAFFIC_GET_NEXT_PROCESS_NETWORK_TRAFFIC; 2665 | } 2666 | 2667 | if( dwTransferLength != MmGetMdlByteCount( pMdl ) ) 2668 | { 2669 | ASSERT( FALSE ); 2670 | goto SKIP_CURRENT_STACK_LOCATION_RELEASE_PROCESS_NETWORK_TRAFFIC_GET_NEXT_PROCESS_NETWORK_TRAFFIC; 2671 | } 2672 | 2673 | pIrpMdlVA = MmGetMdlVirtualAddress( pMdl );; 2674 | if( NULL == pIrpMdlVA ) 2675 | { 2676 | ASSERT( FALSE ); 2677 | goto SKIP_CURRENT_STACK_LOCATION_RELEASE_PROCESS_NETWORK_TRAFFIC_GET_NEXT_PROCESS_NETWORK_TRAFFIC; 2678 | } 2679 | 2680 | dwTransferred = 0; 2681 | 2682 | for( ; ; ) 2683 | { 2684 | if( dwTransferred >= dwTransferLength ) 2685 | { 2686 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, "netmon ThreadSendingSpeedControl irp is departing done\n" ); 2687 | goto RELEASE_PROCESS_IO_INFO_GET_NEXT; 2688 | } 2689 | 2690 | bAssocIrpMakeDone = FALSE; 2691 | dwIrpQueryLength = dwTransferLength - dwTransferred; 2692 | 2693 | if( pProcessNetWorkTrafficInfo->SendingSpeed.QuadPart < dwIrpQueryLength ) 2694 | { 2695 | //If sending speed is negative, then it limits the max data size of you departed fragment of the packet. 2696 | dwIrpQueryLength = pProcessNetWorkTrafficInfo->SendingSpeed.LowPart; 2697 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, "netmon ThreadSendingSpeedControl associated irp send length is %d \n", dwIrpQueryLength ); 2698 | dwSendingSpeedHigh = pProcessNetWorkTrafficInfo->SendingSpeed.HighPart; 2699 | } 2700 | else 2701 | { 2702 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, "netmon ThreadSendingSpeedControl associated irp send length is %d, reach tail \n", dwIrpQueryLength ); 2703 | dwSendingSpeedHigh = 0; 2704 | } 2705 | 2706 | ASSERT( NULL != pDeviceExtension ); 2707 | 2708 | pAssocIrp = IoMakeAssociatedIrp( 2709 | pIrp, 2710 | pDeviceExtension->pTdiDeviceObject->StackSize 2711 | ); 2712 | 2713 | if( NULL == pAssocIrp ) 2714 | { 2715 | goto RELEASE_ASSOCIATED_IRP; 2716 | } 2717 | 2718 | ASSERT( KeGetCurrentIrql() <= DISPATCH_LEVEL ); 2719 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, "netmon ThreadSendingSpeedControl allocated associated irp 0x%0.8x\n", 2720 | pAssocIrp ); 2721 | 2722 | pAllocMdl = IoAllocateMdl( 2723 | pIrpMdlVA, 2724 | dwTransferLength, 2725 | FALSE, 2726 | 0, 2727 | pAssocIrp 2728 | ); 2729 | 2730 | if( NULL == pAllocMdl ) 2731 | { 2732 | IoFreeIrp( pAssocIrp ); 2733 | goto RELEASE_ASSOCIATED_IRP; 2734 | } 2735 | 2736 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, "netmon ThreadSendingSpeedControl allocated mdl 0x%0.8x\n", 2737 | pAllocMdl ); 2738 | 2739 | ASSERT( dwIrpQueryLength + dwTransferred <= dwTransferLength ); 2740 | 2741 | IoBuildPartialMdl( 2742 | pIrp->MdlAddress, 2743 | pAllocMdl, 2744 | pIrpMdlVA - dwIrpQueryLength - dwTransferred + dwTransferLength, 2745 | dwIrpQueryLength 2746 | ); 2747 | 2748 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, "netmon ThreadSendingSpeedControl partial mdl builded addr 0x%0.8x, length %d\n", 2749 | pIrpMdlVA - dwIrpQueryLength - dwTransferred + dwTransferLength, 2750 | dwIrpQueryLength ); 2751 | 2752 | dwTransferred += dwIrpQueryLength; 2753 | 2754 | ASSERT( pAssocIrp->AssociatedIrp.MasterIrp == pIrp ); 2755 | 2756 | pAssocIrpSpNext = IoGetNextIrpStackLocation( pAssocIrp ); 2757 | 2758 | //This new associated irp do the same function of the original irp. 2759 | pAssocIrpSpNext->MajorFunction = pIrpSp->MajorFunction; 2760 | pAssocIrpSpNext->MinorFunction = pIrpSp->MinorFunction; 2761 | pAssocIrpSpNext->DeviceObject = pDeviceExtension->pTdiDeviceObject; 2762 | pAssocIrpSpNext->FileObject = pIrpSp->FileObject; 2763 | 2764 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, "netmon ThreadSendingSpeedControl set associating irp stack \n, Major func: %d\n Minor func: %d\n Device: 0x%0.8x\n, File object: 0x%0.8x \n", 2765 | pAssocIrpSpNext->MajorFunction, 2766 | pAssocIrpSpNext->MinorFunction, 2767 | pAssocIrpSpNext->DeviceObject, 2768 | pAssocIrpSpNext->FileObject 2769 | ); 2770 | 2771 | if( TDI_SEND == pAssocIrpSpNext->MinorFunction ) 2772 | { 2773 | PTDI_REQUEST_KERNEL_SEND pRequestSend; 2774 | pRequestSend = ( PTDI_REQUEST_KERNEL_SEND )&pAssocIrpSpNext->Parameters; 2775 | 2776 | pRequestSend->SendFlags = pTdiSendParam->SendFlags; 2777 | pRequestSend->SendLength = dwIrpQueryLength; 2778 | 2779 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, "netmon ThreadSendingSpeedControl set associating irp stack \n, send flag 0x%0.8x, send length %d \n", 2780 | pRequestSend->SendFlags, 2781 | pRequestSend->SendLength 2782 | ); 2783 | } 2784 | else 2785 | { 2786 | PTDI_REQUEST_KERNEL_SENDDG pRequestSendDG; 2787 | pRequestSendDG = ( PTDI_REQUEST_KERNEL_SENDDG )&pAssocIrpSpNext->Parameters; 2788 | 2789 | pRequestSendDG->SendDatagramInformation = pTdiSendDGParam->SendDatagramInformation;; 2790 | pRequestSendDG->SendLength = dwIrpQueryLength; 2791 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, "netmon ThreadSendingSpeedControl set associating irp stack \n, send datagram info 0x%0.8x, send length %d \n", 2792 | pRequestSendDG->SendDatagramInformation, 2793 | pRequestSendDG->SendLength 2794 | ); 2795 | } 2796 | 2797 | pAssocIrp->MdlAddress = pAllocMdl; 2798 | bAssocIrpMakeDone = TRUE; 2799 | 2800 | DebugPrintEx( IRP_CANCEL_INFO, "netmon ThreadSendingSpeedControl MasterIrp 0x%0.8x Associated irp count is 0x%0.8x\n", 2801 | pIrp, 2802 | pIrp->AssociatedIrp.IrpCount ); 2803 | InterlockedExchangeAdd( &pIrp->AssociatedIrp.IrpCount, 1 ); 2804 | 2805 | { 2806 | KIRQL IrpSpIrql; 2807 | hash_key key; 2808 | PDRIVER_CANCEL OldCancelRoutine; 2809 | 2810 | KeAcquireSpinLock( &pProcessNetWorkTrafficInfo->IrpListLock, &IrpSpIrql ); 2811 | key.quad_part = make_hash_key( 0, ( DWORD )pAssocIrp ); 2812 | 2813 | DebugPrintEx( IRP_CANCEL_INFO, "netmon TdiFilterInternalIoControl add_hash_item 0x%0.8x \n", pIrp ); 2814 | ntStatus = add_hash_item( &g_MasterIrpHash, key, ( hash_value )pProcessNetWorkTrafficInfo ); 2815 | DebugPrintEx( IRP_CANCEL_INFO, "netmon TdiFilterInternalIoControl add_hash_item return 0x%0.8x \n", ntStatus ); 2816 | 2817 | IoMarkIrpPending( pAssocIrp ); 2818 | OldCancelRoutine = IoSetCancelRoutine( pAssocIrp, TdiFilterCancel ); 2819 | ASSERT( NULL == OldCancelRoutine ); 2820 | 2821 | InsertTailList( &pProcessNetWorkTrafficInfo->IrpList, &pAssocIrp->Tail.Overlay.ListEntry ); 2822 | 2823 | if( pIrp->Cancel ) 2824 | { 2825 | OldCancelRoutine = IoSetCancelRoutine( pAssocIrp, NULL); 2826 | if( OldCancelRoutine ) 2827 | { 2828 | RemoveEntryList( &pIrp->Tail.Overlay.ListEntry ); 2829 | KeReleaseSpinLock( &pProcessNetWorkTrafficInfo->IrpListLock, IrpSpIrql ); 2830 | pAssocIrp->IoStatus.Status = STATUS_CANCELLED; 2831 | pAssocIrp->IoStatus.Information = 0; 2832 | IoCompleteRequest( pAssocIrp, IO_NO_INCREMENT ); 2833 | continue; 2834 | } 2835 | } 2836 | 2837 | KeReleaseSpinLock( &pProcessNetWorkTrafficInfo->IrpListLock, IrpSpIrql ); 2838 | } 2839 | 2840 | //delay this irp and its associated irps processing to next loop. 2841 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, "netmon ThreadSendingSpeedControl associated irp inserted to process irp list \n" ); 2842 | 2843 | RELEASE_ASSOCIATED_IRP: 2844 | if( FALSE == bAssocIrpMakeDone ) 2845 | { 2846 | //Release previous added associated irps. 2847 | for( ; ; ) 2848 | { 2849 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, "netmon ThreadSendingSpeedControl free associated irp %d \n", 2850 | pIrp->AssociatedIrp.IrpCount ); 2851 | 2852 | if( 0 == pIrp->AssociatedIrp.IrpCount ) 2853 | { 2854 | break; 2855 | } 2856 | 2857 | pIrpListEntry = ExInterlockedRemoveHeadList( &pProcessNetWorkTrafficInfo->IrpList, 2858 | &pProcessNetWorkTrafficInfo->IrpListLock ); 2859 | 2860 | 2861 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, "netmon ThreadSendingSpeedControl geted associated irp addr 0x%0.8x \n", 2862 | pIrpListEntry ); 2863 | 2864 | if( NULL == pIrpListEntry ) 2865 | { 2866 | ASSERT( FALSE ); 2867 | InterlockedExchangeAdd( &pIrp->AssociatedIrp.IrpCount, -1 ); 2868 | continue; 2869 | } 2870 | 2871 | pIrpListed = CONTAINING_RECORD( pIrpListEntry, IRP, Tail.Overlay.ListEntry ); 2872 | pMdl = pIrpListed->MdlAddress; 2873 | 2874 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, "netmon ThreadSendingSpeedControl geted mdl of associated irp 0x%0.8x \n", 2875 | pMdl ); 2876 | 2877 | for( ; ; ) 2878 | { 2879 | if( NULL == pMdl ) 2880 | { 2881 | break; 2882 | } 2883 | 2884 | pMdlNext = pMdl->Next; 2885 | 2886 | IoFreeMdl( pMdl ); 2887 | pMdl = pMdlNext; 2888 | 2889 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, "netmon ThreadSendingSpeedControl geted next mdl of associated irp 0x%0.8x \n", 2890 | pMdl ); 2891 | } 2892 | 2893 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, "netmon ThreadSendingSpeedControl free associated irp 0x%0.8x \n", 2894 | pIrpListed ); 2895 | IoFreeIrp( pIrpListed ); 2896 | InterlockedExchangeAdd( &pIrp->AssociatedIrp.IrpCount, -1 ); 2897 | } 2898 | 2899 | goto SKIP_CURRENT_STACK_LOCATION_RELEASE_PROCESS_NETWORK_TRAFFIC_GET_NEXT_PROCESS_NETWORK_TRAFFIC; 2900 | } 2901 | 2902 | continue; 2903 | } 2904 | } 2905 | } 2906 | 2907 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, "netmon ThreadSendingSpeedControl packet length lower than speed limit, or packet is associated irp \n" ); 2908 | 2909 | dwThreadWaitTime = 0; 2910 | 2911 | //If sending speed is positive, then it limits the data size of one send time 2912 | for( ; ; ) 2913 | { 2914 | if( pProcessNetWorkTrafficInfo->SendedSizeOneSec.QuadPart + dwTransferLength > pProcessNetWorkTrafficInfo->SendingSpeed.QuadPart ) 2915 | { 2916 | //Delay the sending function to longer time to match the seted sending speed. 2917 | if( dwTransferLength <= pProcessNetWorkTrafficInfo->SendingSpeed.QuadPart ) 2918 | { 2919 | KeDelayExecutionThread( KernelMode, FALSE, &g_SendingDelayTime ); 2920 | dwThreadWaitTime ++; 2921 | if( 5 > dwThreadWaitTime ) 2922 | { 2923 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, "netmon ThreadSendingSpeedControl one second send length is over than speed length wait 10 milli-senconds \n" ); 2924 | 2925 | continue; 2926 | } 2927 | 2928 | ExInterlockedInsertHeadList( &pProcessNetWorkTrafficInfo->IrpList, 2929 | &pIrp->Tail.Overlay.ListEntry, 2930 | &pProcessNetWorkTrafficInfo->IrpListLock ); 2931 | 2932 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, "netmon ThreadSendingSpeedControl waited 50 milli-seconds \n" ); 2933 | goto RELEASE_PROCESS_IO_INFO_GET_NEXT; 2934 | } 2935 | else 2936 | { 2937 | break; 2938 | } 2939 | } 2940 | else 2941 | { 2942 | break; 2943 | } 2944 | } 2945 | 2946 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, "netmon ThreadSendingSpeedControl send speed is correct\n" ); 2947 | 2948 | bIrpContextNotAlloced = FALSE; 2949 | pProcessNetWorkTrafficInfo->SendedSizeOneSec.QuadPart += dwTransferLength; 2950 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, "netmon ThreadSendingSpeedControl new send length one second is %d\n", 2951 | pProcessNetWorkTrafficInfo->SendedSizeOneSec.LowPart ); 2952 | 2953 | ASSERT( pIrpSp->MinorFunction == TDI_SEND || 2954 | pIrpSp->MinorFunction == TDI_SEND_DATAGRAM ); 2955 | 2956 | if( 0 != dwIrpCount ) 2957 | { 2958 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, "netmon ThreadSendingSpeedControl irp is associated, master irp is 0x%0.8x \n", 2959 | pIrp->AssociatedIrp.MasterIrp ); 2960 | 2961 | pCompletionWrap = ( PTDI_COMPLETION_WRAP )ExAllocateFromNPagedLookasideList( &g_CompletionWrapList ); 2962 | if( NULL != pCompletionWrap ) 2963 | { 2964 | pCompletionWrap->bSendOpera = TRUE; 2965 | pCompletionWrap->bWrap = FALSE; 2966 | pCompletionWrap->bAssocIrp = TRUE; 2967 | pCompletionWrap->pEProcess = pProcessNetWorkTrafficInfo->pEProcess; 2968 | pCompletionWrap->pProcessNetWorkTrafficInfo = pProcessNetWorkTrafficInfo; 2969 | } 2970 | else 2971 | { 2972 | bIrpContextNotAlloced = TRUE; 2973 | } 2974 | 2975 | pIrpSp = IoGetNextIrpStackLocation( pIrp ); 2976 | ASSERT( NULL != pIrpSp->DeviceObject ); 2977 | 2978 | if( FALSE == bIrpContextNotAlloced ) 2979 | { 2980 | IoSetCompletionRoutine( pIrp, 2981 | TdiFilterCompletion, 2982 | pCompletionWrap, 2983 | TRUE, 2984 | TRUE, 2985 | TRUE 2986 | ); 2987 | 2988 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, "netmon ThreadSendingSpeedControl allocate completion wrap, call pdo 0x%0.8x driver \n", 2989 | ( pIrpSp - 1 )->DeviceObject ); 2990 | 2991 | g_CompletionIrpCount ++; 2992 | DebugPrintEx( IRP_COMPLETION_INFO, "netmon TdiFilterSyncSendProcess completion count++ %d\n", g_CompletionIrpCount ); 2993 | IoCallDriver( pIrpSp->DeviceObject, pIrp ); 2994 | ASSERT( KeGetCurrentIrql() <= DISPATCH_LEVEL ); 2995 | } 2996 | else 2997 | { 2998 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, "netmon ThreadSendingSpeedControl can't allocate completion wrap, call pdo 0x%0.8x driver \n", 2999 | ( pIrpSp - 1 )->DeviceObject ); 3000 | 3001 | IoCallDriver( pIrpSp->DeviceObject, pIrp ); 3002 | } 3003 | 3004 | goto RELEASE_PROCESS_IO_INFO_GET_NEXT; 3005 | } 3006 | 3007 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, "netmon ThreadSendingSpeedControl irp is not associated current stack location is %d\n", 3008 | pIrp->CurrentLocation ); 3009 | 3010 | if( 1 >= pIrp->CurrentLocation ) 3011 | { 3012 | ASSERT( FALSE ); 3013 | goto SKIP_CURRENT_STACK_LOCATION_RELEASE_PROCESS_NETWORK_TRAFFIC_GET_NEXT_PROCESS_NETWORK_TRAFFIC; 3014 | } 3015 | 3016 | pCompletionWrap = ( PTDI_COMPLETION_WRAP )ExAllocateFromNPagedLookasideList( &g_CompletionWrapList ); 3017 | 3018 | if( NULL == pCompletionWrap ) 3019 | { 3020 | goto SKIP_CURRENT_STACK_LOCATION_RELEASE_PROCESS_NETWORK_TRAFFIC_GET_NEXT_PROCESS_NETWORK_TRAFFIC; 3021 | } 3022 | 3023 | pCompletionWrap->bSendOpera = TRUE; 3024 | pCompletionWrap->bWrap = FALSE; 3025 | pCompletionWrap->bAssocIrp = FALSE; 3026 | pCompletionWrap->pEProcess = pProcessNetWorkTrafficInfo->pEProcess; 3027 | pCompletionWrap->pProcessNetWorkTrafficInfo = pProcessNetWorkTrafficInfo; 3028 | 3029 | IoCopyCurrentIrpStackLocationToNext( pIrp ); 3030 | 3031 | IoSetCompletionRoutine( pIrp, 3032 | TdiFilterCompletion, 3033 | pCompletionWrap, 3034 | TRUE, 3035 | TRUE, 3036 | TRUE 3037 | ); 3038 | 3039 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, "netmon ThreadSendingSpeedControl add completion wrap, call pdo deivce 0x%0.8x driver\n", 3040 | pDeviceExtension->pTdiDeviceObject ); 3041 | 3042 | IoSetCancelRoutine( pIrp, NULL ); 3043 | 3044 | key.quad_part = make_hash_key( 0, ( DWORD )pIrp ); 3045 | DebugPrintEx( IRP_CANCEL_INFO, "netmon ThreadSendingSpeedControl del_hash_item 0x%0.8x \n", pIrp ); 3046 | 3047 | nRet = del_hash_item( &g_MasterIrpHash, key, NULL ); 3048 | DebugPrintEx( IRP_CANCEL_INFO, "netmon ThreadSendingSpeedControl del_hash_item 0x%0.8x return 0x%0.8x\n", pIrp, nRet ); 3049 | 3050 | g_CompletionIrpCount ++; 3051 | DebugPrintEx( IRP_COMPLETION_INFO, "netmon ThreadSendingSpeedControl completion count++ %d\n", g_CompletionIrpCount ); 3052 | IoCallDriver( pDeviceExtension->pTdiDeviceObject, pIrp ); 3053 | ASSERT( KeGetCurrentIrql() <= DISPATCH_LEVEL ); 3054 | goto RELEASE_PROCESS_IO_INFO_GET_NEXT; 3055 | 3056 | SKIP_CURRENT_STACK_LOCATION_RELEASE_PROCESS_NETWORK_TRAFFIC_GET_NEXT_PROCESS_NETWORK_TRAFFIC: 3057 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, "netmon ThreadSendingSpeedControl SKIP_CURRENT_STACK_LOCATION_RELEASE_PROCESS_NETWORK_TRAFFIC_GET_NEXT_PROCESS_NETWORK_TRAFFIC\n" ); 3058 | 3059 | IoSkipCurrentIrpStackLocation( pIrp ); 3060 | IoCallDriver( pDeviceExtension->pTdiDeviceObject, pIrp ); 3061 | 3062 | RELEASE_PROCESS_IO_INFO_GET_NEXT: 3063 | 3064 | DebugPrintEx( SEND_SPEED_CONTROL_INFO, "netmon ThreadSendingSpeedControl RELEASE_PROCESS_IO_INFO_GET_NEXT\n" ); 3065 | ReleaseProcessNetWorkTrafficInfo( pProcessNetWorkTrafficInfo ); 3066 | continue; 3067 | } 3068 | } 3069 | 3070 | PsTerminateSystemThread( STATUS_SUCCESS ); 3071 | } 3072 | 3073 | VOIDreadUpdateProcessIoState( PVOID pParam ) 3074 | { 3075 | TATUS ntStatus; 3076 | RD dwProcessInfoLength; 3077 | ICODE_STRING ProcessImageName; 3078 | STEM_PROCESSES pSystemProcesses; 3079 | OCESS_INFORMATION_RECORD pProcessInformation; 3080 | OCESS_INFORMATION_LIST_ENTRY pProcessInfoListEntry; 3081 | OCESS_NETWORK_TRAFFIC pProcessNetWorkTrafficInfo; 3082 | RD dwProcessId; 3083 | STEM_PROCESSES pSystemProcess; 3084 | E OldIrql; 3085 | ST_ENTRY pListEntry; 3086 | CODE_STRING ProcessImageFilePath; 3087 | R bProcessInfoFinded; 3088 | GE_INTEGER SendingSpeed; 3089 | L bStopRecv; 3090 | L bStopSend; 3091 | 3092 | cessImageName = NULL; 3093 | stemProcesses = NULL; 3094 | 3095 | ( ; ; ) 3096 | 3097 | DebugPrintEx( PROCESS_COMMON_INFO, "netmon ThreadUpdateProcessIoState wait new process\n" ); 3098 | if( TRUE == g_bThreadUpdateConfigStop ) 3099 | { 3100 | break; 3101 | }; 3102 | 3103 | ASSERT( KeGetCurrentIrql() <= DISPATCH_LEVEL ); 3104 | KeWaitForSingleObject( &g_EventProcessInformationAdded, Executive, KernelMode, FALSE, NULL ); //Waiting util process control information or process netword record added, deleted. 3105 | 3106 | for( ; ; ) 3107 | { 3108 | ntStatus = ZwQuerySystemInformation( 3109 | SystemProcessInformation, 3110 | NULL, 3111 | 0, 3112 | &dwProcessInfoLength 3113 | ); 3114 | 3115 | if( STATUS_INFO_LENGTH_MISMATCH != ntStatus ) 3116 | { 3117 | break; 3118 | } 3119 | 3120 | if( NULL != pSystemProcesses ) 3121 | { 3122 | ExFreePoolWithTag( pSystemProcesses, 0 ); 3123 | } 3124 | 3125 | pSystemProcesses = AllocZeroPoolWithTag( NonPagedPool, dwProcessInfoLength ); 3126 | if( NULL == pSystemProcesses ) 3127 | { 3128 | ntStatus = STATUS_INSUFFICIENT_RESOURCES; 3129 | break; 3130 | } 3131 | 3132 | ntStatus = ZwQuerySystemInformation( SystemProcessInformation, 3133 | pSystemProcesses, 3134 | dwProcessInfoLength, 3135 | &dwProcessInfoLength ); 3136 | 3137 | if( STATUS_INFO_LENGTH_MISMATCH != ntStatus ) 3138 | { 3139 | break; 3140 | } 3141 | } 3142 | 3143 | RELE_SYSTEM_PROCESSES_BUFF_WAIT_NEXT_PROCESS: 3144 | if( !NT_SUCCESS( ntStatus ) ) 3145 | { 3146 | if( NULL != pSystemProcesses ) 3147 | { 3148 | ExFreePoolWithTag( pSystemProcesses, 0 ); 3149 | pSystemProcesses = NULL; 3150 | } 3151 | continue; 3152 | } 3153 | 3154 | if( NULL == ProcessImageName ) 3155 | { 3156 | ProcessImageName = AllocZeroPoolWithTag( 3157 | NonPagedPool, 3158 | PROCESS_IMAGE_FILE_PATH_INFO_MAX_LENGTH 3159 | ); 3160 | if( NULL == ProcessImageName ) 3161 | { 3162 | goto RELEASE_SYSTEM_PROCESSES_BUFF_WAIT_NEXT_PROCESS; 3163 | } 3164 | } 3165 | 3166 | pSystemProcess = pSystemProcesses; 3167 | 3168 | for( ; ; ) 3169 | { 3170 | dwProcessId = pSystemProcess->ProcessId; 3171 | 3172 | if( dwProcessId == SYSTEM_IDLE_PROCESS_ID || 3173 | dwProcessId == SYSTEM_SYSTEM_PROCESS_ID ) 3174 | { 3175 | goto LOCATE_NEXT_SYSTEM_PROCESS; 3176 | } 3177 | 3178 | RtlZeroMemory( ProcessImageName, PROCESS_IMAGE_FILE_PATH_INFO_MAX_LENGTH ); 3179 | 3180 | ntStatus = GetProcessImagePath( 3181 | pSystemProcess->ProcessId, 3182 | ProcessImageName, 3183 | PROCESS_IMAGE_FILE_PATH_INFO_MAX_LENGTH 3184 | ); 3185 | 3186 | if( !NT_SUCCESS( ntStatus ) ) 3187 | { 3188 | goto LOCATE_NEXT_SYSTEM_PROCESS; 3189 | } 3190 | 3191 | bProcessInfoFinded = FALSE; 3192 | 3193 | KeEnterCriticalRegion(); 3194 | ExAcquireResourceExclusive( &g_SyncResource, TRUE ); 3195 | 3196 | pListEntry = g_ProcessInformationList.Flink; 3197 | 3198 | for( ; ; ) 3199 | { 3200 | if( pListEntry == &g_ProcessInformationList ) 3201 | { 3202 | break; 3203 | } 3204 | 3205 | pProcessInfoListEntry = ( PPROCESS_INFORMATION_LIST_ENTRY )pListEntry; 3206 | pProcessInformation = pProcessInfoListEntry->pProcessInformation; 3207 | 3208 | RtlInitUnicodeString( &ProcessImageFilePath, pProcessInformation->szNativeImageFileName ); 3209 | 3210 | if( TRUE == RtlEqualUnicodeString( 3211 | &ProcessImageFilePath, 3212 | ProcessImageName, 3213 | TRUE 3214 | ) ) 3215 | { 3216 | SendingSpeed.QuadPart = pProcessInformation->SendingSpeed.QuadPart; 3217 | bStopRecv = pProcessInformation->bStopRecv; 3218 | bStopSend = pProcessInformation->bStopSend; 3219 | 3220 | bProcessInfoFinded = TRUE; 3221 | break; 3222 | } 3223 | 3224 | pListEntry = pListEntry->Flink; 3225 | } 3226 | 3227 | ExReleaseResource( &g_SyncResource ); 3228 | KeLeaveCriticalRegion(); 3229 | 3230 | DebugPrintEx( PROCESS_COMMON_INFO, "netmon ThreadUpdateProcessIoState KeAcquireSpinLock g_SpLockProcessNetWorkTrafficInfo \n" ); 3231 | KeAcquireSpinLock( &g_SpLockProcessNetWorkTrafficInfo, &OldIrql ); 3232 | 3233 | pListEntry = g_ProcessIoInfoList.Flink; 3234 | 3235 | for( ; ; ) 3236 | { 3237 | if( pListEntry == &g_ProcessIoInfoList ) 3238 | { 3239 | break; 3240 | } 3241 | 3242 | pProcessNetWorkTrafficInfo = ( PPROCESS_NETWORK_TRAFFIC )pListEntry; 3243 | 3244 | if( pProcessNetWorkTrafficInfo->dwProcessId == pSystemProcess->ProcessId ) 3245 | { 3246 | LARGE_INTEGER InitializeValue; 3247 | 3248 | if( TRUE == bProcessInfoFinded ) 3249 | { 3250 | 3251 | pProcessNetWorkTrafficInfo->bStopRecv = bStopRecv; 3252 | pProcessNetWorkTrafficInfo->bStopSend = bStopSend; 3253 | 3254 | if( 0 == SendingSpeed.QuadPart ) 3255 | { 3256 | InitializeValue.LowPart = 0xFFFFFFFF; 3257 | InitializeValue.HighPart = 0x7FFFFFFF; 3258 | } 3259 | else 3260 | { 3261 | InitializeValue.QuadPart = SendingSpeed.QuadPart; 3262 | } 3263 | 3264 | INTERLOCKED_COMPARE_EXCHANGE64( &pProcessNetWorkTrafficInfo->SendingSpeed, InitializeValue ); 3265 | } 3266 | else 3267 | { 3268 | 3269 | pProcessNetWorkTrafficInfo->bStopRecv = FALSE; 3270 | pProcessNetWorkTrafficInfo->bStopSend = FALSE; 3271 | 3272 | InitializeValue.LowPart = 0xFFFFFFFF; 3273 | InitializeValue.HighPart = 0x7FFFFFFF; 3274 | 3275 | INTERLOCKED_COMPARE_EXCHANGE64( &pProcessNetWorkTrafficInfo->SendingSpeed, InitializeValue ); 3276 | } 3277 | 3278 | break; //Only one process control information and one process network traffic record match one process. 3279 | } 3280 | pListEntry = pListEntry->Flink; 3281 | } 3282 | 3283 | KeReleaseSpinLock( &g_SpLockProcessNetWorkTrafficInfo, OldIrql ); 3284 | DebugPrintEx( PROCESS_COMMON_INFO, "netmon ThreadUpdateProcessIoState KeReleaseSpinLock g_SpLockProcessNetWorkTrafficInfo \n" ); 3285 | 3286 | LOCANEXT_SYSTEM_PROCESS: 3287 | if( 0 == pSystemProcess->NextEntryDelta ) 3288 | { 3289 | break; 3290 | } 3291 | pSystemProcess = ( PSYSTEM_PROCESSES )( ( PBYTE )pSystemProcess + pSystemProcess->NextEntryDelta ); 3292 | ASSERT( TRUE == MmIsAddressValid( pSystemProcess ) ); 3293 | } // foreach system process. 3294 | 3295 | 3296 | NULL != ProcessImageName ) 3297 | 3298 | ExFreePoolWithTag( ProcessImageName, 0 ); 3299 | 3300 | 3301 | NULL != pSystemProcesses ) 3302 | 3303 | ExFreePoolWithTag( pSystemProcesses, 0 ); 3304 | 3305 | 3306 | erminateSystemThread( STATUS_SUCCESS ); 3307 | } 3308 | 3309 | VOIDmerDpcProcess( PKDPC pDpc, PVOID pEProcess, PVOID SystemArgument1 , PVOID SystemArgument2 ) 3310 | { 3311 | ST_ENTRY pListEntry; 3312 | OCESS_NETWORK_TRAFFIC pProcessNetWorkTrafficInfo; 3313 | GE_INTEGER UpdatedValue; 3314 | 3315 | ugPrintEx( TIMER_DPC_INFO, "Enter netmon TimerDpcProcess" ); 3316 | 3317 | cquireSpinLockAtDpcLevel( &g_SpLockProcessNetWorkTrafficInfo ); 3318 | 3319 | stEntry = g_ProcessIoInfoList.Flink; 3320 | 3321 | ( ; ; ) 3322 | 3323 | if( pListEntry == &g_ProcessIoInfoList ) 3324 | { 3325 | break; 3326 | } 3327 | 3328 | pProcessNetWorkTrafficInfo = ( PPROCESS_NETWORK_TRAFFIC )pListEntry; 3329 | 3330 | if( pProcessNetWorkTrafficInfo->pEProcess == pEProcess ) 3331 | { 3332 | InterlockedExchangeAdd( &pProcessNetWorkTrafficInfo->dwRefCount, 1 ); 3333 | 3334 | UpdatedValue.QuadPart = 0; 3335 | 3336 | INTERLOCKED_COMPARE_EXCHANGE64( 3337 | &pProcessNetWorkTrafficInfo->SendedSizeOneSec, 3338 | UpdatedValue 3339 | ); 3340 | 3341 | if( pProcessNetWorkTrafficInfo->AllSuccSendedDataSize.QuadPart >= 3342 | pProcessNetWorkTrafficInfo->AllSuccSendedDataSizePrev.QuadPart ) 3343 | { 3344 | UpdatedValue.QuadPart = pProcessNetWorkTrafficInfo->AllSuccSendedDataSize.QuadPart - 3345 | pProcessNetWorkTrafficInfo->AllSuccSendedDataSizePrev.QuadPart; 3346 | 3347 | INTERLOCKED_COMPARE_EXCHANGE64( 3348 | &pProcessNetWorkTrafficInfo->SuccSendedDataSizeOnce, 3349 | UpdatedValue 3350 | ); 3351 | } 3352 | 3353 | INTERLOCKED_COMPARE_EXCHANGE64( 3354 | &pProcessNetWorkTrafficInfo->AllSuccSendedDataSizePrev, 3355 | pProcessNetWorkTrafficInfo->AllSuccSendedDataSize 3356 | ); 3357 | 3358 | if( pProcessNetWorkTrafficInfo->AllSuccRecvedDataSize.QuadPart >= 3359 | pProcessNetWorkTrafficInfo->AllSuccRecvedDataSizePrev.QuadPart ) 3360 | { 3361 | UpdatedValue.QuadPart = pProcessNetWorkTrafficInfo->AllSuccRecvedDataSize.QuadPart - 3362 | pProcessNetWorkTrafficInfo->AllSuccRecvedDataSizePrev.QuadPart; 3363 | 3364 | INTERLOCKED_COMPARE_EXCHANGE64( 3365 | &pProcessNetWorkTrafficInfo->SuccRecvedDataSizeOnce, 3366 | UpdatedValue 3367 | ); 3368 | } 3369 | 3370 | INTERLOCKED_COMPARE_EXCHANGE64( 3371 | &pProcessNetWorkTrafficInfo->AllSuccRecvedDataSizePrev, 3372 | pProcessNetWorkTrafficInfo->AllSuccRecvedDataSize 3373 | ); 3374 | 3375 | KeSetTimer( pProcessNetWorkTrafficInfo->pTimer, 3376 | g_TimerElapse, 3377 | pProcessNetWorkTrafficInfo->pDpc ); //Loop the timer 3378 | 3379 | InterlockedExchangeAdd( &pProcessNetWorkTrafficInfo->dwRefCount, -1 ); 3380 | break; 3381 | } 3382 | pListEntry = pListEntry->Flink; 3383 | 3384 | 3385 | eleaseSpinLockFromDpcLevel( &g_SpLockProcessNetWorkTrafficInfo ); 3386 | 3387 | ugPrintEx( TIMER_DPC_INFO, "Leave netmon TimerDpcProcess" ); 3388 | } 3389 | 3390 | VOIDleteProcessIoInfo( DWORD dwParentId, DWORD dwProcessId, BOOL bCreate ) 3391 | { 3392 | QL OldIrql; 3393 | ST_ENTRY pListEntry; 3394 | OCESS_NETWORK_TRAFFIC pProcessNetWorkTrafficInfo; 3395 | 3396 | ugPrintEx( PROCESS_COMMON_INFO, "netmon enter DeleteProcessIoInfo \n" ); 3397 | ( FALSE == bCreate ) 3398 | 3399 | DebugPrintEx( PROCESS_COMMON_INFO, "netmon DeleteProcessIoInfo KeAcquireSpinLock g_SpLockProcessNetWorkTrafficInfo \n" ); 3400 | KeAcquireSpinLock( &g_SpLockProcessNetWorkTrafficInfo, &OldIrql ); 3401 | 3402 | pListEntry = g_ProcessIoInfoList.Flink; 3403 | 3404 | for( ; ; ) 3405 | { 3406 | if( pListEntry == &g_ProcessIoInfoList ) 3407 | { 3408 | break; 3409 | } 3410 | 3411 | pProcessNetWorkTrafficInfo = ( PPROCESS_NETWORK_TRAFFIC )pListEntry; 3412 | if ( pProcessNetWorkTrafficInfo->dwProcessId == dwProcessId ) 3413 | { 3414 | DWORD dwCurRefCount; 3415 | 3416 | RemoveEntryList( pListEntry ); 3417 | 3418 | KeCancelTimer( pProcessNetWorkTrafficInfo->pTimer ); 3419 | 3420 | dwCurRefCount = InterlockedExchangeAdd( &pProcessNetWorkTrafficInfo->dwRefCount, -1 ); 3421 | if ( 1 == dwCurRefCount ) 3422 | { 3423 | ExFreePoolWithTag( pProcessNetWorkTrafficInfo->pDpc, 0 ); 3424 | ExFreePoolWithTag( pProcessNetWorkTrafficInfo->pTimer, 0 ); 3425 | ExFreePoolWithTag( pProcessNetWorkTrafficInfo, 0 ); 3426 | } 3427 | else 3428 | { 3429 | ASSERT( dwCurRefCount > 1 ); 3430 | } 3431 | break; 3432 | } 3433 | 3434 | pListEntry = pListEntry->Flink; 3435 | } 3436 | 3437 | KeReleaseSpinLock( &g_SpLockProcessNetWorkTrafficInfo, OldIrql ); 3438 | DebugPrintEx( PROCESS_COMMON_INFO, "netmon DeleteProcessIoInfo KeReleaseSpinLock g_SpLockProcessNetWorkTrafficInfo \n" ); 3439 | 3440 | 3441 | ugPrintEx( PROCESS_COMMON_INFO, "netmon leave DeleteProcessIoInfo \n" ); 3442 | } 3443 | 3444 | NTSTS GetAllProcessesIoInformation( LPVOID *pOutput, DWORD dwInputBuffLength, DWORD *pAllInfoLength ) 3445 | { 3446 | TATUS ntStatus; 3447 | QL OldIrql; 3448 | ST_ENTRY pListEntry; 3449 | RD dwCopiedLength; 3450 | OCESS_IO_INFO_OUTPUT pProcessIoInfoOutput; 3451 | OCESS_NETWORK_TRAFFIC pProcessNetWorkTrafficInfo; 3452 | 3453 | NULL == pOutput || 3454 | NULL == pAllInfoLength ) 3455 | 3456 | return STATUS_INVALID_PARAMETER; 3457 | 3458 | 3459 | cquireSpinLock( &g_SpLockProcessNetWorkTrafficInfo, &OldIrql ); 3460 | 3461 | ocessIoInfoOutput = ( PPROCESS_IO_INFO_OUTPUT )pOutput; 3462 | 3463 | stEntry = g_ProcessIoInfoList.Blink; 3464 | opiedLength = 0; 3465 | tatus = STATUS_SUCCESS; 3466 | 3467 | ( ; ; ) 3468 | 3469 | if( pListEntry == &g_ProcessIoInfoList ) 3470 | { 3471 | break; 3472 | } 3473 | 3474 | pProcessNetWorkTrafficInfo = ( PPROCESS_NETWORK_TRAFFIC )pListEntry; 3475 | 3476 | if ( dwCopiedLength + sizeof( PROCESS_IO_INFO_OUTPUT ) > dwInputBuffLength ) 3477 | { 3478 | ntStatus = STATUS_BUFFER_TOO_SMALL; 3479 | *pAllInfoLength = 0; 3480 | break; 3481 | } 3482 | 3483 | DebugPrintEx( OUTPUT_ALL_PROCESS_IO_INFO, "netmon GetAllProcessesIoInformation process id: %d \n", 3484 | pProcessNetWorkTrafficInfo->dwProcessId 3485 | ); 3486 | 3487 | pProcessIoInfoOutput->dwProcessId = pProcessNetWorkTrafficInfo->dwProcessId; 3488 | pProcessIoInfoOutput->AllSuccSendedDataSize.QuadPart = pProcessNetWorkTrafficInfo->AllSuccSendedDataSize.QuadPart; 3489 | pProcessIoInfoOutput->AllSuccRecvedDataSize.QuadPart = pProcessNetWorkTrafficInfo->AllSuccRecvedDataSizePrev.QuadPart; 3490 | pProcessIoInfoOutput->bStopSend = pProcessNetWorkTrafficInfo->bStopSend; 3491 | pProcessIoInfoOutput->bStopRecv = pProcessNetWorkTrafficInfo->bStopRecv; 3492 | pProcessIoInfoOutput->SendingSpeed.QuadPart = pProcessNetWorkTrafficInfo->SendingSpeed.QuadPart; 3493 | pProcessIoInfoOutput->SuccSendedDataSizeOnce.QuadPart = pProcessNetWorkTrafficInfo->SuccSendedDataSizeOnce.QuadPart; 3494 | pProcessIoInfoOutput->SuccRecvedDataSizeOnce.QuadPart = pProcessNetWorkTrafficInfo->SuccRecvedDataSizeOnce.QuadPart; 3495 | 3496 | pProcessIoInfoOutput ++; 3497 | dwCopiedLength += sizeof( PROCESS_IO_INFO_OUTPUT ); 3498 | 3499 | pListEntry = pListEntry->Blink; 3500 | 3501 | 3502 | eleaseSpinLock( &g_SpLockProcessNetWorkTrafficInfo, OldIrql ); 3503 | llInfoLength = dwCopiedLength; 3504 | return ntStatus; 3505 | } 3506 | 3507 | NTSTATUS GetAllProcessesInformation( PPROCESS_INFORMATION_RECORD pAllProcessInfomation, DWORD dwBufferLength, DWORD *pAllInfoLength ) 3508 | { 3509 | NTSTATUS ntStatus; 3510 | PLIST_ENTRY pListEntry; 3511 | PPROCESS_INFORMATION_LIST_ENTRY pProcessInformationList; 3512 | PPROCESS_INFORMATION_RECORD pProcessInformation; 3513 | DWORD dwListSize; 3514 | PPROCESS_INFORMATION_RECORD pPrcessInformationOutput; 3515 | 3516 | if ( NULL == pAllProcessInfomation || 3517 | 0 == pAllInfoLength ) 3518 | { 3519 | return STATUS_INVALID_PARAMETER; 3520 | } 3521 | 3522 | KeEnterCriticalRegion(); 3523 | ExAcquireResourceExclusiveLite( &g_SyncResource, TRUE ); 3524 | 3525 | ntStatus = STATUS_SUCCESS; 3526 | 3527 | dwListSize = 0; 3528 | 3529 | for( pListEntry = g_ProcessInformationList.Flink; pListEntry != &g_ProcessInformationList; pListEntry = pListEntry->Flink ) 3530 | { 3531 | dwListSize ++; 3532 | } 3533 | 3534 | if( dwBufferLength < sizeof( PROCESS_INFORMATION_RECORD ) * dwListSize ) 3535 | { 3536 | ntStatus = STATUS_BUFFER_TOO_SMALL; 3537 | goto RETURN_; 3538 | } 3539 | 3540 | *pAllInfoLength = 0; 3541 | pPrcessInformationOutput = pAllProcessInfomation; 3542 | 3543 | pListEntry = g_ProcessInformationList.Flink; 3544 | 3545 | for( ; ; ) 3546 | { 3547 | if( pListEntry == &g_ProcessInformationList ) 3548 | { 3549 | break; 3550 | } 3551 | 3552 | pProcessInformationList = ( PPROCESS_INFORMATION_LIST_ENTRY )pListEntry; 3553 | pProcessInformation = pProcessInformationList->pProcessInformation; 3554 | 3555 | DebugPrintEx( OUTPUT_ALL_PROCESS_CONTROL_INFO, "Get process control setting: \n, Remove %d, StopRecv %d, StopSend %d, SendingSpeed: %d \n ImagePath %ws \n", 3556 | pProcessInformation->bRemove, 3557 | pProcessInformation->bStopRecv, 3558 | pProcessInformation->bStopSend, 3559 | pProcessInformation->SendingSpeed, 3560 | pProcessInformation->szNativeImageFileName 3561 | ); 3562 | 3563 | RtlCopyMemory( pPrcessInformationOutput, pProcessInformationList->pProcessInformation, sizeof( PROCESS_INFORMATION_RECORD ) ); 3564 | *pAllInfoLength += sizeof( PROCESS_INFORMATION_RECORD ); 3565 | pPrcessInformationOutput ++; 3566 | 3567 | pListEntry = pListEntry->Flink; 3568 | } 3569 | 3570 | ntStatus = STATUS_SUCCESS; 3571 | RETURN_: 3572 | ExReleaseResourceLite( &g_SyncResource ); 3573 | KeLeaveCriticalRegion(); 3574 | 3575 | return ntStatus; 3576 | } 3577 | 3578 | NTSTATUS ReleaseAllProcessesInformation() 3579 | { 3580 | PPROCESS_INFORMATION_LIST_ENTRY pProcessInformationList; 3581 | 3582 | KeEnterCriticalRegion(); 3583 | ExAcquireResourceExclusiveLite( &g_SyncResource, TRUE ); 3584 | 3585 | for( ; ; ) 3586 | { 3587 | if( TRUE == IsListEmpty( &g_ProcessInformationList ) ) 3588 | { 3589 | break; 3590 | } 3591 | pProcessInformationList = ( PPROCESS_INFORMATION_LIST_ENTRY )RemoveHeadList( &g_ProcessInformationList ); 3592 | ExFreePoolWithTag( pProcessInformationList->pProcessInformation, 0); 3593 | ExFreePoolWithTag( pProcessInformationList, 0 ); 3594 | } 3595 | 3596 | ExReleaseResourceLite( &g_SyncResource ); 3597 | KeLeaveCriticalRegion(); 3598 | KeSetEvent( &g_EventProcessInformationAdded, 0, FALSE ); 3599 | 3600 | return STATUS_SUCCESS; 3601 | } 3602 | 3603 | BOOL IsDriverDevice( PDEVICE_OBJECT pDeviceObject ) 3604 | { 3605 | if( NULL == pDeviceObject ) 3606 | { 3607 | return FALSE; 3608 | } 3609 | 3610 | if( pDeviceObject == g_DevTdiFilter || 3611 | pDeviceObject == g_FilterDeviceForDeviceTcp || 3612 | pDeviceObject == g_FilterDeviceForDeviceUdp ) 3613 | { 3614 | return TRUE; 3615 | } 3616 | 3617 | return FALSE; 3618 | } 3619 | 3620 | NTSTATUS StartWorkThreadManageProcessInfo( 3621 | PPROCESS_INFORMATION_RECORD pProcessInformationFind, 3622 | DWORD dwInputBufferLength 3623 | ) 3624 | { 3625 | NTSTATUS ntStatus = STATUS_SUCCESS; 3626 | PPROCESS_INFORMATION_LIST_ENTRY pProcessInformationLink; 3627 | PPROCESS_INFORMATION_RECORD pProcessInformation; 3628 | HANDLE hSystemThread; 3629 | UNICODE_STRING ProcessImageFilePathFind; 3630 | UNICODE_STRING ProcessImageFilePath; 3631 | PLIST_ENTRY pListEntry; 3632 | 3633 | DebugPrintEx( PROCESS_START_THREAD_INFO, "netmon Entry StartWorkThreadManageProcessInfo input length is %d\n", dwInputBufferLength ); 3634 | if( TRUE == InterlockedExchangeAdd( &g_bBeginStartThreads, 0 ) ) 3635 | { 3636 | if( FALSE == InterlockedExchangeAdd( &g_bThreadsRunning, 0 ) ) 3637 | { 3638 | return STATUS_UNSUCCESSFUL; 3639 | } 3640 | } 3641 | 3642 | if( NULL == pProcessInformationFind ) 3643 | { 3644 | return STATUS_INVALID_PARAMETER; 3645 | } 3646 | 3647 | if( sizeof( PROCESS_INFORMATION_RECORD ) != dwInputBufferLength ) 3648 | { 3649 | return STATUS_INVALID_PARAMETER; 3650 | } 3651 | 3652 | if( NULL == pProcessInformationFind->szNativeImageFileName ) 3653 | { 3654 | return STATUS_INVALID_PARAMETER; 3655 | } 3656 | 3657 | if( L'\0' != pProcessInformationFind->szNativeImageFileName[ PROCESS_IMAGE_FILE_PATH_INFO_MAX_LENGTH - 1 ] ) 3658 | { 3659 | return STATUS_INVALID_PARAMETER; 3660 | } 3661 | 3662 | if( FALSE == InterlockedExchangeAdd( &g_bBeginStartThreads, 0 ) ) 3663 | { 3664 | InterlockedExchange( &g_bBeginStartThreads, TRUE ); 3665 | 3666 | DebugPrintEx( PROCESS_START_THREAD_INFO, "netmon StartWorkThreadManageProcessInfo start ThreadUpdateProcessIoState \n" ); 3667 | 3668 | if( NULL == ThreadUpdateConfig ) 3669 | { 3670 | ntStatus = CreateWorkThread( ThreadUpdateProcessIoState, 3671 | NULL, 3672 | &ThreadUpdateConfig 3673 | ); 3674 | 3675 | if( !NT_SUCCESS( ntStatus ) ) 3676 | { 3677 | InterlockedExchange( &g_bBeginStartThreads, FALSE ); 3678 | return ntStatus; 3679 | } 3680 | } 3681 | 3682 | DebugPrintEx( PROCESS_START_THREAD_INFO, "netmon StartWorkThreadManageProcessInfo start ThreadSendingSpeedControl \n" ); 3683 | 3684 | if( NULL == ThreadProcessIrp ) 3685 | { 3686 | ntStatus = CreateWorkThread( ThreadSendingSpeedControl, 3687 | NULL, 3688 | &ThreadProcessIrp 3689 | ); 3690 | 3691 | if( !NT_SUCCESS( ntStatus ) ) 3692 | { 3693 | InterlockedExchange( &g_bBeginStartThreads, FALSE ); 3694 | return ntStatus; 3695 | } 3696 | } 3697 | 3698 | InterlockedExchange( &g_bThreadsRunning, TRUE ); 3699 | } 3700 | 3701 | RtlInitUnicodeString( &ProcessImageFilePathFind, pProcessInformationFind->szNativeImageFileName ); 3702 | 3703 | DebugPrintEx( PROCESS_START_THREAD_INFO, "netmon StartWorkThreadManageProcessInfo process information modifing stop recv: %d, stop send %d, send speed: %d\n", 3704 | pProcessInformationFind->bStopRecv, 3705 | pProcessInformationFind->bStopSend, 3706 | pProcessInformationFind->SendingSpeed.LowPart 3707 | ); 3708 | 3709 | KeEnterCriticalRegion(); 3710 | ExAcquireResourceExclusive( &g_SyncResource, TRUE ); 3711 | 3712 | pListEntry = g_ProcessInformationList.Flink; 3713 | 3714 | for( ; ; ) 3715 | { 3716 | if( pListEntry == &g_ProcessInformationList ) 3717 | { 3718 | break; 3719 | } 3720 | 3721 | pProcessInformationLink = ( PPROCESS_INFORMATION_LIST_ENTRY )pListEntry; 3722 | pProcessInformation = pProcessInformationLink->pProcessInformation; 3723 | RtlInitUnicodeString( &ProcessImageFilePath, pProcessInformation->szNativeImageFileName ); 3724 | 3725 | DebugPrintEx( PROCESS_START_THREAD_INFO, "netmon StartWorkThreadManageProcessInfo find process information find image path: %wZ, located image path: %wZ\n", 3726 | &ProcessImageFilePathFind, 3727 | &ProcessImageFilePath ); 3728 | 3729 | if( TRUE == RtlEqualUnicodeString( &ProcessImageFilePath, 3730 | &ProcessImageFilePathFind, TRUE ) ) 3731 | { 3732 | if( FALSE == pProcessInformationFind->bRemove ) 3733 | { 3734 | RtlCopyMemory( pProcessInformation, pProcessInformationFind, sizeof( PROCESS_INFORMATION_RECORD ) ); 3735 | KeSetEvent( &g_EventProcessInformationAdded, 0, FALSE ); 3736 | 3737 | ExReleaseResource( &g_SyncResource ); 3738 | KeLeaveCriticalRegion(); 3739 | return ntStatus; 3740 | } 3741 | 3742 | RemoveEntryList( pListEntry ); 3743 | 3744 | ExFreePoolWithTag( pProcessInformation, 0 ); 3745 | ExFreePoolWithTag( pProcessInformationLink, 0 ); 3746 | 3747 | KeSetEvent( &g_EventProcessInformationAdded, 0, FALSE ); 3748 | 3749 | ExReleaseResource( &g_SyncResource ); 3750 | KeLeaveCriticalRegion(); 3751 | return ntStatus; 3752 | } 3753 | 3754 | pListEntry = pListEntry->Flink; 3755 | } 3756 | 3757 | DebugPrintEx( PROCESS_START_THREAD_INFO, "netmon StartWorkThreadManageProcessInfo process information not find \n" ); 3758 | if( FALSE != pProcessInformationFind->bRemove ) 3759 | { 3760 | ExReleaseResource( &g_SyncResource ); 3761 | KeLeaveCriticalRegion(); 3762 | return ntStatus; 3763 | } 3764 | 3765 | pProcessInformationLink = ( PPROCESS_INFORMATION_LIST_ENTRY )AllocZeroPoolWithTag( PagedPool, sizeof( PROCESS_INFORMATION_LIST_ENTRY ) ); 3766 | 3767 | if( NULL == pProcessInformationLink ) 3768 | { 3769 | ExReleaseResource( &g_SyncResource ); 3770 | KeLeaveCriticalRegion(); 3771 | 3772 | return STATUS_INSUFFICIENT_RESOURCES; 3773 | } 3774 | 3775 | pProcessInformation = ( PPROCESS_INFORMATION_RECORD )AllocZeroPoolWithTag( PagedPool, sizeof( PROCESS_INFORMATION_RECORD ) ); 3776 | 3777 | if( NULL == pProcessInformation ) 3778 | { 3779 | ExFreePoolWithTag( pProcessInformationLink, 0 ); 3780 | 3781 | ExReleaseResource( &g_SyncResource ); 3782 | KeLeaveCriticalRegion(); 3783 | 3784 | return STATUS_INSUFFICIENT_RESOURCES; 3785 | } 3786 | 3787 | RtlCopyMemory( pProcessInformation, pProcessInformationFind, sizeof( PROCESS_INFORMATION_RECORD ) ); 3788 | 3789 | pProcessInformationLink->pProcessInformation = pProcessInformation; 3790 | 3791 | DebugPrintEx( PROCESS_START_THREAD_INFO, "netmon StartWorkThreadManageProcessInfo insert new process information \n" ); 3792 | 3793 | InsertTailList( &g_ProcessInformationList, ( PLIST_ENTRY )pProcessInformationLink ); 3794 | 3795 | KeSetEvent( &g_EventProcessInformationAdded, 0, FALSE ); 3796 | 3797 | ExReleaseResource( &g_SyncResource ); 3798 | KeLeaveCriticalRegion(); 3799 | 3800 | return ntStatus; 3801 | } 3802 | 3803 | NTSTATUS AttachToTdiDevice( PDRIVER_OBJECT DriverObject, PUNICODE_STRING TargetDeviceName, PDEVICE_OBJECT *ppDeviceObject ) 3804 | { 3805 | NTSTATUS ntStatus; 3806 | PDEVICE_OBJECT DeviceObject; 3807 | 3808 | DeviceObject = NULL; 3809 | 3810 | if( NULL == DriverObject || 3811 | NULL == TargetDeviceName || 3812 | NULL == ppDeviceObject ) 3813 | { 3814 | ntStatus = STATUS_INVALID_PARAMETER; 3815 | goto EXIT; 3816 | } 3817 | 3818 | ntStatus = IoCreateDevice( 3819 | DriverObject, 3820 | sizeof( TDI_FILTER_DEVICE_EXTENSION ), 3821 | NULL, 3822 | FILE_DEVICE_NETWORK, 3823 | 0, 3824 | 0, 3825 | &DeviceObject 3826 | ); 3827 | 3828 | if( NT_SUCCESS( ntStatus ) ) 3829 | { 3830 | DeviceObject->Flags |= DO_DIRECT_IO; 3831 | ntStatus = IoAttachDevice( 3832 | DeviceObject, 3833 | TargetDeviceName, 3834 | ( PDEVICE_OBJECT* )DeviceObject->DeviceExtension 3835 | ); 3836 | 3837 | if( NT_SUCCESS( ntStatus ) ) 3838 | *ppDeviceObject = DeviceObject; 3839 | } 3840 | 3841 | EXIT: 3842 | if ( !NT_SUCCESS( ntStatus ) ) 3843 | { 3844 | if( NULL != DeviceObject ) 3845 | IoDeleteDevice( DeviceObject ); 3846 | } 3847 | return ntStatus; 3848 | } 3849 | 3850 | PPROCESS_NETWORK_TRAFFIC GetProcessNetWorkTrafficInfoFromEProcess( PEPROCESS pEProcess ) 3851 | { 3852 | KIRQL OldIrql; 3853 | PLIST_ENTRY pListEntry; 3854 | PPROCESS_NETWORK_TRAFFIC pProcessNetWorkTrafficInfo; 3855 | PPROCESS_NETWORK_TRAFFIC pNewProcessNetWorkTrafficInfo; 3856 | 3857 | ASSERT( NULL != pEProcess ); 3858 | 3859 | if ( NULL == pEProcess ) 3860 | return NULL; 3861 | 3862 | DebugPrintEx( PROCESS_NEW_IO_INFO, "netmon GetProcessNetWorkTrafficInfoFromEProcess KeAcquireSpinLock g_SpLockProcessNetWorkTrafficInfo \n" ); 3863 | KeAcquireSpinLock( &g_SpLockProcessNetWorkTrafficInfo, &OldIrql ); 3864 | 3865 | pListEntry = g_ProcessIoInfoList.Flink; 3866 | 3867 | for ( ; ; ) 3868 | { 3869 | if( pListEntry == &g_ProcessIoInfoList ) 3870 | { 3871 | break; 3872 | } 3873 | 3874 | pProcessNetWorkTrafficInfo = ( PPROCESS_NETWORK_TRAFFIC )pListEntry; 3875 | 3876 | if( pProcessNetWorkTrafficInfo->pEProcess == pEProcess ) 3877 | { 3878 | ASSERT( pProcessNetWorkTrafficInfo->dwRefCount >= 1 ); 3879 | 3880 | InterlockedExchangeAdd( &pProcessNetWorkTrafficInfo->dwRefCount, 1 ); 3881 | KeReleaseSpinLock( &g_SpLockProcessNetWorkTrafficInfo, OldIrql ); 3882 | return pProcessNetWorkTrafficInfo; 3883 | } 3884 | 3885 | pListEntry = pListEntry->Flink; 3886 | } 3887 | 3888 | pNewProcessNetWorkTrafficInfo = ( PPROCESS_NETWORK_TRAFFIC )AllocZeroPoolWithTag( NonPagedPool, sizeof( PROCESS_NETWORK_TRAFFIC ) ); 3889 | if( NULL == pNewProcessNetWorkTrafficInfo ) 3890 | { 3891 | goto RETURN_ERROR; 3892 | } 3893 | 3894 | pNewProcessNetWorkTrafficInfo->pTimer = AllocZeroPoolWithTag( NonPagedPool, sizeof( KTIMER ) ); 3895 | pNewProcessNetWorkTrafficInfo->pDpc = AllocZeroPoolWithTag( NonPagedPool, sizeof( KDPC ) ); 3896 | 3897 | if( NULL == pProcessNetWorkTrafficInfo->pTimer || 3898 | NULL == pProcessNetWorkTrafficInfo->pDpc ) 3899 | { 3900 | goto RETURN_ERROR; 3901 | } 3902 | 3903 | KeInitializeSpinLock( &pNewProcessNetWorkTrafficInfo->IrpListLock ); 3904 | 3905 | InitializeListHead( &pNewProcessNetWorkTrafficInfo->IrpList ); 3906 | 3907 | KeInitializeTimer( pNewProcessNetWorkTrafficInfo->pTimer ); 3908 | KeInitializeDpc( pNewProcessNetWorkTrafficInfo->pDpc, TimerDpcProcess, ( PVOID )pEProcess ); 3909 | KeSetTimer( pNewProcessNetWorkTrafficInfo->pTimer, g_TimerElapse, pNewProcessNetWorkTrafficInfo->pDpc ); 3910 | pNewProcessNetWorkTrafficInfo->pEProcess = pEProcess; 3911 | pNewProcessNetWorkTrafficInfo->dwProcessId = ( DWORD )PsGetProcessId( pEProcess ); 3912 | 3913 | pNewProcessNetWorkTrafficInfo->SendingSpeed.LowPart = 1024; 3914 | pNewProcessNetWorkTrafficInfo->SendingSpeed.HighPart = 0; 3915 | 3916 | pNewProcessNetWorkTrafficInfo->dwRefCount = PROCESS_NETWORK_TRAFFIC_INIT_REFERRENCE; 3917 | InsertHeadList( &g_ProcessIoInfoList, &pNewProcessNetWorkTrafficInfo->ProcessIoList ); 3918 | DebugPrintEx( PROCESS_NEW_IO_INFO, "netmon Insert new process io information 0x%0.8x \n", pNewProcessNetWorkTrafficInfo ); 3919 | 3920 | KeReleaseSpinLock( &g_SpLockProcessNetWorkTrafficInfo, OldIrql ); 3921 | 3922 | if( TRUE == InterlockedExchangeAdd( &g_bThreadsRunning, 0 ) ) 3923 | { 3924 | KeSetEvent( &g_EventProcessInformationAdded, 0, FALSE ); 3925 | } 3926 | 3927 | return pNewProcessNetWorkTrafficInfo; 3928 | 3929 | RETURROR: 3930 | if( NULL != pNewProcessNetWorkTrafficInfo ) 3931 | { 3932 | if ( NULL != pNewProcessNetWorkTrafficInfo->pDpc ) 3933 | { 3934 | ExFreePoolWithTag( pNewProcessNetWorkTrafficInfo->pDpc, 0 );; 3935 | } 3936 | 3937 | if ( NULL != pNewProcessNetWorkTrafficInfo->pTimer ) 3938 | { 3939 | ExFreePoolWithTag( pNewProcessNetWorkTrafficInfo->pTimer, 0 ); 3940 | } 3941 | 3942 | ExFreePoolWithTag( pNewProcessNetWorkTrafficInfo, 0 ); 3943 | } 3944 | 3945 | KeReleaseSpinLock( &g_SpLockProcessNetWorkTrafficInfo, OldIrql ); 3946 | 3947 | return NULL; 3948 | } 3949 | 3950 | PPROCESS_NETWORK_TRAFFIC ReferenceProcessNetWorkTrafficInfo( PEPROCESS pEProcess ) 3951 | { 3952 | KIRQL OldIrql; 3953 | PLIST_ENTRY pListEntry; 3954 | NTSTATUS ntStatus; 3955 | PPROCESS_NETWORK_TRAFFIC pProcessNetWorkTrafficInfo; 3956 | 3957 | DebugPrintEx( PROCESS_COMMON_INFO, "netmon ReferenceProcessNetWorkTrafficInfo KeAcquireSpinLock g_SpLockProcessNetWorkTrafficInfo \n" ); 3958 | 3959 | KeAcquireSpinLock( &g_SpLockProcessNetWorkTrafficInfo, &OldIrql ); 3960 | 3961 | pListEntry = g_ProcessIoInfoList.Flink; 3962 | 3963 | for ( ; ; ) 3964 | { 3965 | ASSERT( NULL != pListEntry ); 3966 | 3967 | if( pListEntry == &g_ProcessIoInfoList ) 3968 | { 3969 | pProcessNetWorkTrafficInfo = NULL; 3970 | break; 3971 | } 3972 | 3973 | pProcessNetWorkTrafficInfo = ( PPROCESS_NETWORK_TRAFFIC )pListEntry; 3974 | 3975 | ASSERT( NULL != pProcessNetWorkTrafficInfo->pEProcess ); 3976 | 3977 | if ( pProcessNetWorkTrafficInfo->pEProcess == pEProcess ) 3978 | { 3979 | InterlockedExchangeAdd( &pProcessNetWorkTrafficInfo->dwRefCount, 1 ); 3980 | break; 3981 | } 3982 | 3983 | pListEntry = pListEntry->Flink; 3984 | } 3985 | 3986 | KeReleaseSpinLock( &g_SpLockProcessNetWorkTrafficInfo, OldIrql ); 3987 | return pProcessNetWorkTrafficInfo; 3988 | } 3989 | 3990 | void ReleaseAllProcessNetWorkTrafficInfo() 3991 | { 3992 | KIRQL OldIrql; 3993 | PLIST_ENTRY pListEntry; 3994 | PLIST_ENTRY pListEntryPrev; 3995 | PPROCESS_NETWORK_TRAFFIC pProcessIoInfo; 3996 | 3997 | KeAcquireSpinLock( &g_SpLockProcessNetWorkTrafficInfo, &OldIrql ); 3998 | 3999 | pListEntry = g_ProcessIoInfoList.Flink; 4000 | 4001 | for( ; ; ) 4002 | { 4003 | DWORD dwCurRefCount; 4004 | if( pListEntry == &g_ProcessIoInfoList ) 4005 | { 4006 | break; 4007 | } 4008 | 4009 | pListEntryPrev = pListEntry->Flink; 4010 | 4011 | RemoveEntryList( pListEntry ); 4012 | 4013 | pProcessIoInfo = ( PPROCESS_NETWORK_TRAFFIC )pListEntry; 4014 | 4015 | ASSERT( NULL != pProcessIoInfo->pTimer ); 4016 | 4017 | KeCancelTimer( pProcessIoInfo->pTimer ); 4018 | 4019 | dwCurRefCount = InterlockedExchangeAdd( &pProcessIoInfo->dwRefCount, -1 ); 4020 | if ( 1 == dwCurRefCount ) 4021 | { 4022 | ExFreePoolWithTag( pProcessIoInfo->pDpc, 0 ); 4023 | ExFreePoolWithTag( pProcessIoInfo->pTimer, 0 ); 4024 | ExFreePoolWithTag( pProcessIoInfo, 0 ); 4025 | } 4026 | else 4027 | { 4028 | ASSERT( dwCurRefCount > 1 ); 4029 | } 4030 | 4031 | pListEntry = pListEntryPrev; 4032 | } 4033 | 4034 | KeReleaseSpinLock( &g_SpLockProcessNetWorkTrafficInfo, OldIrql ); 4035 | } 4036 | 4037 | DWORD ReleaseProcessNetWorkTrafficInfo( PROCESS_NETWORK_TRAFFIC *pProcessNetWorkTrafficInfo ) 4038 | { 4039 | NTSTATUS ntStatus; 4040 | DWORD dwCurRefCount; 4041 | 4042 | ASSERT( NULL != pProcessNetWorkTrafficInfo ); 4043 | ASSERT( TRUE == MmIsAddressValid( pProcessNetWorkTrafficInfo ) ); 4044 | 4045 | dwCurRefCount = InterlockedExchangeAdd( &pProcessNetWorkTrafficInfo->dwRefCount, -1 ); 4046 | 4047 | DebugPrintEx( RELEASE_PROCESS_INFO, "netmon Enter ReleaseProcessNetWorkTrafficInfo prev reference count of the process information is %d\n", 4048 | dwCurRefCount ); 4049 | 4050 | if( 1 == dwCurRefCount ) 4051 | { 4052 | ExFreePoolWithTag( pProcessNetWorkTrafficInfo->pDpc, 0 ); 4053 | ExFreePoolWithTag( pProcessNetWorkTrafficInfo->pTimer, 0 ); 4054 | ExFreePoolWithTag( pProcessNetWorkTrafficInfo, 0 ); 4055 | } 4056 | else 4057 | { 4058 | ASSERT( dwCurRefCount > 1 ); 4059 | } 4060 | 4061 | DebugPrintEx( RELEASE_PROCESS_INFO, "netmon Leave ReleaseProcessNetWorkTrafficInfo \n" ); 4062 | return dwCurRefCount - 1; 4063 | } 4064 | 4065 | NTSTATUS EnterUserProcessReadImagePath( PEPROCESS pEProcess, PUNICODE_STRING pImageFilePath ) 4066 | { 4067 | KAPC_STATE ApcState; 4068 | NTSTATUS ntStatus; 4069 | CHAR bIsAttachToOtherProc; 4070 | PPEB pPeb; 4071 | DWORD ImageFilePathLength; 4072 | PRTL_USER_PROCESS_PARAMETERS pProcessParameters; 4073 | 4074 | ntStatus = STATUS_SUCCESS; 4075 | bIsAttachToOtherProc = FALSE; 4076 | 4077 | if( NULL == pEProcess || 4078 | NULL == pImageFilePath ) 4079 | { 4080 | ASSERT( FALSE ); 4081 | return STATUS_INVALID_PARAMETER; 4082 | } 4083 | 4084 | pPeb = PsGetProcessPeb( pEProcess ); 4085 | 4086 | DebugPrintEx( READ_USER_PROC_PEB_INFO, "netmon Enter EnterUserProcessReadImagePath readed peb 0x%0.8x \n", pPeb ); 4087 | 4088 | if( NULL == pPeb ) 4089 | { 4090 | return STATUS_INVALID_PARAMETER; 4091 | } 4092 | 4093 | if( pEProcess != IoGetCurrentProcess() ) 4094 | { 4095 | KeStackAttachProcess( pEProcess, &ApcState ); 4096 | bIsAttachToOtherProc = TRUE; 4097 | } 4098 | 4099 | ProbeForRead( pPeb, FIELD_OFFSET( PEB, SubSystemData ), 1 ); 4100 | 4101 | pProcessParameters = pPeb->ProcessParameters; 4102 | 4103 | ProbeForRead( pProcessParameters, FIELD_OFFSET( RTL_USER_PROCESS_PARAMETERS, CommandLine ), 1 ); 4104 | ProbeForRead( pProcessParameters->ImagePathName.Buffer, pProcessParameters->ImagePathName.Length, 2 ); 4105 | 4106 | if ( pImageFilePath->MaximumLength < pProcessParameters->ImagePathName.Length + pImageFilePath->Length ) 4107 | { 4108 | ntStatus= STATUS_INSUFFICIENT_RESOURCES; 4109 | } 4110 | else 4111 | { 4112 | RtlCopyMemory( ( PBYTE )pImageFilePath->Buffer + pImageFilePath->Length, pProcessParameters->ImagePathName.Buffer, pProcessParameters->ImagePathName.Length); 4113 | pImageFilePath->Length += pProcessParameters->ImagePathName.Length; 4114 | } 4115 | 4116 | if( TRUE == bIsAttachToOtherProc ) 4117 | { 4118 | KeUnstackDetachProcess( &ApcState ); 4119 | } 4120 | return ntStatus; 4121 | } 4122 | 4123 | NTSTATUS GetFileHandle( PHANDLE pFileHandle, PUNICODE_STRING FileName ) 4124 | { 4125 | NTSTATUS ntStatus; 4126 | OBJECT_ATTRIBUTES ObjectAttributes; 4127 | IO_STATUS_BLOCK IoStatusBlock; 4128 | 4129 | if ( NULL == pFileHandle || NULL == FileName ) 4130 | { 4131 | return STATUS_INVALID_PARAMETER; 4132 | } 4133 | 4134 | InitializeObjectAttributes( 4135 | &ObjectAttributes, 4136 | FileName, 4137 | OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, 4138 | NULL, 4139 | NULL 4140 | ); 4141 | 4142 | ntStatus = ZwCreateFile( 4143 | pFileHandle, 4144 | GENERIC_READ, 4145 | &ObjectAttributes, 4146 | &IoStatusBlock, 4147 | 0, 4148 | FILE_ATTRIBUTE_NORMAL, 4149 | FILE_SHARE_READ | FILE_SHARE_WRITE, 4150 | FILE_OPEN, 4151 | FILE_SYNCHRONOUS_IO_NONALERT | FILE_DIRECTORY_FILE, 4152 | NULL, 4153 | 0 4154 | ); 4155 | 4156 | return ntStatus; 4157 | } 4158 | 4159 | NTSTATUS QueryFileAndDirInfo( HANDLE hFile, 4160 | LPCWSTR pwszFilePath, 4161 | LPCWSTR pwszFileName, 4162 | PFILE_BOTH_DIRECTORY_INFORMATION FileInformation, 4163 | ULONG FileInformationLength ) 4164 | { 4165 | NTSTATUS ntStatus; 4166 | IO_STATUS_BLOCK IoStatusBlock; 4167 | UNICODE_STRING FileName; 4168 | 4169 | if( NULL == hFile || 4170 | pwszFilePath > pwszFileName || 4171 | NULL == FileInformation || 4172 | 0 == FileInformationLength) 4173 | { 4174 | return STATUS_INVALID_PARAMETER; 4175 | } 4176 | 4177 | 4178 | FileName.Length = sizeof( WCHAR ) * ( pwszFileName - pwszFilePath ); 4179 | FileName.MaximumLength = sizeof( WCHAR ) * ( pwszFileName - pwszFilePath ); 4180 | FileName.Buffer = ( LPWSTR )pwszFilePath; 4181 | 4182 | ntStatus = ZwQueryDirectoryFile 4183 | ( 4184 | hFile, 4185 | NULL, 4186 | NULL, 4187 | NULL, 4188 | &IoStatusBlock, 4189 | FileInformation, 4190 | FileInformationLength, 4191 | FileBothDirectoryInformation, 4192 | TRUE, 4193 | &FileName, 4194 | TRUE 4195 | ); 4196 | return ntStatus; 4197 | } 4198 | 4199 | LPWSTR FindWideCharInWideString(LPCWSTR pszwString, DWORD dwLength, WCHAR wFindChar) 4200 | { 4201 | INT32 i; 4202 | LPWSTR pwszFinded; 4203 | 4204 | if( NULL == pszwString || 4205 | dwLength == 0 ) 4206 | { 4207 | ASSERT( FALSE ); 4208 | return 0; 4209 | } 4210 | 4211 | pwszFinded = NULL; 4212 | for( i = 0; i < ( INT32 )dwLength; i ++ ) 4213 | { 4214 | if( pszwString[ i ] == wFindChar ) 4215 | { 4216 | pwszFinded = ( LPWSTR )&pszwString[i]; 4217 | break; 4218 | } 4219 | } 4220 | 4221 | return pwszFinded; 4222 | } 4223 | 4224 | NTSTATUS ShortPathNameToEntirePathName( PUNICODE_STRING ShortPathName, PUNICODE_STRING FullPathName ) 4225 | { 4226 | NTSTATUS ntStatus; 4227 | UNICODE_STRING __FullPathName; 4228 | HANDLE hFile; 4229 | LPWSTR pwszShortPath; 4230 | UNICODE_STRING __ShortPathName; 4231 | LPWSTR pwszAfterSymPrefix; 4232 | LPWSTR pwszPathDelim; 4233 | CHAR bPathEnd; 4234 | PFILE_BOTH_DIRECTORY_INFORMATION pFileInfo; 4235 | DWORD dwFileNameLength; 4236 | DWORD dwWritedLength; 4237 | 4238 | if( NULL == ShortPathName || 4239 | NULL == FullPathName ) 4240 | { 4241 | return STATUS_INVALID_PARAMETER; 4242 | } 4243 | 4244 | if( ShortPathName->Length < FILE_SYMBLOLIC_NAME_PREFIX_SIZE || 4245 | ShortPathName->Buffer[ 0 ] != L'\\' || 4246 | ShortPathName->Buffer[ 1 ] != L'?' || 4247 | ShortPathName->Buffer[ 2 ] != L'?' || 4248 | ShortPathName->Buffer[ 3 ] != L'\\' || 4249 | ShortPathName->Buffer[ 5 ] != L':' || 4250 | ShortPathName->Buffer[ 6 ] != L'\\' ) 4251 | { 4252 | return STATUS_INVALID_PARAMETER; 4253 | } 4254 | 4255 | pFileInfo = NULL; 4256 | hFile = NULL; 4257 | 4258 | __FullPathName.Length = 0; 4259 | __FullPathName.MaximumLength = COMMON_OBJ_NAME_MAX_LENGTH; 4260 | __FullPathName.Buffer = AllocZeroPoolWithTag( NonPagedPool, COMMON_OBJ_NAME_MAX_LENGTH ); 4261 | 4262 | if( NULL == __FullPathName.Buffer ) 4263 | { 4264 | ntStatus = STATUS_INSUFFICIENT_RESOURCES; 4265 | goto RETURN_ERROR; 4266 | } 4267 | 4268 | pFileInfo = AllocZeroPoolWithTag( NonPagedPool, COMMON_OBJ_NAME_MAX_LENGTH ); 4269 | 4270 | if( NULL == pFileInfo ) 4271 | { 4272 | ntStatus = STATUS_INSUFFICIENT_RESOURCES; 4273 | goto RETURN_ERROR; 4274 | } 4275 | 4276 | __ShortPathName.Buffer = ShortPathName->Buffer; 4277 | __ShortPathName.Length = FILE_SYMBLOLIC_NAME_PREFIX_SIZE; 4278 | __ShortPathName.MaximumLength = FILE_SYMBLOLIC_NAME_PREFIX_SIZE; 4279 | 4280 | ntStatus = GetFileHandle( &hFile, &__ShortPathName ); 4281 | if( !NT_SUCCESS( ntStatus ) ) 4282 | { 4283 | goto RETURN_ERROR; 4284 | } 4285 | 4286 | RtlCopyMemory( __FullPathName.Buffer, ShortPathName->Buffer, FILE_SYMBLOLIC_NAME_PREFIX_SIZE ); 4287 | 4288 | __FullPathName.Length = FILE_SYMBLOLIC_NAME_PREFIX_SIZE; 4289 | pwszAfterSymPrefix = ShortPathName->Buffer + FILE_SYMBLOLIC_NAME_PREFIX_SIZE / sizeof( WCHAR ); 4290 | 4291 | bPathEnd = FALSE; 4292 | dwWritedLength = FILE_SYMBLOLIC_NAME_PREFIX_SIZE; 4293 | 4294 | for( ; ; ) 4295 | { 4296 | if( ShortPathName->Length <= dwWritedLength ) 4297 | { 4298 | if( !NT_SUCCESS( ntStatus ) ) 4299 | { 4300 | goto RETURN_ERROR; 4301 | } 4302 | 4303 | goto OUTPUT_FULL_PATH; 4304 | } 4305 | 4306 | pwszPathDelim = FindWideCharInWideString( pwszAfterSymPrefix, 4307 | ( ShortPathName->Length - dwWritedLength ) / sizeof( WCHAR ), 4308 | PATH_DELIM 4309 | ); 4310 | 4311 | if( NULL == pwszPathDelim ) 4312 | { 4313 | pwszPathDelim = ShortPathName->Buffer + ShortPathName->Length; 4314 | } 4315 | 4316 | if( pwszPathDelim == ShortPathName->Buffer + ShortPathName->Length ) 4317 | { 4318 | bPathEnd = TRUE; 4319 | } 4320 | 4321 | ntStatus = QueryFileAndDirInfo( hFile, pwszAfterSymPrefix, pwszPathDelim, pFileInfo, COMMON_OBJ_NAME_MAX_LENGTH ); 4322 | 4323 | if( !NT_SUCCESS( ntStatus ) ) 4324 | { 4325 | goto RETURN_ERROR; 4326 | } 4327 | 4328 | dwFileNameLength = pFileInfo->FileNameLength + ( DWORD )__FullPathName.Length + sizeof( WCHAR ); 4329 | 4330 | if( dwFileNameLength > __FullPathName.MaximumLength ) 4331 | { 4332 | ntStatus = STATUS_INSUFFICIENT_RESOURCES; 4333 | goto RETURN_ERROR; 4334 | } 4335 | 4336 | dwFileNameLength = __FullPathName.Length / sizeof( WCHAR ); 4337 | if( __FullPathName.Buffer[ __FullPathName.Length / sizeof( WCHAR ) - 1 ] != L'\\' ) 4338 | { 4339 | __FullPathName.Buffer[ __FullPathName.Length / sizeof( WCHAR ) ] = L'\\'; 4340 | __FullPathName.Length += sizeof( WCHAR ); 4341 | } 4342 | 4343 | RtlCopyMemory( __FullPathName.Buffer + __FullPathName.Length, pFileInfo->FileName, pFileInfo->FileNameLength ); 4344 | __FullPathName.Length += ( USHORT )pFileInfo->FileNameLength; 4345 | 4346 | ZwClose( hFile ); 4347 | hFile = NULL; 4348 | 4349 | if( TRUE == bPathEnd ) 4350 | { 4351 | goto OUTPUT_FULL_PATH; 4352 | } 4353 | 4354 | __ShortPathName.MaximumLength = __ShortPathName.Length = ( PBYTE )pwszPathDelim - ( PBYTE )ShortPathName->Buffer; 4355 | 4356 | ntStatus = GetFileHandle( &hFile, &__ShortPathName ); 4357 | 4358 | if( !NT_SUCCESS( ntStatus ) ) 4359 | { 4360 | goto RETURN_ERROR; 4361 | } 4362 | 4363 | dwWritedLength += ( pwszPathDelim - pwszAfterSymPrefix + 1 ) * sizeof( WCHAR ); 4364 | 4365 | pwszAfterSymPrefix = pwszPathDelim + 1; 4366 | 4367 | if( pwszAfterSymPrefix < ShortPathName->Buffer + ShortPathName->Length ) 4368 | { 4369 | continue; 4370 | } 4371 | 4372 | ntStatus = STATUS_INVALID_PARAMETER; 4373 | goto RETURN_ERROR; 4374 | } 4375 | 4376 | OUTPUT_FULL_PATH: 4377 | FullPathName->Length = __FullPathName.Length; 4378 | FullPathName->MaximumLength = __FullPathName.MaximumLength; 4379 | 4380 | FullPathName->Buffer = AllocZeroPoolWithTag( NonPagedPool, __FullPathName.Length ); 4381 | 4382 | if( NULL == FullPathName->Buffer ) 4383 | { 4384 | ntStatus = STATUS_INSUFFICIENT_RESOURCES; 4385 | goto RETURN_ERROR; 4386 | } 4387 | 4388 | RtlCopyMemory( FullPathName->Buffer, __FullPathName.Buffer, __FullPathName.Length ); 4389 | 4390 | RETURN_ERROR: 4391 | if( NULL != __FullPathName.Buffer ) 4392 | { 4393 | ExFreePoolWithTag( __FullPathName.Buffer, 0 ); 4394 | } 4395 | 4396 | if( NULL != pFileInfo ) 4397 | { 4398 | ExFreePoolWithTag( pFileInfo, 0 ); 4399 | } 4400 | 4401 | if( NULL != hFile ) 4402 | { 4403 | ZwClose( hFile ); 4404 | } 4405 | 4406 | return ntStatus; 4407 | } 4408 | 4409 | NTSTATUS GetProcessImagePath( DWORD dwProcessId, PUNICODE_STRING ProcessImageFilePath, DWORD dwBufferLen ) 4410 | { 4411 | OBJECT_ATTRIBUTES ObjectAttributes; 4412 | IO_STATUS_BLOCK IoStatusBlock; 4413 | POBJECT_NAME_INFORMATION pFileDosDeviceName; 4414 | ULONG ImageFilePathLength; 4415 | PFILE_OBJECT pFileDirectObject; 4416 | PFILE_OBJECT pFileIndirectObject; 4417 | HANDLE hFileDirect; 4418 | HANDLE hFileIndirect; 4419 | HANDLE hProcess; 4420 | PEPROCESS pEProcess; 4421 | NTSTATUS ntStatus; 4422 | BOOL bFullPath; 4423 | UNICODE_STRING FullPathName = { 0 }; 4424 | UNICODE_STRING FileDosName = { 0 }; 4425 | 4426 | pEProcess = NULL; 4427 | hProcess = NULL; 4428 | hFileDirect = NULL; 4429 | hFileIndirect = NULL; 4430 | pFileDirectObject = NULL; 4431 | pFileIndirectObject = NULL; 4432 | bFullPath = FALSE; 4433 | pFileDosDeviceName = NULL; 4434 | 4435 | ntStatus = PsLookupProcessByProcessId( ( HANDLE )dwProcessId, &pEProcess ); 4436 | if( !NT_SUCCESS( ntStatus ) ) 4437 | { 4438 | goto RETURN_ERROR; 4439 | } 4440 | 4441 | ntStatus = ObOpenObjectByPointer( 4442 | pEProcess, 4443 | OBJ_KERNEL_HANDLE, 4444 | NULL, 4445 | FILE_ALL_ACCESS, 4446 | NULL, 4447 | KernelMode, 4448 | &hProcess 4449 | ); 4450 | 4451 | if( !NT_SUCCESS( ntStatus ) ) 4452 | { 4453 | goto RETURN_ERROR; 4454 | } 4455 | 4456 | ntStatus = ZwQueryInformationProcess( 4457 | hProcess, 4458 | ProcessImageFileName, 4459 | ProcessImageFilePath, 4460 | dwBufferLen, 4461 | &ImageFilePathLength 4462 | ); 4463 | 4464 | if( !NT_SUCCESS( ntStatus ) ) 4465 | { 4466 | goto RETURN_ERROR; 4467 | } 4468 | 4469 | InitializeObjectAttributes( 4470 | &ObjectAttributes, 4471 | ProcessImageFilePath, 4472 | OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, 4473 | NULL, 4474 | NULL 4475 | ); 4476 | 4477 | ntStatus = ZwOpenFile( 4478 | &hFileDirect, 4479 | GENERIC_READ, 4480 | &ObjectAttributes, 4481 | &IoStatusBlock, 4482 | FILE_SHARE_READ, 4483 | FILE_SYNCHRONOUS_IO_NONALERT 4484 | ); //First get process image file path by its process handle 4485 | 4486 | if( NT_SUCCESS( ntStatus ) ) 4487 | { 4488 | if ( NULL != FindWideCharInWideString( 4489 | ProcessImageFilePath->Buffer, 4490 | ProcessImageFilePath->Length / sizeof( WCHAR ), 4491 | SHORT_PATH_SIGN 4492 | ) ) 4493 | { 4494 | bFullPath = TRUE; 4495 | FileDosName.MaximumLength = COMMON_OBJ_NAME_MAX_LENGTH; 4496 | FileDosName.Buffer = AllocZeroPoolWithTag( NonPagedPool, COMMON_OBJ_NAME_MAX_LENGTH ); 4497 | 4498 | if ( NULL == FileDosName.Buffer ) 4499 | { 4500 | ntStatus= STATUS_INSUFFICIENT_RESOURCES; 4501 | goto RETURN_ERROR; 4502 | } 4503 | 4504 | RtlCopyMemory( FileDosName.Buffer, DOS_DEVICE_NAME_PREFIX, CONST_STRING_SIZE( DOS_DEVICE_NAME_PREFIX ) ); 4505 | 4506 | FileDosName.Length = CONST_STRING_SIZE( DOS_DEVICE_NAME_PREFIX ); 4507 | 4508 | ntStatus = ObReferenceObjectByHandle( 4509 | hFileDirect, 4510 | 0, 4511 | *IoFileObjectType, 4512 | 0, 4513 | &pFileDirectObject, 4514 | 0 4515 | ); 4516 | 4517 | if( !NT_SUCCESS( ntStatus ) ) 4518 | { 4519 | goto RETURN_ERROR; 4520 | } 4521 | 4522 | ntStatus = IoQueryFileDosDeviceName( pFileDirectObject, &pFileDosDeviceName ); 4523 | if( !NT_SUCCESS( ntStatus ) ) 4524 | { 4525 | goto RETURN_ERROR; 4526 | } 4527 | 4528 | ASSERT( NULL != pFileDosDeviceName && NULL != pFileDosDeviceName->Name.Buffer ); 4529 | if( FileDosName.MaximumLength < FileDosName.Length + pFileDosDeviceName->Name.Length ) 4530 | { 4531 | ntStatus = STATUS_INSUFFICIENT_RESOURCES; 4532 | goto RETURN_ERROR; 4533 | } 4534 | 4535 | RtlCopyMemory( 4536 | ( FileDosName.Buffer + FileDosName.Length ), 4537 | pFileDosDeviceName->Name.Buffer, 4538 | pFileDosDeviceName->Name.Length 4539 | ); 4540 | 4541 | FileDosName.Length += pFileDosDeviceName->Name.Length; 4542 | 4543 | ntStatus = ShortPathNameToEntirePathName( &FileDosName, &FullPathName ); 4544 | if( !NT_SUCCESS( ntStatus ) ) 4545 | { 4546 | goto RETURN_ERROR; 4547 | } 4548 | 4549 | InitializeObjectAttributes( 4550 | &ObjectAttributes, 4551 | &FullPathName, 4552 | OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, 4553 | NULL, 4554 | NULL 4555 | ); 4556 | 4557 | ntStatus = ZwCreateFile( 4558 | &hFileIndirect, 4559 | GENERIC_READ, 4560 | &ObjectAttributes, 4561 | &IoStatusBlock, 4562 | NULL, 4563 | FILE_ATTRIBUTE_NORMAL, 4564 | FILE_SHARE_READ, 4565 | FILE_OPEN, 4566 | FILE_SYNCHRONOUS_IO_NONALERT, 4567 | NULL, 4568 | 0 4569 | ); 4570 | 4571 | if( !NT_SUCCESS( ntStatus ) ) 4572 | { 4573 | goto RETURN_ERROR; 4574 | } 4575 | 4576 | ntStatus = ObReferenceObjectByHandle( 4577 | hFileIndirect, 4578 | 0, 4579 | *IoFileObjectType, 4580 | KernelMode, 4581 | &pFileIndirectObject, 4582 | NULL 4583 | ); 4584 | 4585 | if( !NT_SUCCESS( ntStatus ) ) 4586 | { 4587 | goto RETURN_ERROR; 4588 | } 4589 | 4590 | ntStatus = ObQueryNameString( 4591 | pFileIndirectObject, 4592 | ( POBJECT_NAME_INFORMATION )ProcessImageFilePath, 4593 | dwBufferLen, 4594 | &ImageFilePathLength 4595 | ); 4596 | } 4597 | } 4598 | else 4599 | { 4600 | FileDosName.MaximumLength = COMMON_OBJ_NAME_MAX_LENGTH; 4601 | FileDosName.Buffer = AllocZeroPoolWithTag( NonPagedPool, COMMON_OBJ_NAME_MAX_LENGTH ); 4602 | 4603 | if ( NULL == FileDosName.Buffer ) 4604 | { 4605 | ntStatus = STATUS_INSUFFICIENT_RESOURCES; 4606 | goto RETURN_ERROR; 4607 | } 4608 | 4609 | RtlCopyMemory( FileDosName.Buffer, DOS_DEVICE_NAME_PREFIX, CONST_STRING_SIZE( DOS_DEVICE_NAME_PREFIX ) ); 4610 | FileDosName.Length = CONST_STRING_SIZE( DOS_DEVICE_NAME_PREFIX ); 4611 | 4612 | ntStatus = EnterUserProcessReadImagePath( pEProcess, &FileDosName ); 4613 | if( !NT_SUCCESS( ntStatus ) ) 4614 | { 4615 | goto RETURN_ERROR; 4616 | } 4617 | 4618 | if( NULL == FindWideCharInWideString( 4619 | ( LPCWSTR )FileDosName.Buffer, 4620 | FileDosName.Length / sizeof( WCHAR ), 4621 | SHORT_PATH_SIGN 4622 | ) ) 4623 | { 4624 | InitializeObjectAttributes( 4625 | &ObjectAttributes, 4626 | &FileDosName, 4627 | OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, 4628 | NULL, 4629 | NULL 4630 | ); 4631 | 4632 | ntStatus= ZwCreateFile( 4633 | &hFileIndirect, 4634 | GENERIC_READ, 4635 | &ObjectAttributes, 4636 | &IoStatusBlock, 4637 | 0, 4638 | FILE_ATTRIBUTE_NORMAL, 4639 | FILE_SHARE_READ, 4640 | FILE_OPEN, 4641 | FILE_SYNCHRONOUS_IO_NONALERT, 4642 | NULL, 4643 | 0 ); 4644 | 4645 | if( !NT_SUCCESS( ntStatus ) ) 4646 | { 4647 | goto RETURN_ERROR; 4648 | } 4649 | 4650 | ntStatus = ObReferenceObjectByHandle( 4651 | hFileIndirect, 4652 | 0, 4653 | *IoFileObjectType, 4654 | KernelMode, 4655 | &pFileIndirectObject, 4656 | NULL 4657 | ); 4658 | 4659 | if( !NT_SUCCESS( ntStatus ) ) 4660 | { 4661 | goto RETURN_ERROR; 4662 | } 4663 | 4664 | ntStatus = ObQueryNameString( 4665 | pFileIndirectObject, 4666 | ( POBJECT_NAME_INFORMATION )ProcessImageFilePath, 4667 | dwBufferLen, 4668 | &ImageFilePathLength 4669 | ); 4670 | } 4671 | } 4672 | 4673 | RETURN_ERROR: 4674 | if( NULL != pEProcess ) 4675 | { 4676 | ObfDereferenceObject( pEProcess ); 4677 | } 4678 | 4679 | if( NULL != hProcess ) 4680 | { 4681 | ZwClose( hProcess ); 4682 | } 4683 | 4684 | if( NULL != pFileDosDeviceName ) 4685 | { 4686 | ExFreePool( pFileDosDeviceName ); 4687 | } 4688 | 4689 | if( NULL != pFileIndirectObject ) 4690 | { 4691 | ObfDereferenceObject( pFileIndirectObject ); 4692 | } 4693 | 4694 | if( NULL != hFileIndirect ) 4695 | { 4696 | ZwClose( hFileIndirect ); 4697 | } 4698 | 4699 | if( NULL != pFileDirectObject ) 4700 | { 4701 | ObfDereferenceObject( pFileDirectObject ); 4702 | } 4703 | 4704 | if( NULL != hFileDirect ) 4705 | { 4706 | ZwClose( hFileDirect ); 4707 | } 4708 | 4709 | if( NULL != FileDosName.Buffer ) 4710 | { 4711 | ExFreePoolWithTag( FileDosName.Buffer, 0 ); 4712 | } 4713 | 4714 | return ntStatus; 4715 | } 4716 | 4717 | NTSTATUS RegisterProcessCreateNotify() 4718 | { 4719 | return PsSetCreateProcessNotifyRoutine( ( PCREATE_PROCESS_NOTIFY_ROUTINE )DeleteProcessIoInfo, FALSE ); 4720 | } 4721 | 4722 | NTSTATUS DeregisterProcessCreateNotify() 4723 | { 4724 | return PsSetCreateProcessNotifyRoutine( ( PCREATE_PROCESS_NOTIFY_ROUTINE )DeleteProcessIoInfo, TRUE ); 4725 | } 4726 | -------------------------------------------------------------------------------- /netmon.rc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2024 JiJie.Shi. 3 | * 4 | * This file is part of netmon. 5 | * Licensed under the Gangoo License, Version 1.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | 15 | #include 16 | 17 | #include 18 | 19 | VS_VERSION_INFO VERSIONINFO 20 | FILEVERSION 1,0,3,1006 21 | PRODUCTVERSION 1,0,3,1006 22 | FILEFLAGSMASK 0x3fL 23 | #ifdef _DEBUG 24 | FILEFLAGS 0x9L 25 | #else 26 | FILEFLAGS 0x8L 27 | #endif 28 | FILEOS 0x40004L 29 | FILETYPE 0x3L 30 | FILESUBTYPE 0x0L 31 | BEGIN 32 | BLOCK "StringFileInfo" 33 | BEGIN 34 | BLOCK "040904b0" 35 | BEGIN 36 | VALUE "CompanyName", "coderebasoft corp." 37 | VALUE "FileDescription", "net traffic monitor" 38 | VALUE "FileVersion", "1.0.0.0006" 39 | VALUE "InternalName", "netmon.sys" 40 | VALUE "LegalCopyright", "coderebasoft. all right reserved." 41 | VALUE "OriginalFilename", "netmon.sys" 42 | VALUE "ProductName", "netmon" 43 | VALUE "ProductVersion", "1.0.0.0006" 44 | END 45 | END 46 | BLOCK "VarFileInfo" 47 | BEGIN 48 | VALUE "Translation", 0x409, 1200 49 | END 50 | END 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /netmon_global.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2010-2024 JiJie.Shi. 3 | * 4 | * This file is part of netmon. 5 | * Licensed under the Gangoo License, Version 1.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * 8 | * Unless required by applicable law or agreed to in writing, software 9 | * distributed under the License is distributed on an "AS IS" BASIS, 10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | * See the License for the specific language governing permissions and 12 | * limitations under the License. 13 | */ 14 | 15 | #ifndef ___NETMON_GLOBAL_H__ 16 | #define ___NETMON_GLOBAL_H__ 17 | 18 | // The pplication to call this driver 19 | #define IO_SENDING_SIZE_INIT_VALUE_LOW 0xFFFFFFFF 20 | #define IO_SENDING_SIZE_INIT_VALUE_HIGH 0x7FFFFFFF 21 | #define PROCESS_NETWORK_TRAFFIC_INIT_REFERRENCE 2 22 | #define COMMON_OBJ_NAME_MAX_LENGTH 0x400 23 | #define TDI_EVENT_CONTEXT_MARK 0xFEC02B00 24 | #define TDI_FILTER_LOOKASIDE_POOL_TAG 'vect' 25 | #define TDI_FILTER_TIMER_ELAPSE_TIME -10000000 //1 second 26 | #define WAIT_CONFIGURED_PROC_TIME -100000 //10 milli second 27 | #define SHORT_PATH_SIGN L'~' 28 | #define PATH_DELIM L'\\' 29 | #define CONST_STRING_SIZE( const_str ) ( DWORD )( sizeof( const_str ) - sizeof( const_str[ 0 ] ) ) 30 | #define FILE_SYMBLOLIC_NAME_PREFIX L"\\??\\\\:\\" 31 | #define FILE_SYMBLOLIC_NAME_PREFIX_SIZE CONST_STRING_SIZE( FILE_SYMBLOLIC_NAME_PREFIX ) 32 | 33 | #define PROCESS_IMAGE_FILE_PATH_INFO_MAX_LENGTH 300 34 | #define MAX_PATH 260 35 | #define SYSTEM_IDLE_PROCESS_ID 0 36 | #define SYSTEM_SYSTEM_PROCESS_ID 4 37 | 38 | #define IRP_PROCESS_INFO 0x01 39 | #define PROCESS_IO_OUTPUT_INFO 0x02 40 | #define IO_INTERNAL_CONTROL_INFO 0x04 41 | #define IRP_COMPLETION_INFO 0x08 42 | #define TIMER_DPC_INFO 0x10 43 | #define PROCESS_NEW_IO_INFO 0x20 44 | #define DRIVER_UNLOAD_INFO 0x40 45 | #define PROCESS_IRP_LIST_INFO 0x80 46 | #define PROCESS_START_THREAD_INFO 0x0100 47 | #define IO_CONTROL_INFO 0x0200 48 | #define RECV_EVENT_HANDLER_INFO 0x0400 49 | #define SEND_SPEED_CONTROL_INFO 0x0800 50 | #define CLEANUP_INFO 0x1000 51 | #define OUTPUT_ALL_PROCESS_IO_INFO 0x2000 52 | #define OUTPUT_ALL_PROCESS_CONTROL_INFO 0x4000 53 | #define RESTORE_EVENT_HANDLER_INFO 0x0008000 54 | #define ADD_PROCESS_CONTROL_INFO 0x00010000 55 | #define SYNC_SEND_IRP_PROCESS_INFO 0x00020000 56 | #define RELEASE_PROCESS_INFO 0x00040000 57 | #define READ_USER_PROC_PEB_INFO 0x00080000 58 | #define DRIVER_ENTRY_INFO 0x00100000 59 | #define IRP_CANCEL_INFO 0x00200000 60 | #define PROCESS_COMMON_INFO 0x80000000 61 | 62 | #define BP_ON_GET_ALL_PROCESS_IO 0x01 63 | #define BP_ON_GET_ALL_PROCESS_CONTROL 0x02 64 | #define BP_ON_ADD_PROCESS_CONTROL 0x04 65 | 66 | #define IOCTL_SELF_PROTECT_NOTIFY CTL_CODE( FILE_DEVICE_UNKNOWN, 0x101, METHOD_BUFFERED, FILE_ANY_ACCESS ) 67 | #define IOCTL_TDI_GET_TDI_FILTER_DRIVER_VERSION CTL_CODE( FILE_DEVICE_UNKNOWN, 0x102, METHOD_BUFFERED, FILE_ANY_ACCESS ) 68 | #define IOCTL_TDI_GET_ALL_PROCESS_IO_INFO CTL_CODE( FILE_DEVICE_UNKNOWN, 0x103, METHOD_BUFFERED, FILE_ANY_ACCESS ) 69 | #define IOCTL_TDI_OPEN_FILTERING CTL_CODE( FILE_DEVICE_UNKNOWN, 0x104, METHOD_BUFFERED, FILE_ANY_ACCESS ) 70 | #define IOCTL_TDI_CLOSE_FILTERING CTL_CODE( FILE_DEVICE_UNKNOWN, 0x105, METHOD_BUFFERED, FILE_ANY_ACCESS ) 71 | #define IOCTL_TDI_CHECK_FILTERING_STATE CTL_CODE( FILE_DEVICE_UNKNOWN, 0x106, METHOD_BUFFERED, FILE_ANY_ACCESS ) 72 | #define IOCTL_TDI_GET_ALL_TRAFFIC CTL_CODE( FILE_DEVICE_UNKNOWN, 0x107, METHOD_BUFFERED, FILE_ANY_ACCESS ) 73 | 74 | #define IOCTL_TDI_START_UPDATE_PROCESS_IO_INFO CTL_CODE( FILE_DEVICE_UNKNOWN, 0x201, METHOD_BUFFERED, FILE_ANY_ACCESS ) 75 | #define IOCTL_TDI_GET_ALL_PROCESS_INFO CTL_CODE( FILE_DEVICE_UNKNOWN, 0x202, METHOD_BUFFERED, FILE_ANY_ACCESS ) 76 | #define IOCTL_TDI_RELEASE_ALL_PROCESS_INFO CTL_CODE( FILE_DEVICE_UNKNOWN, 0x203, METHOD_BUFFERED, FILE_ANY_ACCESS ) 77 | #define IOCTL_TDI_SET_DEBUG_TRACE_FLAG CTL_CODE( FILE_DEVICE_UNKNOWN, 0x204, METHOD_BUFFERED, FILE_ANY_ACCESS ) 78 | #define IOCTL_TDI_SET_BP_FLAG CTL_CODE( FILE_DEVICE_UNKNOWN, 0x205, METHOD_BUFFERED, FILE_ANY_ACCESS ) 79 | 80 | typedef struct __PROCESS_INFORMATION_RECORD 81 | { 82 | WCHAR szNativeImageFileName[ PROCESS_IMAGE_FILE_PATH_INFO_MAX_LENGTH ]; 83 | WCHAR szImageFileName[ MAX_PATH ]; 84 | BOOL bRemove; 85 | BOOL bStopSend; 86 | BOOL bStopRecv; 87 | LARGE_INTEGER SendingSpeed; 88 | } PROCESS_INFORMATION_RECORD, *PPROCESS_INFORMATION_RECORD; 89 | 90 | #endif //___NETMON_GLOBAL_H__ --------------------------------------------------------------------------------