辦公室通過路由器上網,所以不能直接遠程桌面登錄到自己計算機上,辦公室的人都想在宿舍登錄到自己的計算機上工作學習,所以可以簡單的將路由器的3389端口(windows遠程桌面默認使用3389端口)映射到自己的IP上,同時修改其他人計算機的遠程桌面端口,然后再相應的將路由器端口映射到自己的IP上即可。
修改遠程桌面端口需要修改注冊表中的兩個值:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp]
"PortNumber"=dword:00000d3d
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\Wds\rdpwd\Tds\tcp]
"PortNumber"=dword:00000d3d
修改兩個值,十進制是0-65535,雙字十六進制是0x00000000-0x0000FFFF,推薦修改為1024以上。
如何使用windows api編寫一個小程序來修改端口呢?接下來就詳細的講講這個程序應該如何實現,另外在討論一下如何使用windows api編寫簡單的windows程序。
下載開源的windows api集成開發環境Code::Blocks (訪問Code::Blocks主頁)
建議下載集成mingw的CodeBlocks,這樣就不用單獨下載安裝mingw了,如果不知道什么是mingw,趕緊google一下看看吧。配置好開發環境后,就可以開始下一步啦。
啟動Code::Blocks,然后新建一個Win32 GUI Project,這樣IDE會自動構建一個對話框,而且程序的基本結構也就構造好了。程序的入口就是WinMain函數,然后就可以在這個基礎之上編寫我們的程序了。
先確定這個程序有幾個窗口,然后修改resource.rc文件,資料都可以去MSDN查找

resource.rc
1
#include "resource.h"
2
3
DLG_MAIN DIALOGEX 6,6,269,131
4
STYLE 0x90CC0800
5
CAPTION "遠程桌面連接端口修改器"
6
FONT 8,"MS Sans Serif",0,0
7
BEGIN
8
CONTROL "",IDC_EDT,"Edit",0x50010000,72,51,170,13,0x00000200
9
CONTROL "十進制(&D)",IDC_RBN_D,"Button",0x50010009,20,81,54,9
10
CONTROL "十六進制(&H)",IDC_RBN_H,"Button",0x50010009,90,81,60,9
11
CONTROL "二進制(&B)",IDC_RBN_B,"Button",0x50010009,164,81,54,9
12
CONTROL "修改(&E)",IDC_BTN_E,"Button",0x50010000,14,107,54,13
13
CONTROL "還原(&B)",IDC_BTN_B,"Button",0x50010000,70,107,54,13
14
CONTROL "關于(&A)",IDC_BTN_A,"Button",0x50010000,126,107,54,13
15
CONTROL "退出(&Q)",IDC_BTN_Q,"Button",0x50010000,198,107,54,13
16
CONTROL "遠程桌面端口",IDC_STC,"Static",0x50000000,16,53,52,9
17
CONTROL "基數",IDC_GRP,"Button",0x50000007,14,70,228,24
18
CONTROL "#1013",IDC_IMG,"Static",0x5000020E,0,0,271,44
19
END
20
ICON_LOH ICON DISCARDABLE "rd.ico"
21
BMP_HEAD BITMAP DISCARDABLE "head.bmp"
22
23
IDD_DLG_ABOUT DIALOGEX 55,25,151,55
24
CAPTION "關于"
25
FONT 8,"MS Sans Serif",0,0
26
STYLE 0x90CC0000
27
BEGIN
28
CONTROL "#1012",IDC_IMG_ABOUT,"Static",0x50000203,14,11,20,19
29
CONTROL "遠程桌面鏈接端口修改器\nloh.wong@qq.com",IDC_STC_ABOUT,"Static",0x50000000,42,11,94,20
30
CONTROL "確定",IDC_BTN_ABOUT,"Button",0x50010000,106,38,40,13
31
END
32
resource.rc文件很簡單,包括兩個對話框,同時對話框里包括了一些簡單的控件。
修改resource.h文件,在其中添加一些控件的預定義

resource.h
1
#include <windows.h>
2
3
// ID of Main Dialog
4
#define DLG_MAIN 1000
5
6
// ID of Button Controls
7
#define IDC_GRP 1003
8
#define IDC_STC 1001
9
#define IDC_EDT 1002
10
#define IDC_RBN_H 1004
11
#define IDC_RBN_D 1005
12
#define IDC_BTN_E 1006
13
#define IDC_BTN_B 1007
14
#define IDC_BTN_Q 1008
15
#define IDC_BTN_A 1009
16
#define IDC_IMG 1010
17
#define IDC_RBN_B 1011
18
#define ICON_LOH 1012
19
#define BMP_HEAD 1013
20
21
//About Dialog
22
#define IDD_DLG_ABOUT 1017
23
#define IDC_STC_ABOUT 1014
24
#define IDC_BTN_ABOUT 1015
25
#define IDC_IMG_ABOUT 1016
26
編寫一些簡單的工具函數,主要實現2進制、10進制和16進制之間的相互轉換,和一些輸入的校驗。這個程序做的不是很完善,沒有校驗一些輸入數據。
這里是utils.h文件(H代表16進制,D代表10進制,B代表2進制)

utils.h
1
#ifndef UTILS_H_INCLUDED
2
#define UTILS_H_INCLUDED
3
4
#define H 16
5
#define D 10
6
#define B 2
7
8
#define RD_FALSE 0
9
#define RD_TRUE 1
10
11
/**//*格式轉換*/
12
char * strReverse(char *);
13
char * DtoDstr(int);
14
int CommontoD(char *, int);
15
16
char * HtoD(char *);
17
char * BtoD(char *);
18
19
char * HtoB(char *);
20
char * DtoB(char *);
21
22
char * BtoH(char *);
23
char * DtoH(char *);
24
25
/**//*格式檢查*/
26
int HFormatCheck(char *);
27
int BFormatCheck(char *);
28
int DFormatCheck(char *);
29
30
#endif // UTILS_H_INCLUDED
31
這里是utils.c文件

utils.c
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <string.h>
4
#include <math.h>
5
#include "utils.h"
6
7
//字符串逆序
8
char * strReverse(char *str)
9

{
10
int i,j,len = strlen(str);
11
char * res = (char*)malloc(len + 1);
12
memset(res, 0, len + 1);
13
for(i = len - 1, j = 0; i >= 0; i --, j ++)
{
14
res[j] = str[i];
15
}
16
return res;
17
}
18
19
//2,16進制轉10進制
20
int CommontoD(char *pC, int factor)
21

{
22
pC = strReverse(pC);
23
int d_res = 0;
24
int d_num = 0;
25
int i;
26
for(i = strlen(pC) - 1; i >= 0; i --)
27
{
28
if(pC[i] >= '0' && pC[i] <= '9')
{
29
d_num = pC[i] - '0';
30
}
31
if(pC[i] >= 'a' && pC[i] <= 'f')
{
32
d_num = pC[i] - 87;
33
}
34
if(pC[i] >= 'A' && pC[i] <= 'F')
{
35
d_num = pC[i] - 55;
36
}
37
d_res += d_num * pow(factor, i);
38
}
39
return d_res;
40
}
41
42
//將10進制數轉為字符串
43
char * DtoDstr(int d_num)
44

{
45
char *d_str = (char*)malloc(6);
46
memset(d_str,0,6);
47
int i = 0;
48
while(d_num > 0)
49
{
50
d_str[i++] = (d_num % 10) + '0';
51
d_num /= 10;
52
}
53
return strReverse(d_str);
54
}
55
//二進制到十進制
56
char * BtoD(char *pB)
57

{
58
return DtoDstr(CommontoD(pB, B));
59
}
60
61
//十六進制到十進制
62
char * HtoD(char *pH)
63

{
64
return DtoDstr(CommontoD(pH, H));
65
}
66
67
68
//十進制到二進制
69
char * DtoB(char *pD)
70

{
71
//65535用16個1表示
72
//開17個就夠了
73
char *b_str = (char*)malloc(17);
74
memset(b_str,0,17);
75
int d_num = atoi(pD);
76
int i = 0;
77
while(d_num > 0)
{
78
b_str[i++] = (d_num % 2) + '0';
79
d_num /= 2;
80
}
81
return strReverse(b_str);
82
}
83
84
//十六進制轉二進制
85
char * HtoB(char *pH)
86

{
87
return DtoB(HtoD(pH));
88
}
89
90
//十進制到十六進制
91
char * DtoH(char *pD)
92

{
93
//65535用4個f表示
94
//開5個就夠了
95
char *h_str = (char*)malloc(5);
96
memset(h_str,0,5);
97
int d_num = atoi(pD);
98
int bit;
99
int i = 0;
100
while(d_num > 0)
{
101
bit = d_num % 16;
102
if(bit >= 0 && bit <= 9)
{
103
h_str[i++] = bit + '0';
104
}
105
else
{
106
h_str[i++] = bit + 87;
107
}
108
d_num /= 16;
109
}
110
return strReverse(h_str);
111
}
112
113
//二進制轉十六進制
114
char * BtoH(char *pB)
115

{
116
return DtoH(BtoD(pB));
117
}
118
119
//檢查16進制數是否合法
120
int HFormatCheck(char *pH)
121

{
122
if(pH == NULL)
{
123
return RD_FALSE;
124
}
125
126
int len = strlen(pH);
127
int i;
128
for(i = 0; i < len; i ++)
129
{
130
if(!((pH[i] >= '0' && pH[i] <= '9') || (pH[i] >= 'a' && pH[i] <= 'f') || (pH[i] >= 'A' && pH[i] <= 'F') ))
131
{
132
return RD_FALSE;
133
}
134
}
135
return RD_TRUE;
136
}
137
//檢查2進制數是否合法
138
int BFormatCheck(char *pH)
139

{
140
if(pH == NULL)
{
141
return RD_FALSE;
142
}
143
144
int len = strlen(pH);
145
int i;
146
for(i = 0; i < len; i ++)
147
{
148
if(!(pH[i] >= '0' && pH[i] <= '1'))
149
{
150
return RD_FALSE;
151
}
152
}
153
return RD_TRUE;
154
}
155
156
//檢查10進制數是否合法
157
int DFormatCheck(char *pH)
158

{
159
if(pH == NULL)
{
160
return RD_FALSE;
161
}
162
163
int len = strlen(pH);
164
int i;
165
for(i = 0; i < len; i ++)
166
{
167
if(!(pH[i] >= '0' && pH[i] <= '9'))
168
{
169
return RD_FALSE;
170
}
171
}
172
return RD_TRUE;
173
}
174
175
176
最后是主程序main.c

main.c
1
#include <windows.h>
2
#include <stdio.h>
3
#include <stdlib.h>
4
5
#include "utils.h"
6
#include "resource.h"
7
8
HINSTANCE hInst;
9
HICON hIcon;
10
int id_pre_checked;
11
int port;
12
char *buf;
13
14
//兩個注冊表
15
HKEY winstations;
16
HKEY wds;
17
18
//獲得十進制的數
19
int GetPortNumber(char *port, int IDC)
20

{
21
//char * res;
22
if(IDC == IDC_RBN_D)
23
{
24
return atoi(port);
25
}
26
if(IDC == IDC_RBN_H)
27
{
28
return atoi(HtoD(port));
29
}
30
if(IDC == IDC_RBN_B)
31
{
32
return atoi(BtoD(port));
33
}
34
return -1;
35
}
36
37
//關于窗口
38
BOOL CALLBACK AboutDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
39

{
40
switch(uMsg)
41
{
42
case WM_INITDIALOG:
43
SendMessage(hwndDlg,WM_SETICON,ICON_BIG,(LPARAM)hIcon);
44
//SendMessage(hwndDlg,WM_SETICON,ICON_SMALL,(LPARAM)hIcon);
45
return TRUE;
46
case WM_CLOSE:
47
EndDialog(hwndDlg, 0);
48
return TRUE;
49
50
case WM_COMMAND:
51
switch(LOWORD(wParam))
52
{
53
case IDC_BTN_ABOUT:
54
EndDialog(hwndDlg, 0);
55
return TRUE;
56
}
57
}
58
return FALSE;
59
}
60
61
//主窗口
62
BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
63

{
64
switch(uMsg)
65
{
66
case WM_INITDIALOG:
67
//設置十進制是選中狀態
68
CheckRadioButton(hwndDlg,IDC_RBN_D,IDC_RBN_B,IDC_RBN_D);
69
id_pre_checked = IDC_RBN_D;
70
buf = (char *)malloc(20);
71
72
//打開注冊表
73
RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\Wds\\rdpwd\\Tds\\tcp",0,KEY_ALL_ACCESS,&wds);
74
RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\WinStations\\RDP-Tcp",0,KEY_ALL_ACCESS,&winstations);
75
76
//讀取注冊表的值
77
DWORD value = 0;
78
DWORD dwType = REG_DWORD;
79
DWORD dwSize = sizeof(DWORD);
80
RegQueryValueEx(wds,"PortNumber",NULL,&dwType,(LPBYTE)&value, &dwSize);
81
82
SetDlgItemText(hwndDlg,IDC_EDT,DtoDstr(value));
83
84
//加載圖標
85
hIcon = LoadIcon(hInst,(LPCTSTR)ICON_LOH);
86
SendMessage(hwndDlg,WM_SETICON,ICON_BIG,(LPARAM)hIcon);
87
//SendMessage(hwndDlg,WM_SETICON,ICON_SMALL,(LPARAM)hIcon);
88
return TRUE;
89
90
case WM_CLOSE:
91
EndDialog(hwndDlg, 0);
92
RegCloseKey(wds);
93
RegCloseKey(winstations);
94
return TRUE;
95
96
case WM_COMMAND:
97
switch(LOWORD(wParam))
98
{
99
case IDC_BTN_Q:
100
EndDialog(hwndDlg, 0);
101
return TRUE;
102
103
case IDC_BTN_E:
104
memset(buf,0,20);
105
GetDlgItemText(hwndDlg,IDC_EDT,buf,19);
106
port = GetPortNumber(buf,id_pre_checked);
107
if(RegSetValueEx(wds,"PortNumber",0,REG_DWORD,(LPBYTE)&port, sizeof(DWORD)) || RegSetValueEx(winstations,"PortNumber",0,REG_DWORD,(LPBYTE)&port, sizeof(DWORD)))
108
{
109
printf("Could not set the event message file.");
110
}
111
return TRUE;
112
113
case IDC_BTN_B:
114
port = 3389;
115
if(RegSetValueEx(wds,"PortNumber",0,REG_DWORD,(LPBYTE)&port, sizeof(DWORD)) || RegSetValueEx(winstations,"PortNumber",0,REG_DWORD,(LPBYTE)&port, sizeof(DWORD)))
116
{
117
printf("Could not set the event message file.");
118
}
119
SetDlgItemText(hwndDlg,IDC_EDT,DtoDstr(port));
120
return TRUE;
121
122
case IDC_BTN_A:
123
//MessageBox(hwndDlg, "關于!", "提示信息", MB_ICONINFORMATION);
124
return DialogBox(hInst, MAKEINTRESOURCE(IDD_DLG_ABOUT), hwndDlg, AboutDialogProc);
125
//return TRUE;
126
127
case IDC_RBN_D:
128
memset(buf,0,20);
129
GetDlgItemText(hwndDlg,IDC_EDT,buf,19);
130
if(id_pre_checked == IDC_RBN_H)
131
{
132
SetDlgItemText(hwndDlg, IDC_EDT, HtoD(buf));
133
}
134
if(id_pre_checked == IDC_RBN_B)
135
{
136
SetDlgItemText(hwndDlg,IDC_EDT,BtoD(buf));
137
}
138
139
id_pre_checked = IDC_RBN_D;
140
return TRUE;
141
142
case IDC_RBN_H:
143
memset(buf,0,20);
144
GetDlgItemText(hwndDlg,IDC_EDT,buf,19);
145
if(id_pre_checked == IDC_RBN_D)
146
{
147
SetDlgItemText(hwndDlg, IDC_EDT, DtoH(buf));
148
}
149
if(id_pre_checked == IDC_RBN_B)
150
{
151
SetDlgItemText(hwndDlg,IDC_EDT,BtoH(buf));
152
}
153
id_pre_checked = IDC_RBN_H;
154
return TRUE;
155
156
case IDC_RBN_B:
157
memset(buf,0,20);
158
GetDlgItemText(hwndDlg,IDC_EDT,buf,19);
159
if(id_pre_checked == IDC_RBN_H)
160
{
161
SetDlgItemText(hwndDlg, IDC_EDT, HtoB(buf));
162
}
163
if(id_pre_checked == IDC_RBN_D)
164
{
165
SetDlgItemText(hwndDlg,IDC_EDT,DtoB(buf));
166
}
167
id_pre_checked = IDC_RBN_B;
168
return TRUE;
169
}
170
}
171
return FALSE;
172
}
173
174
175
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
176

{
177
hInst = hInstance;
178
179
// The user interface is a modal dialog box
180
return DialogBox(hInstance, MAKEINTRESOURCE(DLG_MAIN), NULL, DialogProc);
181
}
182
關于使用windows api操作注冊表需要注意的是:
1.先打開注冊表,獲得注冊表的句柄,代碼為:
//讀取注冊表的值
DWORD value = 0;
DWORD dwType = REG_DWORD;
DWORD dwSize = sizeof(DWORD);
RegQueryValueEx(wds,"PortNumber",NULL,&dwType,(LPBYTE)&value, &dwSize);
int port = 3389;






RegSetValueEx(wds,"PortNumber",0,REG_DWORD,(LPBYTE)&port, sizeof(DWORD))
修改遠程桌面端口需要修改注冊表中的兩個值:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp]
"PortNumber"=dword:00000d3d
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\Wds\rdpwd\Tds\tcp]
"PortNumber"=dword:00000d3d
修改兩個值,十進制是0-65535,雙字十六進制是0x00000000-0x0000FFFF,推薦修改為1024以上。
如何使用windows api編寫一個小程序來修改端口呢?接下來就詳細的講講這個程序應該如何實現,另外在討論一下如何使用windows api編寫簡單的windows程序。
下載開源的windows api集成開發環境Code::Blocks (訪問Code::Blocks主頁)
建議下載集成mingw的CodeBlocks,這樣就不用單獨下載安裝mingw了,如果不知道什么是mingw,趕緊google一下看看吧。配置好開發環境后,就可以開始下一步啦。
啟動Code::Blocks,然后新建一個Win32 GUI Project,這樣IDE會自動構建一個對話框,而且程序的基本結構也就構造好了。程序的入口就是WinMain函數,然后就可以在這個基礎之上編寫我們的程序了。
先確定這個程序有幾個窗口,然后修改resource.rc文件,資料都可以去MSDN查找


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

resource.rc文件很簡單,包括兩個對話框,同時對話框里包括了一些簡單的控件。
修改resource.h文件,在其中添加一些控件的預定義


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

編寫一些簡單的工具函數,主要實現2進制、10進制和16進制之間的相互轉換,和一些輸入的校驗。這個程序做的不是很完善,沒有校驗一些輸入數據。
這里是utils.h文件(H代表16進制,D代表10進制,B代表2進制)


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

這里是utils.c文件


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

最后是主程序main.c


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

關于使用windows api操作注冊表需要注意的是:
1.先打開注冊表,獲得注冊表的句柄,代碼為:
1 //打開注冊表
2 RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\Wds\\rdpwd\\Tds\\tcp",0,KEY_ALL_ACCESS,&wds);
3 RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\WinStations\\RDP-Tcp",0,KEY_ALL_ACCESS,&winstations);
2 RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\Wds\\rdpwd\\Tds\\tcp",0,KEY_ALL_ACCESS,&wds);
3 RegOpenKeyEx(HKEY_LOCAL_MACHINE,"SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\WinStations\\RDP-Tcp",0,KEY_ALL_ACCESS,&winstations);
2.然后在讀入注冊表的值或是寫入注冊表的值
例如讀取PortNumber的值到變量value中:





例如寫值到PortNumber中:








這里是最終程序的截圖,[下載這個程序]