0%

WindowsAPI - 进程线程

最近在学习 Win32编程,所以顺便将每日所学记录下来,一方面为了巩固学习的知识,另一方面也为同样在学习Win32开发的童鞋们提供一份参考。

本系列博文均根据学习《WindowsAPI开发详解》一书总结而来;

运行环境:

  • 操作系统: Windows 10家庭版
  • 编译器:Visual Studio 2013

进程线程模块

运行一个程序就会产生一个进程。进程是应用程序的实例。进程包括一个虚拟地址空间及代码、数据、对象等程序运行所需环境和资源的集合;

基本概念

程序与进程

  • 可执行文件
    • 程序的载体是可执行文件。可执行文件中包括了运行所需的程序、数据以配置信息等。Windows平台的可执行程序基本都是PE格式
  • 应用程序
    • 程序是一系列具有特定功能、能完成操作的代码集合。
  • 进程
    • 进程提供了程序运行所需要的资源、虚拟内存地址空间、各种数据、可执行代码、需要使用的各种内核对象、系统调用接口等,还至少包含了一个线程;

进程管理

创建进程

  • 父子进程
    • 如果一个进程创建了另外一个进程,那么被创建的进程成为子进程,创建者为父进程
  • 启动参数
    • 进程创建后,可以调用GetCommandLine、GetStartupInfo获取启动参数、启动信息;
  • 进程句柄和进程标识
    • 如果需要知道自己的句柄,可以使用GetCurrentProcess和GetCurrentPocessId函数获取自己的句柄和PID;
  • 退出和终止线程
    • 代码执行完成后自动退出,如果要立即退出调用ExitProcess,使其他进程退出调用TerminateProcess函数;

CreateProcess

1
2
3
4
5
6
7
8
9
10
11
12
13
BOOL CreateProcess(
LPCTSTR lpApplicationName, // name of executable module //进程名,进程要拉起的程序
LPTSTR lpCommandLine, // command line string //命令行参数
LPSECURITY_ATTRIBUTES lpProcessAttributes, // SD //安全描述符
LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD
BOOL bInheritHandles, // handle inheritance option //是否继承
DWORD dwCreationFlags, // creation flags //创建标志
LPVOID lpEnvironment, // new environment block //新进程环境快,如果为空则继承父进程环境
LPCTSTR lpCurrentDirectory, // current directory name //当前目录
LPSTARTUPINFO lpStartupInfo, // startup information //START_INFO结构体
LPPROCESS_INFORMATION lpProcessInformation // process information //PROCESS_INFOMATION结构体
);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <windows.h>
#include <stdio.h>

DWORD CreateChildProcess(LPTSTR szChildProcessCmd);

/*************************************
* int main(void)
* 功能 演示进程创建
*
* 参数 未使用
**************************************/
int main()
{
TCHAR szApplicationName[] = TEXT("notepad.exe");
CreateChildProcess(szApplicationName);

}
/*************************************
* DWORD CreateChildProcess(LPSTR szChildProcessCmd)
* 功能 演示创建子进程
*
* 参数 LPSTR szChildProcessCmd 启动子进程的命令行
* 返回值 成功返回,失败返回
**************************************/
DWORD CreateChildProcess(LPTSTR szChildProcessCmd)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
ZeroMemory(&pi, sizeof(pi));
si.cb = sizeof(si);
//
if (!CreateProcess(
NULL, //对象名称
szChildProcessCmd, //进程命令行
NULL, //不继承进程句柄
NULL, //不继承线程句柄
FALSE, //不继承句柄
0, //创建标志
NULL, //使用父进程环境变量
NULL, //使用父进程目录作为当前目录
&si, //进程的详细信息
&pi //
)
)
{
printf("CreateChildProcess Error = %d\n", GetLastError());
return FALSE;
}
// 在创建成功后父进程也可直接退出,这里等待子进程执行结束

// 等待子进程结束
// 使用到了通过PROCESS_INFORMATION 返回的相关信息,hProcess为子进程句柄
// 父进程也可以不等待子进程运行完成而直接退出
WaitForSingleObject(pi.hProcess, INFINITE);
// 关闭进程句柄和线程句柄
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return 0;
}

获取和设置环境变量

GetEnvironmentStrings

获取所有环境变量的字符串;

1
LPVOID GetEnvironmentStrings(VOID);

线程

创建线程

CreateThread

使用CreateThread函数可以创建线程,每一个线程都必须拥有线程函数,线程函数是线程执行的起点。

1
2
3
4
5
6
HANDLE CreateThread (  SEC_ATTRS SecurityAttributes,  //安全描述符
ULONG StackSize, //堆栈大小
SEC_THREAD_START StartFunction, //线程函数
PVOID ThreadParameter, //线程函数
ULONG CreationFlags, //创建标志
PULONG ThreadId); //线程ID

ThreadProc

1
DWORD WINAPI ThreadProc(LPVOID lpParameter);

进程中每一个线程都有一个句柄和一个标识符,每一个线程的TID都不一样,因此TID用于标识一个线程。如果只要线程的TID,可以通过OpenThread获取线程句柄,如果知道线程的句柄,可以使用GetThreadId获取线程的TID;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <Windows.h>
#include <tchar.h>
#include <stdio.h>

#define MAX_THREADS 5
typedef struct _THREAD_PARAM{
DWORD i;
DWORD dwRandom;
DWORD dwData;
}THREAD_PARAM,*LPTHREAD_PARAM;

DWORD WINAPI ThreadProc(LPVOID lpParam)
{
LPTHREAD_PARAM pData;
// 参数数据类型
pData = (LPTHREAD_PARAM)lpParam;
// 显示参数
printf("TID = %u,\t Parameters = %u, %u, %u\n",
GetCurrentThreadId(),
pData->i, pData->dwRandom, pData->dwData);
// 释放保存参数的内存(在主线程中分配的).
HeapFree(GetProcessHeap(), 0, pData);
return 0;
}

int main()
{
LPTHREAD_PARAM pData;
DWORD dwThreadId[MAX_THREADS];
HANDLE hThread[MAX_THREADS];
int i;
for (i = 0; i < MAX_THREADS; i++)
{
pData = (LPTHREAD_PARAM)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(THREAD_PARAM));
if (pData == NULL)
{
printf("HeapAlloc Error\n");
ExitProcess(2);
}
pData->i = i;
pData->dwRandom = rand();
pData->dwData = 100;
hThread[i] = CreateThread(
NULL, // 默认安全属性
0, // 默认堆栈大小
ThreadProc, // 线程函数
pData, // 参数
0, // 默认创建标志
&dwThreadId[i]); // 返回TID
// 判断是否创建成功
if (hThread[i] == NULL)
{
ExitProcess(i);
}
}
WaitForMultipleObjects(MAX_THREADS, hThread, TRUE, INFINITE);
for (size_t i = 0; i < 5; i++)
{
CloseHandle(hThread[i]);
}
getchar();
return 0;
}


线程挂起、恢复、切换、终止

Sleep

1
2
void Sleep(DWORD dwMilliseconds); 
DWORD SleepEx( DWORD dwMilliseconds, // time-out interval BOOL bAlertable // early completion option);

SuspendThread、ResumeThread

SuspendThread是挂起指定线程,不同于Sleep,挂起的线程只能通过ResumeThread恢复

1
2
DWORD SuspendThread(HANDLE hThread); 
DWORD ResumeThread( HANDLE hThread);

SwitchtoThread

SwitchToThread函数的作用是使得线程主动让出程序的执行;

1
BOOL SwitchToThread(VOID);

ExitThread

退出本线程

1
VOID ExitThread( DWORD dwExitCode); 

TerminateThread

终止线程线程

1
2
BOOL TerminateThread(HANDLE hThread, 	//句柄
DWORD dwExitCode); //退出码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <Windows.h>
#include <tchar.h>
#include <stdio.h>

DWORD WINAPI ThreadProc(LPVOID lpParam)
{
LPDWORD pData;
DWORD i = 0;
pData = (LPDWORD)lpParam;
for (; i < 10; i++)
{
Sleep(100);
printf("TID = %u,\t Paramters = %u\t i = %u\n", GetCurrentThreadId(), *pData, i);
}
ExitThread(1);
return 0;

}

int main()
{
DWORD dwData;
DWORD dwThreadId[2];
HANDLE hThread[2];
//创建线程
dwData = 1;
hThread[0] = CreateThread(NULL, 0, ThreadProc, &dwData, CREATE_SUSPENDED, &dwThreadId[0]); //挂起方式创建线程
if (hThread[0] == NULL)
{
ExitProcess(0);
}
dwData = 2;
hThread[1] = CreateThread(NULL, 0, ThreadProc, &dwData, 0, &dwThreadId[1]);
if (hThread[0] == NULL)
{
ExitProcess(1);
}
Sleep(200);
ResumeThread(hThread[0]); //恢复线程运行
SuspendThread(hThread[1]); //将线程1挂起
Sleep(300); //等待
TerminateThread(hThread[0], 0); //结束线程0
ResumeThread(hThread[1]); //恢复线程1
WaitForMultipleObjects(2, hThread, TRUE, INFINITE); //等待线程结束运行
CloseHandle(hThread[0]); //关闭句柄
CloseHandle(hThread[1]);
getchar();
return 0;
}

远程线程

如果进程具有特定权限,可以为其他进程创建线程。

CreateRemoteThread

1
2
3
4
5
6
7
8
9
10
HANDLE CreateRemoteThread(
HANDLE hProcess, // handle to process
LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD
SIZE_T dwStackSize, // initial stack size
LPTHREAD_START_ROUTINE lpStartAddress, // thread function
LPVOID lpParameter, // thread argument
DWORD dwCreationFlags, // creation option
LPDWORD lpThreadId // thread identifier
);

WriteProcessMemory

1
2
3
4
5
BOOL WriteProcessMemory( HANDLE hProcess, 
LPVOID lpBaseAddress,
LPVOID lpBuffer,
DWORD nSize,
LPDWORD lpNumberOfBytesWritten );
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#include <Windows.h>
#include <tchar.h>
#include <TlHelp32.h>
#include <stdio.h>
BOOL LoadRometeDll(DWORD dwProcessId, LPTSTR lpszLibName)
{
BOOL bResult = FALSE;
HANDLE hProcess = NULL;
HANDLE hThread = NULL;
PSTR pszLibFileRemote = NULL;
DWORD dwCch;
PTHREAD_START_ROUTINE pfnThreadRtn;
__try
{
//获取想要注入代码的句柄
hProcess = OpenProcess(
PROCESS_ALL_ACCESS,
FALSE,
dwProcessId
);
if (hProcess == NULL)
{
__leave;
}
dwCch = 1 + lstrlen(lpszLibName); //计算DLL路径名需要的字节数
pszLibFileRemote = (PSTR)VirtualAllocEx(hProcess, NULL, dwCch, MEM_COMMIT, PAGE_READWRITE); //远程线程中为路径分配空间
if (pszLibFileRemote == NULL)
{
__leave;
}
if (!WriteProcessMemory(hProcess, pszLibFileRemote, lpszLibName, dwCch, NULL)) //将DLL名复制到远程线程空间中
{
__leave;
}
pfnThreadRtn = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryA"); //获取LoadLibrary真实地址
if (pfnThreadRtn == NULL)
{
__leave;
}

hThread = CreateRemoteThread(hProcess, NULL, 0, pfnThreadRtn, (PVOID)pszLibFileRemote, 0, NULL); //创建远程线程,并通过远程调用DLL
if (hThread == NULL)
{
__leave;
}
WaitForSingleObject(hThread, INFINITE);
bResult = TRUE;

}
__finally
{
// 关闭句柄.
if (pszLibFileRemote != NULL)
VirtualFreeEx(hProcess, (PVOID)pszLibFileRemote, 0, MEM_RELEASE);
if (hThread != NULL)
CloseHandle(hThread);
if (hProcess != NULL)
CloseHandle(hProcess);
}
return bResult;
}


BOOL GetProcessIdByName(LPTSTR szProcessName, LPDWORD lpPID)
{
// 变量及初始化
STARTUPINFO st;
PROCESS_INFORMATION pi;
PROCESSENTRY32 ps;
HANDLE hSnapshot;
ZeroMemory(&st, sizeof(STARTUPINFO));
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
st.cb = sizeof(STARTUPINFO);
ZeroMemory(&ps, sizeof(PROCESSENTRY32));
ps.dwSize = sizeof(PROCESSENTRY32);
// 遍历进程
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot == INVALID_HANDLE_VALUE)
{
return FALSE;
}

if (!Process32First(hSnapshot, &ps))
{
return FALSE;
}
do
{
// 比较进程名
if (lstrcmpi(ps.szExeFile, TEXT("explorer.exe")) == 0)
{
// 找到了
*lpPID = ps.th32ProcessID;
CloseHandle(hSnapshot);
return TRUE;
}
} while (Process32Next(hSnapshot, &ps));
// 没有找到
CloseHandle(hSnapshot);
return FALSE;
}

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, INT)
{
DWORD dwPID;
//获取进程PID
if (!GetProcessIdByName(TEXT("explorer.exe"), &dwPID))
{
return 0;
}
if (!LoadRometeDll(dwPID, TEXT("msg.dll")))
{
return 0;
}
getchar();
return 1;
}

进程状态信息

PS和Tool Help

使用CreateToolhelp32Snapshot获取快照;

遍历系统进程

使用EnumProcess函数和Process32First和Process32Next函数完成列举进程;

EnumProcess

1
2
3
BOOL EnumProcesses(  DWORD *lpidProcess,  // array of process identifiers		//保存获取的进程PID数组
DWORD cb, // size of array //指向数组的大小、字节
DWORD *cbNeeded // number of bytes returned); //获取PID的个数

CreateToolhelp32Snapshot

1
2
HANDLE WINAPI CreateToolhelp32Snapshot(  DWORD dwFlags,       	//指明快照信息
DWORD th32ProcessID ); //PID 所有进程的快照

Process32First

1
2
BOOL WINAPI Process32First(  HANDLE hSnapshot,       	// 返回的快照句柄
LPPROCESSENTRY32 lppe ); //PROCESSENTRY32结构变量的指针
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
#include <Windows.h>
#include <Psapi.h>
#include <Tlhelp32.h>
#include <stdio.h>
/* 预处理声明 */
#pragma comment (lib, "psapi.lib")
/* 函数声明 */
VOID WINAPI EnumProcess1();
VOID WINAPI EnumProcess2();
VOID ListProcessModules1( DWORD dwPID );
VOID ListProcessModules2( DWORD dwPID);
VOID PrintMemoryInfo( DWORD dwPID );
VOID ShowProcessMemoryInfo( DWORD dwPID );
VOID ListHeapInfo( DWORD dwPID );
VOID ListProcessThreads( DWORD dwPID );
VOID PrintError( LPTSTR msg );

/*************************************
* VOID WINAPI EnumProcess1()
* 功能 调用EnumProcesses遍历进程,
* 并调用ListProcessModules1函数和
* ListProcessThreads函数列举模块和线程
*
* 无参数,无返回值
**************************************/
VOID WINAPI EnumProcess1()
{
// 假设不超过1024个进程
DWORD aProcesses[1024], cbNeeded, cProcesses;
unsigned int i;
// 调用EnumProcesses
if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )
return;
// 进程数
cProcesses = cbNeeded / sizeof(DWORD);
for ( i = 0; i < cProcesses; i++ )
{
// 显示进程信息
printf( "\n\n**************************************************" );
printf("\nPROCESS : %u\n\n",aProcesses[i]);
printf( "\n****************************************************" );
// 列举模块信息和线程信息
ListProcessModules1( aProcesses[i] );
ListProcessThreads( aProcesses[i] );
}
}
/*************************************
* VOID WINAPI EnumProcess2()
* 功能 调用Process32First和Process32Next遍历进程,
* 并调用ListProcessModules2函数列举模块,
* 调用ShowProcessMemoryInfo函数显示内存使用情况
*
* 无参数,无返回值
**************************************/
VOID WINAPI EnumProcess2()
{
HANDLE hProcessSnap;
HANDLE hProcess;
PROCESSENTRY32 pe32;
DWORD dwPriorityClass;
// Snapshot
hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
if( hProcessSnap == INVALID_HANDLE_VALUE )
{
PrintError( "CreateToolhelp32Snapshot (of processes)" );
return ;
}
// 设置输入参数,结构的大小
pe32.dwSize = sizeof( PROCESSENTRY32 );

// 开始列举进程
if( !Process32First( hProcessSnap, &pe32 ) )
{
PrintError( "Process32First" ); // 出错信息
CloseHandle( hProcessSnap );
return ;
}
do
{
// 打印进程名
printf( "\n\n=====================================================" );
printf( "\nPROCESS NAME: %s", pe32.szExeFile );
printf( "\n-----------------------------------------------------" );

// 获取优先级
dwPriorityClass = 0;
hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID );
if( hProcess == NULL )
PrintError( "OpenProcess" );
else
{
dwPriorityClass = GetPriorityClass( hProcess );
if( !dwPriorityClass )
PrintError( "GetPriorityClass" );
CloseHandle( hProcess );
}
// 打印进程相关信息
printf( "\n process ID = 0x%08X", pe32.th32ProcessID );
printf( "\n thread count = %d", pe32.cntThreads );
printf( "\n parent process ID = 0x%08X", pe32.th32ParentProcessID );
printf( "\n Priority Base = %d", pe32.pcPriClassBase );
if( dwPriorityClass )
printf( "\n Priority Class = %d", dwPriorityClass );

// 获取模块信息,显示内存使用情况
ListProcessModules2( pe32.th32ProcessID );
PrintMemoryInfo(pe32.th32ProcessID);
ListHeapInfo(pe32.th32ProcessID);

} while( Process32Next( hProcessSnap, &pe32 ) );

CloseHandle( hProcessSnap ); //关闭句柄
return ;
}

/*************************************
* VOID ListProcessModules1( DWORD dwPID )
* 功能 调用EnumProcessModules函数
* 列举和显示进程加载的模块
*
* 参数 DWORD dwPID 进程PID
**************************************/
VOID ListProcessModules1( DWORD dwPID )
{
HMODULE hMods[1024];
HANDLE hProcess;
DWORD cbNeeded;
unsigned int i;

printf( "\nListProcessModules1 Process ID %u\n", dwPID );

// 打开进程,获得句柄
hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ,
FALSE, dwPID );
if (NULL == hProcess)
return;
// 调用EnumProcessModules
if( EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
{
for ( i = 0; i < (cbNeeded / sizeof(HMODULE)); i++ )
{
TCHAR szModName[MAX_PATH];
// 获取获取的路径
if ( GetModuleFileNameEx( hProcess, hMods[i], szModName,
sizeof(szModName)/sizeof(TCHAR)))
{
// 打印
printf( TEXT("\t%s (0x%08X)\n"), szModName, hMods[i] );
}
}
}
CloseHandle( hProcess ); // 关闭进程句柄
}

/*************************************
* VOID ListProcessModules2( DWORD dwPID )
* 功能 调用Module32First和Module32Next函数
* 列举和显示进程加载的模块
*
* 参数 DWORD dwPID 进程PID
**************************************/
VOID ListProcessModules2( DWORD dwPID)
{
HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
MODULEENTRY32 me32;
printf( "\nListProcessModules2 Process ID %u\n", dwPID );
// Snapshot
hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID );
if( hModuleSnap == INVALID_HANDLE_VALUE )
{
PrintError( "CreateToolhelp32Snapshot (of modules)" );
return ;
}
// 设置输入参数,结构的大小
me32.dwSize = sizeof( MODULEENTRY32 );
// 开始获取模块信息
if( !Module32First( hModuleSnap, &me32 ) )
{
PrintError( "Module32First" ); // Show cause of failure
CloseHandle( hModuleSnap ); // Must clean up the snapshot object!
return ;
}
do
{
printf( "\n\n MODULE NAME: %s", me32.szModule );
printf( "\n executable = %s", me32.szExePath );
printf( "\n process ID = 0x%08X", me32.th32ProcessID );
printf( "\n ref count (g) = 0x%04X", me32.GlblcntUsage );
printf( "\n ref count (p) = 0x%04X", me32.ProccntUsage );
printf( "\n base address = 0x%08X", (DWORD) me32.modBaseAddr );
printf( "\n base size = %d", me32.modBaseSize );

} while( Module32Next( hModuleSnap, &me32 ) );
CloseHandle( hModuleSnap ); // 关闭句柄
return ;
}

/*************************************
* VOID PrintMemoryInfo( DWORD dwPID )
* 功能 显示进程的内存使用情况
*
* 参数 DWORD dwPID 进程PID
**************************************/
VOID PrintMemoryInfo( DWORD dwPID )
{
HANDLE hProcess;
PROCESS_MEMORY_COUNTERS pmc;

printf( "\nProcess ID: %u\n", dwPID );

hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ,
FALSE, dwPID );
if (NULL == hProcess)
return;

if ( GetProcessMemoryInfo( hProcess, &pmc, sizeof(pmc)) )
{
printf( "\tPageFaultCount: 0x%08X\n", pmc.PageFaultCount );
printf( "\tPeakWorkingSetSize: 0x%08X\n",
pmc.PeakWorkingSetSize );
printf( "\tWorkingSetSize: 0x%08X\n", pmc.WorkingSetSize );
printf( "\tQuotaPeakPagedPoolUsage: 0x%08X\n",
pmc.QuotaPeakPagedPoolUsage );
printf( "\tQuotaPagedPoolUsage: 0x%08X\n",
pmc.QuotaPagedPoolUsage );
printf( "\tQuotaPeakNonPagedPoolUsage: 0x%08X\n",
pmc.QuotaPeakNonPagedPoolUsage );
printf( "\tQuotaNonPagedPoolUsage: 0x%08X\n",
pmc.QuotaNonPagedPoolUsage );
printf( "\tPagefileUsage: 0x%08X\n", pmc.PagefileUsage );
printf( "\tPeakPagefileUsage: 0x%08X\n",
pmc.PeakPagefileUsage );
}
CloseHandle( hProcess );
}

/*************************************
* VOID ListHeapInfo( DWORD dwPID )
* 功能 显示进程的堆分配情况
*
* 参数 DWORD dwPID 进程PID
**************************************/
VOID ListHeapInfo( DWORD dwPID )
{
HEAPLIST32 hl;
HEAPENTRY32 he;
HANDLE hSnapshot = INVALID_HANDLE_VALUE;

printf( "\\ListHeapInfo Process ID %u\n", dwPID );

// Snapshot
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPHEAPLIST , dwPID );
if( hSnapshot == INVALID_HANDLE_VALUE )
{
PrintError( "CreateToolhelp32Snapshot (of heaplist)" );
return ;
}
// 设置输入参数,结构的大小
hl.dwSize = sizeof( HEAPLIST32 );

// 开始获取信息
if( !Heap32ListFirst( hSnapshot, &hl ) )
{
PrintError( "Heap32ListFirst" );
CloseHandle( hSnapshot );
return ;
}
do
{
printf( "\n\tHeap ID =%u", hl.th32HeapID );
printf( "\tHeap Flags = %u", hl.dwFlags );
he.dwSize = sizeof(HEAPENTRY32);
if( !Heap32First(&he,dwPID,hl.th32HeapID) )
{
PrintError( "Heap32First" ); // 出错
CloseHandle( hSnapshot );
return ;
}
do
{
// 显示信息
printf( "\n\t\t Heap Address\t= %u",he.dwAddress );
printf( "\t Heap Size\t= %u",he.dwBlockSize);
printf( "\t Heap Flags\t= %u",he.dwFlags);
printf( "\t Heap Handle\t= %u",he.hHandle);
} while( Heap32Next(&he ));

} while( Heap32ListNext( hSnapshot, &hl ) );
CloseHandle( hSnapshot ); // 关闭句柄
return ;
}

/*************************************
* VOID ListProcessThreads( DWORD dwPID )
* 功能 调用Thread32First和Thread32Next
* 显示一个进程的线程
*
* 参数 DWORD dwPID 进程PID
**************************************/
VOID ListProcessThreads( DWORD dwPID )
{
HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
THREADENTRY32 te32;

printf( "\\ListProcessThreads Process ID %u\n", dwPID );

// Snapshot
hThreadSnap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
if( hThreadSnap == INVALID_HANDLE_VALUE )
return ;

// 设置输入参数,结构的大小
te32.dwSize = sizeof(THREADENTRY32 );

// 开始获取信息
if( !Thread32First( hThreadSnap, &te32 ) )
{
PrintError( "Thread32First" ); // Show cause of failure
CloseHandle( hThreadSnap ); // Must clean up the snapshot object!
return ;
}
do
{
if( te32.th32OwnerProcessID == dwPID )
{
// 显示相关信息
printf( "\n THREAD ID = 0x%08X", te32.th32ThreadID );
printf( "\t base priority = %d", te32.tpBasePri );
printf( "\t delta priority = %d", te32.tpDeltaPri );
}
} while( Thread32Next(hThreadSnap, &te32 ) );

CloseHandle( hThreadSnap );
return ;

}

// 打印出错信息
VOID PrintError( LPTSTR msg )
{
DWORD eNum;
TCHAR sysMsg[256];
TCHAR* p;

eNum = GetLastError( );
FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, eNum,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
sysMsg, 256, NULL );
p = sysMsg;
while( ( *p > 31 ) || ( *p == 9 ) )
++p;
do { *p-- = 0; } while( ( p >= sysMsg ) &&
( ( *p == '.' ) || ( *p < 33 ) ) );
printf( "\n WARNING: %s failed with error %d (%s)", msg, eNum, sysMsg );
}

void main()
{
printf("EnumProcess1 \n");
EnumProcess1();
printf("\n\n\nEnumProcess2 \n");
EnumProcess2();
}

动态链接库