办公室通过路由器上网,所以不能直接远程桌面登录到自己计算机上,办公室的人都想在宿舍登录到自己的计算机上工作学习,所以可以简单的将路由器的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 “远程桌面链接端口修改器\[email protected]”,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))

这里是最终程序的截图,[下载这个程序]