Click here to Skip to main content
Click here to Skip to main content

Desktop Sharing using RDP APIs and Socket

, 13 Feb 2014
Rate this:
Please Sign up or sign in to vote.
You can share a peer's desktop with any others using this software

Introduction

In the situation of an e-classroom, the teacher might want to share one specified student's desktop with a group of others, another specified student's desktop to another group, or his/her own desktop with a specified group of students, so that the group of students knows how to operate on some problem during studying.

And the teacher might also want to test if some student really understands how to operate, so that he can specify the student to be a controller who is granted with the privilege of controlling the desktop of the sharer.

Another situation is that the teacher wants to make sure that the students are doing what he/she assigned them to do, thus he/she can monitor the desktops of a specified group of students.

Environment

Develop environment: VS2012 on Windows 8

Run environment: Windows 7 or later editions, Windows 2012 or later editions. Note that VC++11 runtime is required. Install it first if you didn't have it.

Background

The software is of server-client model using socket to control and transfer commands between server and clients. And in low level, the functionality of transferring desktops is through Microsoft's WDS APIs (http://msdn.microsoft.com/zh-cn/library/windows/desktop/aa373871(v=vs.85).aspx) using RDP.

As a matter of fact, as for the RDP server I referred to this link, and I even directly quoted the class "CMyRDPSessionEvents" to handle RDP events. To understand the codes, you need basic knowledge of COM. As for the RDP client, I referred to this link. The RDP client should be an ActiveX control, Microsoft has already provided such a control in MFC. Thank to the authors of the two articles.

Using the Code

1. Brief Introduction

This desktop share software is divided into two parts: the server side Control Center and the client Peer. In fact, each peer contains both RDP server as sharer and RDP client as viewer, meaning it has everything that is needed to share desktop and view other’s desktop. The Control Center only plays the role of controlling peers with socket commands.

2. Control Center

2.1 Architecture in general

"Control Center" is the name of the server side. Control Center is organized in three layers in logic. The bottom layer contains two classes derived from CSocket: CDoorSocket and CListenSock, which communicates with client and with socket. The mid layer is just one service class CService, providing basic socket services such as sending data and receiving data. This class servers the UI classes from upper layer, sending them messages when some socket commands or state strings come. It also has a list and a map to contain the sockets corresponding to the client. The top layer contains a lot of UI classes and some related helper classes. The UI classes are mainly dialog classes derived from CDialogEx.

2.2 Detail of CService

As mentioned above, the CService class mainly servers UI classes by providing socket services.

Main Methods
  • SockSend: used to send commands to the client wherever needed.
  • OnSockReceive: This method will be called once the sockets receive commands or reply to commands from clients. And it will take actions to change the state of the sockets in the map and/or send self-defined messages to corresponding classes according to different received strings. This method is like a message dispatcher.

This class also has a list and a map as its attributes. They are both used to store sockets connected to the clients. But why two containers? The situation is when a client is connected to the Control Center, a new instance of CDoorSocket will be created in method OnSockAccept, later when the socket sends a "logname" command along with a name identifying the client itself, the name-socket pair will be added to the map. And in later period only the entity in the map will be used and usually by the name as an id.

As far as the function of this class goes, the instance of it should be only, which means a singleton. Thus letting it be an attribute of the main dialog is far from enough, I make it an attribute of CControlCenterApp, so that any class can use it though the single "theApp".

Note that this class also has some pointers to CWnd. They are used to indicate where message will be sent in method OnSockReceive. Apparently, this is not a good design. And in order to pass some parameters while sending messages, I used the SendMessage function. It might have a bad influence on performance.

2.3 Design of UI

The software is an MFC Dialog project. Thus the user interfaces are sets of dialogs and controls on them. The main window is a dialog whose class is CControlCenterDlg , which contains such elements: three dialogs in the client area of the tab control, the static control in the left bottom corner and a corresponding hid "Hand Message" dialog and finally the static control representing number of online clients in the right bottom corner.

2.4 About the CPeerTreeDlg

This class might be the most complex one even though it is just a dialog containing a tree control. I want it to be a portable control so that I set the border of the dialog resource as "none".

The most basic function of it is to show a tree containing peers divided into different groups.

Note that there are two ways to initially construct the tree. The first way is through "BuildTree" method, firstly read the contents of a set of files from a directory into memory, in the form of a map<CString, list<CString>* >, whose first element is group name, while the second is the pointer to the list of peer names. The default directory is ".\\Group\\", and the files in it must have ".dat" extension. Each file represents a group, the file name is the group name, the content inside are peer names. Each peer name is in one row. After the data is loaded to the map, the tree nodes are created according to the map. Finally the memory of the map is freed. After all real groups showed, an "Unknown Group" will be added. This is how the tree in the "Manage Group" panel is constructed.

The second way is through "FilterTree" function. It filters an existing tree depending on whether the peer represented by the node is online or not. If the peer is online, it keeps the corresponding node, otherwise deletes it. The trees in the "create new session" dialog showed when you are creating a new broadcast session or a monitor session are constructed in this way.

2.5 Session list dialogs

In the "Broadcast Desktop" and the "Monitor Desktop", the CShareSessionDlg and the CMonitorSessionDlg are behind. I invented two different kinds of sessions, the first is the share session, used in CShareSessionDlg, which means broadcast a peer’s desktop to others in the same session, and the second is monitor session, used in CMonitorSessionDlg, which means monitoring some peers. And the classes "CShareSession" and "CMonitorSession" correspond to each respectively. And when you are about to create new share session, a dialog containing sharer to choose and viewers to choose from the trees is the UI the CShareSession. Here, in this situation, the CShareSession seems to be the "managed bean" of the dialog as well as the CMonitorSession. The dialogs showed up when creating sessions are modal dialog, before calling the DoModal, I pass an instance of the CShareSession or the CMonitorSession, in this way I can pass in data and let the dialog show, and after the DoModal returned, I can get the instance filled with new data from user input through the dialog. This is an important concept. However in the software I didn’t use this way to pass in data. Note that the concept of monitor session in code level is a little different from that on the UI where a monitor session has only one peer monitored.

3. Peer

3.1 Architecture

The architecture is like that of the Control Center. The bottom layer is the CDoorSocket, the mid layer is the CService class, the top layer is the CPeerDlg and the CViewerDlg. Much less complex. Something is different. The dialog corresponding to the CPeerDlg as the main dialog never shows up while the software is running. However, it handles events triggered by tray icon menu or sockets. The CService class provides three kinds of services: socket service, RDP service and system management service. The RDP service mainly includes start RDP service using StartRDPService and stop RDP service using StopRDPService. The system management service here is just install global mouse hook and keyboard hook using SetHook. In the SetHook function, I load a library called "GlobalHook" in which global mouse hook and key hook are installed.

3.2 RDP Service

This is the core of the software. Microsoft has provided APIs here, and I also referred to this link and this link, the two articles helped me a lot. And I even directly quoted two classes "CMyRDPSessionEvents" to provide event handle and "B" to transform a normal string to BSTR.

4. Command System

reply self-defined message classes
"sharer started" WM_MY_SHARERSTARTED CShareSessionDlg
"sharer not started" WM_MY_SHARERNOTSTARTED CShareSessionDlg
"sharer stopped" WM_MY_SHARERSTOPPED CShareSessionDlg
"sharer not stopped"
"viewer started"
"viewer not started"
"viewer stopped"
"viewer not stopped"
"monitor opened" WM_MY_MONITOROPENED CMonitorSessionDlg
"monitor not opened" WM_MY_MONITORNOTOPENED CMonitorSessionDlg
"monitor closed" WM_MY_MONITORCLOSED CMonitorSessionDlg
"monitor not closed"
client’s command "logname" WM_MY_LOGNAME CPeerTreeDlg CControlCenterDlg
socket close event WM_MY_SOCKCLOSE CPeerTreeDlg CShareSessionDlg CMonitorSessionDlg CControlCenterDlg
client’s command"hand up" WM_MY_HANDUP CControlCenterDlg CHandDlg

Commands sent from the server are listed below:

functionality command success reply failure reply
start RDP service "start sharer" sharer started ticket:+ticket string sharer not started
stop RDP service "stop sharer" sharer stopped sharer not stopped
let RDPViewer connect RDP sharer according to ticket "start viewer" + ticket string viewer started viewer not started
disconnect RDP "stop viewer" viewer stopped viewer not stopped
the same as start sharer "open monitor" monitor opened ticket:+ticket string monitor not opened
the same as stop sharer "close monitor" monitor closed monitor not closed
lock viewer "lock"
unlock viewer "unlock"
disable the "Exit program" menu item on client "config disable exit"
enable the "Exit program" menu item "config enable exit"
disconnect

Commands sent from the client (no reply from server expected):

functionality command
log on "logname"+name
electronic hand up "hand up"
disconnect

Note: White means nothing.

5. Language

In order to internationalize the software, multi-language is a problem. For providing editions of different languages, I transferred every string in the source code to the string table of the resource script. Thus all the language related resources are in the resource script. The default resource script is of Chinese. Collect the resources into another DLL project to build a resource-only DLL as an independent language package. More information can be found here.

Points of Interest

I needed to provide the software with different languages. The project type is MFC dialog project using VC++11. At the beginning, I created all the resources as Chinese edition, later I wanted an English edition, just put all the resource related files including the res directory, resource.h and targetver.h into another DLL project, compile and link you get a resource-only DLL. The system can decide which resource to use depending on the name the resource-only DLL and the system configuration. More details can be found here and here. It's really powerful.

History

This is the third edition finished on 20-1-2014.

Conclusion

I am new in developing MFC software. Although the technologies of the software can be concluded as RDP+Socket, it is not so easy for me. It also include a lot of other things such as configuration files, global hooks, resource internationalization, COM events, MFC DLLs and so on. If you have problems or other things to talk with me, email me at nuclear.sun@qq.com.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

nuclear_sun
Technical Lead student
China China
No Biography provided

Comments and Discussions

 
QuestionThank you for this demo PinmemberRickLeinecker16-Jul-14 6:16 
QuestionCan't read Chinese...sorry Pinmemberkoskeshkhar18-Feb-14 1:29 
QuestionAre you using blocking sockets? PinmemberVictor Nijegorodov17-Feb-14 23:10 
AnswerRe: Are you using blocking sockets? Pinprofessionalnuclear_sun18-Feb-14 2:18 
GeneralRe: Are you using blocking sockets? PinmemberVictor Nijegorodov18-Feb-14 4:34 
QuestionLink to project is an external site PinmvpCHill6013-Feb-14 2:01 
GeneralMy vote of 1 PinprofessionalMarco Bertschi13-Feb-14 0:34 
QuestionWhat exactly do you mean when you say "Using the Code?" PinmemberJohnWallis426-Feb-14 2:26 
AnswerRe: What exactly do you mean when you say "Using the Code?" Pinprofessionalnuclear_sun6-Feb-14 19:12 
GeneralRe: What exactly do you mean when you say "Using the Code?" PinmemberVictor Nijegorodov17-Feb-14 23:06 
GeneralRe: What exactly do you mean when you say "Using the Code?" Pinprofessionalnuclear_sun18-Feb-14 2:01 
GeneralRe: What exactly do you mean when you say "Using the Code?" PinmemberVictor Nijegorodov18-Feb-14 4:39 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140721.1 | Last Updated 13 Feb 2014
Article Copyright 2014 by nuclear_sun
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid