辦公室通過路由器上網,所以不能直接遠程桌面登錄到自己計算機上,辦公室的人都想在宿舍登錄到自己的計算機上工作學習,所以可以簡單的將路由器的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.先打開注冊表,獲得注冊表的句柄,代碼為:
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.然后在讀入注冊表的值或是寫入注冊表的值
例如讀取PortNumber的值到變量value中:
//讀取注冊表的值
DWORD value = 0;
DWORD dwType = REG_DWORD;
DWORD dwSize = sizeof(DWORD);
RegQueryValueEx(wds,"PortNumber",NULL,&dwType,(LPBYTE)&value, &dwSize);
例如寫值到PortNumber中:
int port = 3389;






RegSetValueEx(wds,"PortNumber",0,REG_DWORD,(LPBYTE)&port, sizeof(DWORD))
這里是最終程序的截圖,[下載這個程序]
