Windows服务访问控制


Warning: WP_Syntax::substituteToken(): Argument #1 ($match) must be passed by reference, value given in /www/wwwroot/fawdlstty.com/wp-content/plugins/wp-syntax/wp-syntax.php on line 383

服务控制在win32用户层系统编程中比较重要,一般用于创建自启动项或加载驱动,这样的话启动服务就是载入驱动,停止服务就是卸载驱动,极大方便了驱动控制。下面贴一个服务控制代码,可用于方便的控制服务。

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
#pragma once
#ifndef __HSERVER_HPP__
#define __HSERVER_HPP__
 
#include <Windows.h>
 
class hService {
    SC_HANDLE h_scm = NULL, h_service = NULL;
    QUERY_SERVICE_CONFIG *h_qsc = NULL;
    SERVICE_STATUS h_status;
 
public:
    hService (LPCTSTR serv_name) {
        h_qsc = (LPQUERY_SERVICE_CONFIG)new BYTE [8 * 1024];
        if ((h_scm = ::OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS)) && serv_name && serv_name[0]) {
            h_service = ::OpenService (h_scm, serv_name, SERVICE_ALL_ACCESS);
        }
    }
    ~hService () {
        delete h_qsc;
        if (h_service) ::CloseServiceHandle (h_service);
        if (h_scm) ::CloseServiceHandle (h_scm);
    }
 
    //服务是否正在运行
    BOOL is_running () {
        if (!h_service) return FALSE;
        if (::QueryServiceStatus (h_service, &h_status)) {
            if (h_status.dwCurrentState == SERVICE_RUNNING) return TRUE;
        }
        return FALSE;
    }
 
    //服务是否已停止
    BOOL is_stopped () {
        if (!h_service) return FALSE;
        if (::QueryServiceStatus (h_service, &h_status)) {
            if (h_status.dwCurrentState == SERVICE_STOPPED) return TRUE;
        }
        return FALSE;
    }
 
    //服务是否已暂停
    BOOL is_pause () {
        if (!h_service) return FALSE;
        if (::QueryServiceStatus (h_service, &h_status)) {
            if (h_status.dwCurrentState == SERVICE_PAUSED) return TRUE;
        }
        return FALSE;
    }
 
    //服务是否自动启动
    BOOL is_auto_run () {
        DWORD d;
        if (!h_service) return FALSE;
        if (::QueryServiceConfig (h_service, h_qsc, 8 * 1024, &d)) {
            return h_qsc->dwStartType <= 2;
        }
        return FALSE;
    }
 
    //启动服务
    BOOL start () {
        if (!h_service) return FALSE;
        if (is_running ()) return TRUE;
        return ::StartService (h_service, NULL, NULL);
    }
 
    //停止服务
    BOOL stop () {
        if (!h_service) return FALSE;
        if (is_stopped ()) return TRUE;
        return ::ControlService (h_service, SERVICE_CONTROL_STOP, &h_status);
    }
 
    //暂停服务
    BOOL pause () {
        if (!h_service) return FALSE;
        if (is_running ()) return ::ControlService (h_service, SERVICE_CONTROL_PAUSE, &h_status);
        return TRUE;
    }
 
    //恢复服务
    BOOL resume () {
        if (!h_service) return FALSE;
        if (is_pause ()) return ::ControlService (h_service, SERVICE_CONTROL_CONTINUE, &h_status);
        return is_running ();
    }
 
    //设置自动启动服务
    BOOL auto_start () {
        if (!h_service) return FALSE;
        if (is_auto_run ()) return TRUE;
        SC_LOCK sclLock = ::LockServiceDatabase (h_scm);
        BOOL bRet = ::ChangeServiceConfig (h_service, SERVICE_NO_CHANGE, SERVICE_AUTO_START, SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
        if (sclLock) ::UnlockServiceDatabase (sclLock);
        return bRet;
    }
 
    //设置手动启动服务
    BOOL demand_start () {
        if (!h_service) return FALSE;
        if (!is_auto_run ()) return TRUE;
        SC_LOCK sclLock = ::LockServiceDatabase (h_scm);
        BOOL bRet = ::ChangeServiceConfig (h_service, SERVICE_NO_CHANGE, SERVICE_DEMAND_START, SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
        if (sclLock) ::UnlockServiceDatabase (sclLock);
        return bRet;
    }
 
    //创建服务
    static hService *create_service (LPCTSTR serv_name, LPCTSTR display_name, DWORD service_type, LPCTSTR path) {
        hService *service = new hService (NULL);
        service->h_service = ::CreateService (service->h_scm, serv_name, display_name, SC_MANAGER_ALL_ACCESS, service_type, SERVICE_DEMAND_START, SERVICE_ERROR_IGNORE, path, NULL, NULL, NULL, NULL, NULL);
        return service;
    }
 
    //删除服务
    BOOL delete_service () {
        if (::DeleteService (h_service)) {
            h_service = NULL;
            return TRUE;
        }
        return FALSE;
    }
};
#endif //__HSERVER_HPP__

创建头文件,引入以上代码之后,就可以方便进行服务控制了。调用方式在代码中已有注释。

Windows下编码转换


Warning: WP_Syntax::substituteToken(): Argument #1 ($match) must be passed by reference, value given in /www/wwwroot/fawdlstty.com/wp-content/plugins/wp-syntax/wp-syntax.php on line 383

对于网络程序来说经常需要用到编码转换,比如访问utf8编码网页下载之后,转为unicode进行显示。windows自带的编码API比较难用,所以对其进行简单的封装。分SDK和MFC两个版本代码,SDK版本如下

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
#pragma once
#ifndef __HCODEC_HPP__
#define __HCODEC_HPP__
 
#include <windows .h>
#include <string>
 
class hCodec {
    //不可实例化
    hCodec () = delete;
    ~hCodec () = delete;
 
    static bool hCodec::_conv_Down (std::wstring& _old, std::string& _new, UINT ToType) {
        int lenOld = lstrlenW (_old.c_str ());
        int lenNew = ::WideCharToMultiByte (ToType, 0, _old.c_str (), lenOld, NULL, 0, NULL, NULL);
        std::string s;
        s.resize (lenNew);
        bool bRet = ::WideCharToMultiByte (ToType, 0, _old.c_str (), lenOld, const_cast<char *>(s.c_str ()), lenNew, NULL, NULL);
        _new.clear ();
        _new = s.c_str ();
        return bRet;
    }
    static bool hCodec::_conv_Up (std::string& _old, std::wstring& _new, UINT ToType) {
        int lenOld = lstrlenA (_old.c_str ());
        int lenNew = ::MultiByteToWideChar (ToType, 0, _old.c_str (), lenOld, NULL, 0);
        std::wstring s;
        s.resize (lenNew);
        bool bRet = ::MultiByteToWideChar (ToType, 0, _old.c_str (), lenOld, const_cast<wchar_t *>(s.c_str ()), lenNew);
        _new.clear ();
        _new = s.c_str ();
        return bRet;
    }
 
public:
    static bool hCodec::AnsiToUnicode (std::string& _old, std::wstring& _new) {
        return hCodec::_conv_Up (_old, _new, CP_ACP);
    }
    static bool hCodec::UnicodeToAnsi (std::wstring& _old, std::string& _new) {
        return hCodec::_conv_Down (_old, _new, CP_ACP);
    }
    static bool hCodec::Utf8ToUnicode (std::string& _old, std::wstring& _new) {
        return hCodec::_conv_Up (_old, _new, CP_UTF8);
    }
    static bool hCodec::UnicodeToUtf8 (std::wstring& _old, std::string& _new) {
        return hCodec::_conv_Down (_old, _new, CP_UTF8);
    }
    static bool hCodec::AnsiToUtf8 (std::string& _old, std::string& _new) {
        std::wstring t;
        if (!hCodec::AnsiToUnicode (_old, t)) return false;
        return hCodec::UnicodeToUtf8 (t, _new);
    }
    static bool hCodec::Utf8ToAnsi (std::string& _old, std::string& _new) {
        std::wstring t;
        if (!hCodec::Utf8ToUnicode (_old, t)) return false;
        return hCodec::UnicodeToAnsi (t, _new);
    }
};
 
#endif //__HCODEC_HPP__</wchar_t></char></string></windows>

继续阅读Windows下编码转换

Windows注册表访问的封装


Warning: WP_Syntax::substituteToken(): Argument #1 ($match) must be passed by reference, value given in /www/wwwroot/fawdlstty.com/wp-content/plugins/wp-syntax/wp-syntax.php on line 383

注册表这东西用的越来越少了,但在特定场合还是不可替代的东西。比如开机启动项、环境变量和文件扩展名等各种系统信息都是放在注册表中。
由于注册表API访问稍微麻烦了点,于是我对其进行简单的封装。代码如下:

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
#pragma once
#ifndef __HREG_HPP__
#define __HREG_HPP__
 
#include <Windows.h>
 
// main_key 注册表根键可取值
// HKEY_CLASSES_ROOT
// HKEY_CURRENT_CONFIG
// HKEY_CURRENT_USER
// HKEY_LOCAL_MACHINE
// HKEY_USERS
 
// type 键值类型可取值
// REG_BINARY               二进制数据
// REG_DWORD                双字
// REG_DWORD_LITTLE_ENDIAN  双字小头模式
// REG_DWORD_BIG_ENDIAN     双字大头模式
// REG_EXPAND_SZ            包含未展开的环境变量的引用的字串
// REG_LINK                 一个用 RegCreateKeyEx 传 REG_OPTION_CREATE_LINK 创建的符号链接的字串
// REG_MULTI_SZ             多个字符串,用\0分隔,末尾为\0\0
// REG_NONE                 没定义值类型
// REG_QWORD                四字
// REG_QWORD_LITTLE_ENDIAN  四字小头模式
// REG_SZ                   普通字符串
 
 
class hReg {
    //不可实例化
    hReg () = delete;
    ~hReg () = delete;
    hReg (hReg&) = delete;
 
public:
    //创建注册表路径
    //main_key:   注册表根键
    //sub_key:    注册表路径
    //type:       键值类型
    //value:      值
    //value_size: 值长度(字节)
    static BOOL set_path (HKEY main_key, LPCTSTR sub_key, DWORD type, LPBYTE value, DWORD value_size) {
        return ERROR_SUCCESS == ::RegSetValueEx (main_key, sub_key, 0, type, value, value_size);
    }
 
    //创建注册表键值
    //main_key:   注册表根键
    //sub_key:    注册表路径
    //sub_key2:   键值名称
    //type:       键值类型
    //value:      值
    //value_size: 值长度(字节)
    static BOOL set_key (HKEY main_key, LPCTSTR sub_key, LPCTSTR sub_key2, DWORD type, LPBYTE value, DWORD value_size) {
        HKEY hKey;
        if (ERROR_SUCCESS != ::RegOpenKeyEx (main_key, sub_key, 0, KEY_WRITE, &hKey)) return FALSE;
        BOOL bRet = ERROR_SUCCESS == ::RegSetValueEx (hKey, sub_key2, 0, type, value, value_size);
        ::RegCloseKey (hKey);
        return bRet;
    }
 
    //获取注册表路径键值
    //main_key:   注册表根键
    //sub_key:    注册表路径
    //value:      值
    //value_size: 值长度(字节)
    static BOOL get_path_value (HKEY main_key, LPCTSTR sub_key, LPBYTE value, DWORD &value_size) {
        return ERROR_SUCCESS == ::RegQueryValueEx (main_key, sub_key, NULL, NULL, value, &value_size);
    }
 
    //获取注册表路径键值
    //main_key:   注册表根键
    //sub_key:    注册表路径
    //sub_key2:   键值名称
    //value:      值
    //value_size: 值长度(字节)
    static BOOL get_key_value (HKEY main_key, LPCTSTR sub_key, LPCTSTR sub_key2, LPBYTE value, DWORD &value_size) {
        HKEY hKey;
        if (ERROR_SUCCESS != ::RegOpenKeyEx (main_key, sub_key, 0, KEY_READ, &hKey)) return FALSE;
        BOOL bRet = ERROR_SUCCESS == ::RegQueryValueEx (hKey, sub_key2, NULL, NULL, value, &value_size);
        ::RegCloseKey (hKey);
        return bRet;
    }
 
    //删除注册表路径
    //main_key:   注册表根键
    //sub_key:    注册表路径
    static BOOL delete_path (HKEY main_key, LPCTSTR sub_key) {
        return ERROR_SUCCESS == ::RegDeleteKey (main_key, sub_key);
    }
 
    //删除注册表键值
    //main_key:   注册表根键
    //sub_key:    注册表路径
    //sub_key2:   注册表路径
    static BOOL delete_key (HKEY main_key, LPCTSTR sub_key, LPCTSTR sub_key2) {
        HKEY hKey;
        if (ERROR_SUCCESS != ::RegOpenKeyEx (main_key, sub_key, 0, KEY_ALL_ACCESS, &hKey)) return FALSE;
        BOOL bRet = ERROR_SUCCESS == ::RegDeleteKey (hKey, sub_key2);
        ::RegCloseKey (hKey);
        return bRet;
    }
};
 
#endif //__HREG_HPP__

全部为静态函数,注上了比较完整的注释,另外函数名也较之前清晰,统一返回BOOL表示执行成功或失败。