要生成NB5.5的服务端,首先编译“svchost”项目,该项目生成NBVip.dll和NBVip.lib动态库文件。之后,将这两个文件拷贝到“InstallServer”项目的目录下,打开“InstallServer”项目,将NBVip.dll导入到项目中,并将其ID设置为IDR_DLL。
接下来编译“InstallServer”项目,生成名为“service.exe”的程序,并将该程序拷贝到“NetBot”项目的“res”文件夹中,并将“service.exe”导入到“NetBot”项目中,ID设置为IDR_EXE。最后编译“NetBot”项目,得到NB5.5的客户端。
在NB5.5的客户端中,点击工具栏中“配服务端”,弹出“配服务端”对话框。在选择了服务端的配置之后,点击“生成”按键,则会生成一个名为“NB_Server.exe”的程序,该程序即为NB5.5的服务端程序。
1 NBVip.dll和NBVip.lib的生成
在svchost.cpp的ServiceMain()入口函数中,创建RunningThread线程,在该线程中又创建ConnectThread线程,创建套接字并连接客户端,通过while()循环不断地接收来自客户端的指令,并将反馈数据发送给客户端。
NBVip.dll和NBVip.lib的生成的详细流程参见“NetBots5.5代码分析之套接字模型2”。
2 “service.exe”的生成
“service.exe”程序由“InstallServer”项目生成。
2.1 DLL资源的释放
在InstallServer.cpp的入口函数WinMain()中,首先调用自定义函数ReleaseResource()函数将之前导入到项目中的DLL资源进行释放:
ReleaseResource(NULL, IDR_DLL, “DLL”, szDllPath);
其中,函数的第一个参数表示模块的句柄;第二个参数表示要释放的资源的ID;第三个参数表示要释放的资源的类型;第四个参数表示资源释放后的绝对路径。szDllPath指定的文件即为NBVip.dll文件。
2.2 DLL的导入
在释放了DLL资源之后,接下来要导入该DLL文件。
HMODULE hModule = LoadLibrary(szDllPath);
其中,szDllPath即为在“2.1”中指定的资源释放后的绝对路径。
2.3 DLL中函数的调用
导入了DLL之后,接下来调用DLL中的函数。
BOOL (_stdcall *InstallFunc)(LPCSTR szDllPath);
(FARPROC&)InstallFunc = GetProcAddress(hModule, “Install”);
InstallFunc(szDllPath);
其中,第1行定义了一个名为InstallFunc的函数指针;第2行将DLL文件中的Install函数的地址保存在InstallFunc中,即获取到了Install函数;第3行调用该函数,并将szDllPath作为该函数的参数。
可以在svchost.cpp源文件中查看Install()函数的功能。该函数的作用是根据服务端的配置信息在服务端电脑中安装服务及修改注册表。
3服务端程序“NB_Server.exe”的生成
通过点击客户端“配服务端”对话框中的“生成”按键,产生服务端程序。“配服务端”对话框对应的是NetBot项目中的CServerDlg类,当点击“生成”按键,会调用CServerDlg::OnCreate()函数。
3.1 获取服务端配置信息
在该函数中,首先获取用户在“配服务端”对话框中选择的服务端配置信息。服务端的配置信息是自定义结构MODIFY_DATA的对象,该结构包含了服务端版本号、VIP的ID号、替换服务还是新建服务、服务名称、服务显示和服务描述等信息。这些信息都保存在全局变量mdoify_data中。
3.2 导入service.exe
service.exe是在“InstallServer”项目中生成的程序,并且已经被导入到“NetBot”项目中。通过FindResource()、SizeofResource()和LoadResource()函数将“service.exe”导入。
3.3 创建服务端
3.3.1 为文件分配内存空间
首先在内存中为“service.exe”分配空间:
p=(LPBYTE)GlobalAlloc(GPTR, dwSize);
其中,GPTR表示分配一个固定的内存并且将该内存清零;dwSize是分配的内存长度。分配的内存地址保存在p中。
3.3.2 将文件内容拷贝到内存中
CopyMemory((LPVOID)p, (LPCVOID)LockResource(hResData), dwSize);
其中,p表示分配的内存地址;LockResource(hResData)是在“3.2”中导入的service.exe的地址;dwSize是程序的大小。
3.3.3 配置信息的写入
接下来将在“3.1”中获取的配置信息写入到文件内存中。
CopyMemory((LPVOID)(p+iPos), (LPCVOID)&modify_data, sizeof(MODIFY_DATA));
其中,p+iPos是配置信息在文件中的位置;modify_data是配置信息;sizeof(MODIFY_DATA)是配置信息的大小。
3.3.4 服务端文件的创建
最后,将内存中的服务端文件写入到创建好的服务端文件中。
CreateFile(Path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
WriteFile(hFile, (LPVOID)p, dwSize, &dwWritten, NULL);
其中,第1行是创建服务端文件;第2行是将内存中的文件数据写入到服务端文件中,完成服务端的创建。
4 服务端程序流程